blob: 36bb01aabc0d98afc8c768cdf6b9ebb10926fb1b [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
17//Package adaptercore provides the utility for olt devices, flows and statistics
Phaneendra Manda4c62c802019-03-06 21:37:49 +053018package adaptercore
19
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "errors"
24 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040032 "google.golang.org/grpc/codes"
33
David Bainbridgef5879ca2019-12-13 21:17:54 +000034 backoff "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Scott Baker51290152019-10-24 14:23:20 -070037 "github.com/opencord/voltha-lib-go/v2/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Naga Manjunath7615e552019-10-11 22:35:47 +053039 "github.com/opencord/voltha-lib-go/v2/pkg/pmmetrics"
Girish Gowdru0c588b22019-04-23 23:24:56 -040040 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080041 "github.com/opencord/voltha-protos/v2/go/common"
42 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
43 of "github.com/opencord/voltha-protos/v2/go/openflow_13"
44 oop "github.com/opencord/voltha-protos/v2/go/openolt"
45 "github.com/opencord/voltha-protos/v2/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070046 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040047 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053048)
49
salmansiddiqui7ac62132019-08-22 03:58:50 +000050// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040051const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000052 MaxRetry = 10
53 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040054)
55
kdarapu381c6902019-07-31 18:23:16 +053056func init() {
57 _, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
58}
59
Phaneendra Manda4c62c802019-03-06 21:37:49 +053060//DeviceHandler will interact with the OLT device.
61type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070062 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070063 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040064 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070065 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053066 coreProxy adapterif.CoreProxy
67 AdapterProxy adapterif.AdapterProxy
68 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070069 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070070 exitChannel chan int
71 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053072 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070073 transitionMap *TransitionMap
74 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053075 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040076 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053077 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053078
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053079 discOnus sync.Map
80 onus sync.Map
81 portStats *OpenOltStatisticsMgr
82 metrics *pmmetrics.PmMetrics
83 stopCollector chan bool
84 stopHeartbeatCheck chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085}
86
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070090 deviceType string
91 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070092 onuID uint32
93 intfID uint32
94 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000095 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070096}
97
Naga Manjunath7615e552019-10-11 22:35:47 +053098var pmNames = []string{
99 "rx_bytes",
100 "rx_packets",
101 "rx_mcast_packets",
102 "rx_bcast_packets",
103 "tx_bytes",
104 "tx_packets",
105 "tx_mcast_packets",
106 "tx_bcast_packets",
107}
108
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 device.deviceType = deviceTp
114 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 device.onuID = onuID
116 device.intfID = intfID
117 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000118 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530120}
121
122//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530123func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700124 var dh DeviceHandler
125 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400126 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400127 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700129 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700130 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400131 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 dh.device = cloned
133 dh.openOLT = adapter
134 dh.exitChannel = make(chan int, 1)
135 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530136 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530137 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530138 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
cuilin20187b2a8c32019-03-26 19:52:28 -0700139 //TODO initialize the support classes.
140 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530141}
142
143// start save the device to the data model
144func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700145 dh.lockDevice.Lock()
146 defer dh.lockDevice.Unlock()
147 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
148 // Add the initial device to the local model
149 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530150}
151
152// stop stops the device dh. Not much to do for now
153func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 dh.lockDevice.Lock()
155 defer dh.lockDevice.Unlock()
156 log.Debug("stopping-device-agent")
157 dh.exitChannel <- 1
158 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530159}
160
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400161func macifyIP(ip net.IP) string {
162 if len(ip) > 0 {
163 oct1 := strconv.FormatInt(int64(ip[12]), 16)
164 oct2 := strconv.FormatInt(int64(ip[13]), 16)
165 oct3 := strconv.FormatInt(int64(ip[14]), 16)
166 oct4 := strconv.FormatInt(int64(ip[15]), 16)
167 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
168 }
169 return ""
170}
171
172func generateMacFromHost(host string) (string, error) {
173 var genmac string
174 var addr net.IP
175 var ips []string
176 var err error
177
178 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
179
180 if addr = net.ParseIP(host); addr == nil {
181 log.Debugw("looking-up-hostname", log.Fields{"host": host})
182
183 if ips, err = net.LookupHost(host); err == nil {
184 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
185 if addr = net.ParseIP(ips[0]); addr == nil {
186 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
187 return "", errors.New("unable-to-parse-ip")
188 }
189 genmac = macifyIP(addr)
190 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
191 return genmac, nil
192 }
193 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
194 return "", err
195 }
196
197 genmac = macifyIP(addr)
198 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
199 return genmac, nil
200}
201
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530202func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 slist := strings.Split(mac, ":")
204 result := make([]uint32, len(slist))
205 var err error
206 var tmp int64
207 for index, val := range slist {
208 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
209 return []uint32{1, 2, 3, 4, 5, 6}
210 }
211 result[index] = uint32(tmp)
212 }
213 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530214}
215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700216//GetportLabel returns the label for the NNI and the PON port based on port number and port type
manikkaraj kbf256be2019-03-25 00:13:48 +0530217func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530218
Girish Gowdru0c588b22019-04-23 23:24:56 -0400219 if portType == voltha.Port_ETHERNET_NNI {
220 return fmt.Sprintf("nni-%d", portNum)
221 } else if portType == voltha.Port_PON_OLT {
222 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700223 } else if portType == voltha.Port_ETHERNET_UNI {
224 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400225 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 }
227 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 var operStatus common.OperStatus_OperStatus
232 if state == "up" {
233 operStatus = voltha.OperStatus_ACTIVE
234 } else {
235 operStatus = voltha.OperStatus_DISCOVERED
236 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400238 label := GetportLabel(portNum, portType)
239 if len(label) == 0 {
240 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
241 return
242 }
243 // Now create Port
244 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700245 PortNo: portNum,
246 Label: label,
247 Type: portType,
248 OperStatus: operStatus,
249 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400250 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700252 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
253 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400254 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530255}
256
257// readIndications to read the indications from the OLT device
258func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400259 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400260 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700261 if err != nil {
262 log.Errorw("Failed to read indications", log.Fields{"err": err})
263 return
264 }
265 if indications == nil {
266 log.Errorw("Indications is nil", log.Fields{})
267 return
268 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400269 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400271 if err != nil || device == nil {
272 /*TODO: needs to handle error scenarios */
273 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700274 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400275 }
276 // When the device is in DISABLED and Adapter container restarts, we need to
277 // rebuild the locally maintained admin state.
278 if device.AdminState == voltha.AdminState_DISABLED {
279 dh.lockDevice.Lock()
280 dh.adminState = "down"
281 dh.lockDevice.Unlock()
282 }
283
David Bainbridgef5879ca2019-12-13 21:17:54 +0000284 // Create an exponential backoff around re-enabling indications. The
285 // maximum elapsed time for the back off is set to 0 so that we will
286 // continue to retry. The max interval defaults to 1m, but is set
287 // here for code clarity
288 indicationBackoff := backoff.NewExponentialBackOff()
289 indicationBackoff.MaxElapsedTime = 0
290 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 for {
292 indication, err := indications.Recv()
293 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530294 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000295 // Use an exponential back off to prevent getting into a tight loop
296 duration := indicationBackoff.NextBackOff()
297 if duration == backoff.Stop {
298 // If we reach a maximum then warn and reset the backoff
299 // timer and keep attempting.
300 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
301 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
302 indicationBackoff.Reset()
303 }
304 time.Sleep(indicationBackoff.NextBackOff())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530305 indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
306 if err != nil {
307 log.Errorw("Failed to read indications", log.Fields{"err": err})
308 return
309 }
310 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 }
312 if err != nil {
313 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400314 if dh.adminState == "deleted" {
315 log.Debug("Device deleted stoping the read indication thread")
316 break
317 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400318 dh.transitionMap.Handle(DeviceDownInd)
319 dh.transitionMap.Handle(DeviceInit)
320 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000322 // Reset backoff if we have a successful receive
323 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400324 dh.lockDevice.RLock()
325 adminState := dh.adminState
326 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400327 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400328 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530329
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +0530330 log.Infow("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400331 continue
332 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700333 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530334
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 }
336}
337
338func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000339 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000340 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700341 dh.transitionMap.Handle(DeviceUpInd)
342 } else if oltIndication.OperState == "down" {
343 dh.transitionMap.Handle(DeviceDownInd)
344 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000345 // Send or clear Alarm
346 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700347}
348
349func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400350 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700351 switch indication.Data.(type) {
352 case *oop.Indication_OltInd:
353 dh.handleOltIndication(indication.GetOltInd())
354 case *oop.Indication_IntfInd:
355 intfInd := indication.GetIntfInd()
356 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
357 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
358 case *oop.Indication_IntfOperInd:
359 intfOperInd := indication.GetIntfOperInd()
360 if intfOperInd.GetType() == "nni" {
361 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530362 dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700363 } else if intfOperInd.GetType() == "pon" {
364 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
365 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000366 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700367 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
369 case *oop.Indication_OnuDiscInd:
370 onuDiscInd := indication.GetOnuDiscInd()
371 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400373 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700374 case *oop.Indication_OnuInd:
375 onuInd := indication.GetOnuInd()
376 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
377 go dh.onuIndication(onuInd)
378 case *oop.Indication_OmciInd:
379 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700380 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 -0400381 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700382 case *oop.Indication_PktInd:
383 pktInd := indication.GetPktInd()
384 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
385 go dh.handlePacketIndication(pktInd)
386 case *oop.Indication_PortStats:
387 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530388 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700389 case *oop.Indication_FlowStats:
390 flowStats := indication.GetFlowStats()
391 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
392 case *oop.Indication_AlarmInd:
393 alarmInd := indication.GetAlarmInd()
394 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530395 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700396 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530397}
398
399// doStateUp handle the olt up indication and update to voltha core
400func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400401 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700402 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400403 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700404 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 -0400405 return err
406 }
407 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530408}
409
410// doStateDown handle the olt down indication
411func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700412 dh.lockDevice.Lock()
413 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400414 log.Debug("do-state-down-start")
415
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700416 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400417 if err != nil || device == nil {
418 /*TODO: needs to handle error scenarios */
419 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400421 }
422
423 cloned := proto.Clone(device).(*voltha.Device)
424 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700425 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
426 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
427 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400428 }
429
430 //Update the device oper state and connection status
431 cloned.OperStatus = voltha.OperStatus_UNKNOWN
432 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
433 dh.device = cloned
434
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700435 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
436 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
437 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400438 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400439
440 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400442 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700443 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400444 return err
445 }
446 for _, onuDevice := range onuDevices.Items {
447
448 // Update onu state as down in onu adapter
449 onuInd := oop.OnuIndication{}
450 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700451 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
452 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
453 if er != nil {
454 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
455 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700456 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700457 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400458 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700459 /* Discovered ONUs entries need to be cleared , since after OLT
460 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530461 dh.discOnus = sync.Map{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700462 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700463 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530464}
465
466// doStateInit dial the grpc before going to init state
467func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400468 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400469 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400470 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400472 return err
473 }
474 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530475}
476
477// postInit create olt client instance to invoke RPC on the olt device
478func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400479 dh.Client = oop.NewOpenoltClient(dh.clientCon)
480 dh.transitionMap.Handle(GrpcConnected)
481 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530482}
483
484// doStateConnected get the device info and update to voltha core
485func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400486 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400487
488 // Case where OLT is disabled and then rebooted.
489 if dh.adminState == "down" {
490 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400492 if err != nil || device == nil {
493 /*TODO: needs to handle error scenarios */
494 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
495 }
496
497 cloned := proto.Clone(device).(*voltha.Device)
498 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
499 cloned.OperStatus = voltha.OperStatus_UNKNOWN
500 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
502 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400503 }
504
Chaitrashree G S44124192019-08-07 20:21:36 -0400505 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400506 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
507 if err != nil {
508 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
509 }
510
511 // Start reading indications
512 go dh.readIndications()
513 return nil
514 }
515
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400516 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400518 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 return err
520 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400521
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400523 if err != nil || device == nil {
524 /*TODO: needs to handle error scenarios */
525 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400527 }
528 cloned := proto.Clone(device).(*voltha.Device)
529 // Update the all ports (if available) on that device to ACTIVE.
530 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
532 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400533 return err
534 }
535
Girish Gowdru0c588b22019-04-23 23:24:56 -0400536 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
537 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400539 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400541 }
542 // Instantiate flow manager
543 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
544 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700545 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400546 }
547 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400548 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400549 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530550 // Stats config for new device
551 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530552
cuilin20187b2a8c32019-03-26 19:52:28 -0700553 // Start reading indications
554 go dh.readIndications()
555 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530556}
557
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400558func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
559 var err error
560 var deviceInfo *oop.DeviceInfo
561
562 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
563
564 if err != nil {
565 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
566 return nil, err
567 }
568 if deviceInfo == nil {
569 log.Errorw("Device info is nil", log.Fields{})
570 return nil, errors.New("failed to get device info from OLT")
571 }
572
573 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
574 dh.device.Root = true
575 dh.device.Vendor = deviceInfo.Vendor
576 dh.device.Model = deviceInfo.Model
577 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
578 dh.device.HardwareVersion = deviceInfo.HardwareVersion
579 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
580
581 if deviceInfo.DeviceId == "" {
582 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
583 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
584 genmac, err := generateMacFromHost(host)
585 if err != nil {
586 return nil, err
587 }
588 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
589 dh.device.MacAddress = genmac
590 } else {
591 dh.device.MacAddress = deviceInfo.DeviceId
592 }
593
594 // Synchronous call to update device - this method is run in its own go routine
595 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
596 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
597 return nil, err
598 }
599
600 return deviceInfo, nil
601}
602
Naga Manjunath7615e552019-10-11 22:35:47 +0530603func startCollector(dh *DeviceHandler) {
604 // Initial delay for OLT initialization
605 time.Sleep(1 * time.Minute)
606 log.Debugf("Starting-Collector")
607 context := make(map[string]string)
608 for {
609 select {
610 case <-dh.stopCollector:
611 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
612 return
613 default:
614 freq := dh.metrics.ToPmConfigs().DefaultFreq
615 time.Sleep(time.Duration(freq) * time.Second)
616 context["oltid"] = dh.deviceID
617 context["devicetype"] = dh.deviceType
618 // NNI Stats
619 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
620 log.Debugf("Collect-NNI-Metrics %v", cmnni)
621 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
622 log.Debugf("Publish-NNI-Metrics")
623 // PON Stats
624 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
625 for i := uint32(0); i < NumPonPORTS; i++ {
626 cmpon := dh.portStats.collectPONMetrics(i)
627 log.Debugf("Collect-PON-Metrics %v", cmpon)
628
629 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
630 log.Debugf("Publish-PON-Metrics")
631 }
632 }
633 }
634}
635
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530637func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400640 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530641
642 // Now, set the initial PM configuration for that device
643 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
644 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
645 }
646
647 go startCollector(dh)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530648 go startHeartbeatCheck(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530649}
650
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530652func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700653 return &ic.SwitchCapability{
654 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530655 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700656 HwDesc: "open_pon",
657 SwDesc: "open_pon",
658 SerialNum: dh.device.SerialNumber,
659 },
660 SwitchFeatures: &of.OfpSwitchFeatures{
661 NBuffers: 256,
662 NTables: 2,
663 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
664 of.OfpCapabilities_OFPC_TABLE_STATS |
665 of.OfpCapabilities_OFPC_PORT_STATS |
666 of.OfpCapabilities_OFPC_GROUP_STATS),
667 },
668 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530669}
670
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530672func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700674 return &ic.PortCapability{
675 Port: &voltha.LogicalPort{
676 OfpPort: &of.OfpPort{
677 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
678 Config: 0,
679 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 Curr: capacity,
681 Advertised: capacity,
682 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700683 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
684 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
685 },
686 DeviceId: dh.device.Id,
687 DevicePortNo: uint32(portNo),
688 },
689 }, nil
690}
691
William Kurkianff524662019-08-20 10:34:30 -0400692func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700694 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 var deviceID string
696 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700697
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700698 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530699
700 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
701
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
703 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700704 kwargs := make(map[string]interface{})
705 kwargs["onu_id"] = omciInd.OnuId
706 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700707
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
709 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400710 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
711 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700712 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 deviceType = onuDevice.Type
714 deviceID = onuDevice.Id
715 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
716 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530717 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700718 } else {
719 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530721 deviceType = onuInCache.(*OnuDevice).deviceType
722 deviceID = onuInCache.(*OnuDevice).deviceID
723 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700724 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700725
726 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
727 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
728 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400730 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
731 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700732 }
William Kurkianff524662019-08-20 10:34:30 -0400733 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530734}
735
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736//ProcessInterAdapterMessage sends the proxied messages to the target device
737// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
738// is meant, and then send the unmarshalled omci message to this onu
739func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
740 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700741 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700743 fromTopic := msg.Header.FromTopic
744 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 toDeviceID := msg.Header.ToDeviceId
746 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700747
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700749
750 msgBody := msg.GetBody()
751
752 omciMsg := &ic.InterAdapterOmciMessage{}
753 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
754 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
755 return err
756 }
757
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700758 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
760 if err != nil {
761 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700762 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700763 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
765 dh.sendProxiedMessage(onuDevice, omciMsg)
766
cuilin20187b2a8c32019-03-26 19:52:28 -0700767 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 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 -0700769 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700770 }
771
772 } else {
773 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
774 }
775 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530776}
777
cuilin20187b2a8c32019-03-26 19:52:28 -0700778func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 var intfID uint32
780 var onuID uint32
781 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700782 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 intfID = onuDevice.ProxyAddress.GetChannelId()
784 onuID = onuDevice.ProxyAddress.GetOnuId()
785 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700786 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 intfID = omciMsg.GetProxyAddress().GetChannelId()
788 onuID = omciMsg.GetProxyAddress().GetOnuId()
789 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700790 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700791 if connectStatus != voltha.ConnectStatus_REACHABLE {
792 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700793 return
794 }
795
lcuie24ef182019-04-29 22:58:36 -0700796 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
797 isHexString := false
798 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
799 if decodeerr == nil {
800 isHexString = true
801 }
802
803 // 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.
804 var omciMessage *oop.OmciMsg
805 if isHexString {
806 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
807 } else {
808 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
809 hex.Encode(hexPkt, omciMsg.Message)
810 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
811 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700812
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
814 if err != nil {
815 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
816 return
817 }
lcuie24ef182019-04-29 22:58:36 -0700818 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700819}
820
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700821func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
822 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
823 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700824 // TODO: need resource manager
825 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700826 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400828 st, _ := status.FromError(err)
829 if st.Code() == codes.AlreadyExists {
830 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
831 } else {
832 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
833 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700834 } else {
835 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
836 }
837}
838
Matt Jeanneret53539512019-07-20 14:47:02 -0400839func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 channelID := onuDiscInd.GetIntfId()
841 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400842
843 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530844
845 if _, ok := dh.discOnus.Load(sn); ok {
846
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400847 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400848 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700849 }
850
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530851 dh.discOnus.Store(sn, true)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400852
cuilin20187b2a8c32019-03-26 19:52:28 -0700853 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400854 if sn != "" {
855 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400856 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400857 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
858 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400859 }
860
861 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
862 var onuID uint32
863 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700864 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400865 ponintfid := onuDiscInd.GetIntfId()
866 dh.lockDevice.Lock()
867 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
868 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400869 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400870 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
871 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400872 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700873 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400874 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700875 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400876 log.Errorw("Create onu error",
877 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
878 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400879 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400880 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400881 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400882
883 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700884 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400885 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400886 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700887 //Insert the ONU into cache to use in OnuIndication.
888 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Scott Baker7eb0a932019-07-26 10:33:22 -0700889 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
890 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700891 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400892
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530893 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
894 dh.onus.Store(onuKey, onuDev)
895 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400896
Mahir Gunyele77977b2019-06-27 05:36:22 -0700897 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
898 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400899 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
900 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700901 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700902 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
903 //TODO: We put this sleep here to prevent the race between state update and onuIndication
904 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
905 //then the initialisation fails.
906 time.Sleep(1 * time.Second)
907 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400908 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700909}
910
911func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
912 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
913
914 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700915 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700916 var onuDevice *voltha.Device
917 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700918 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
919 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700920 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530921
922 if onuInCache, ok := dh.onus.Load(onuKey); ok {
923
Mahir Gunyele77977b2019-06-27 05:36:22 -0700924 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
925 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530926 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700927 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700928 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
929 if serialNumber != "" {
930 kwargs["serial_number"] = serialNumber
931 } else {
932 kwargs["onu_id"] = onuInd.OnuId
933 kwargs["parent_port_no"] = ponPort
934 }
935 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700936 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700937
938 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400939 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700940 //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 -0400941 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700942 }
943
944 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
945 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})
946 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700947 if !foundInCache {
948 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530949
950 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
951
Mahir Gunyele77977b2019-06-27 05:36:22 -0700952 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700953 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700954
cuilin20187b2a8c32019-03-26 19:52:28 -0700955 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700956 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700957 return
958 }
959
960}
961
Scott Baker7eb0a932019-07-26 10:33:22 -0700962func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400963 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 -0700964 dh.updateOnuAdminState(onuInd)
965 // operState
966 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400967 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 -0700968 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
969 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
970 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
971 if err != nil {
972 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
973 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
974 }
975 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700976 // Ignore operstatus if device was found in cache
977 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400978 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 -0700979 return
980 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400981 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
982 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
984 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
985 if err != nil {
986 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +0530987 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 return
989 }
990 } else {
991 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
992 }
993}
994
995func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
996 if onuInd.AdminState == "down" {
997 if onuInd.OperState != "down" {
998 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
999 // Forcing the oper state change code to execute
1000 onuInd.OperState = "down"
1001 }
1002 // Port and logical port update is taken care of by oper state block
1003 } else if onuInd.AdminState == "up" {
1004 log.Debugln("received-onu-admin-state up")
1005 } else {
1006 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
1007 }
1008 log.Debugln("admin-state-dealt-with")
1009}
1010
cuilin20187b2a8c32019-03-26 19:52:28 -07001011func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1012 if serialNum != nil {
1013 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001014 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001016}
1017
1018func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1019 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001021 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1022 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1023 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1024 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1025 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1026 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1027 return tmp
1028}
1029
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030//UpdateFlowsBulk upates the bulk flow
1031func (dh *DeviceHandler) UpdateFlowsBulk() error {
1032 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -07001033}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001034
1035//GetChildDevice returns the child device for given parent port and onu id
1036func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1037 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001038 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001040 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001042 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001044 return nil
1045 }
1046 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1047 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301048}
1049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050// SendPacketInToCore sends packet-in to core
1051// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1052// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001053func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001054 log.Debugw("send-packet-in-to-core", log.Fields{
1055 "port": logicalPort,
1056 "packet": hex.EncodeToString(packetPayload),
1057 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001058 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001059 log.Errorw("Error sending packetin to core", log.Fields{
1060 "error": err,
1061 "packet": hex.EncodeToString(packetPayload),
1062 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001063 return
1064 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001065 log.Debugw("Sent packet-in to core successfully", log.Fields{
1066 "packet": hex.EncodeToString(packetPayload),
1067 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001068}
1069
A R Karthick1f85b802019-10-11 05:06:05 +00001070// AddUniPortToOnu adds the uni port to the onu device
1071func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1072 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301073
1074 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001075 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301076 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1077 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001078 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1079 }
1080 }
1081}
1082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001084func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1085 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 -04001086 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001087 for _, flow := range flows.ToRemove.Items {
1088 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1089 dh.flowMgr.RemoveFlow(flow)
1090 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301091
1092 for _, flow := range flows.ToAdd.Items {
1093 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
1094 dh.flowMgr.AddFlow(flow, flowMetadata)
1095 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001096 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001097 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001098 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001099 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001100 // dh.flowMgr.RemoveFlow(flow)
1101 }
1102 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001103 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001104 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301105}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001106
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001107//DisableDevice disables the given device
1108//It marks the following for the given device:
1109//Device-Handler Admin-State : down
1110//Device Port-State: UNKNOWN
1111//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001112func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001113 /* On device disable ,admin state update has to be done prior sending request to agent since
1114 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001115 dh.lockDevice.Lock()
1116 dh.adminState = "down"
1117 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001118 if dh.Client != nil {
1119 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1120 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1121 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1122 dh.lockDevice.Lock()
1123 dh.adminState = "up"
1124 dh.lockDevice.Unlock()
1125 return err
1126 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001127 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001128 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001129 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001130 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001131 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301132
1133 dh.discOnus = sync.Map{}
1134 dh.onus = sync.Map{}
1135
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301136 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001137 cloned := proto.Clone(device).(*voltha.Device)
1138 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1140 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001141 return err
1142 }
1143
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001144 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001145 return nil
1146}
1147
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301148func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001149
1150 // Update onu state as unreachable in onu adapter
1151 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301152 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001153 //get the child device for the parent device
1154 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1155 if err != nil {
1156 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1157 }
1158 if onuDevices != nil {
1159 for _, onuDevice := range onuDevices.Items {
1160 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1161 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1162 if err != nil {
1163 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1164 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1165 }
1166
1167 }
1168 }
1169
1170}
1171
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172//ReenableDevice re-enables the olt device after disable
1173//It marks the following for the given device:
1174//Device-Handler Admin-State : up
1175//Device Port-State: ACTIVE
1176//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001177func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001178 dh.lockDevice.Lock()
1179 dh.adminState = "up"
1180 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301181
1182 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1183 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1184 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1185 dh.lockDevice.Lock()
1186 dh.adminState = "down"
1187 dh.lockDevice.Unlock()
1188 return err
1189 }
1190 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001191 log.Debug("olt-reenabled")
1192
1193 cloned := proto.Clone(device).(*voltha.Device)
1194 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001195 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1196 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001197 return err
1198 }
1199
1200 //Update the device oper status as ACTIVE
1201 cloned.OperStatus = voltha.OperStatus_ACTIVE
1202 dh.device = cloned
1203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001204 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1205 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001206 return err
1207 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001209
1210 return nil
1211}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001212
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301213func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001214 var uniID uint32
1215 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301216 for _, port := range onu.UniPorts {
1217 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001218 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1219 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301220 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1221 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001222 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301223 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1224 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001225 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301226 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001227 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301228 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001229 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301230 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1231 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001232 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301233 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1234 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1235 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001236 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301237 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1238 }
1239 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1240 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1241 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1242 }
1243 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1244 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1245 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 +00001246 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001247 }
1248 return nil
1249}
1250
1251func (dh *DeviceHandler) clearNNIData() error {
1252 nniUniID := -1
1253 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301254
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001255 if dh.resourceMgr == nil {
1256 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1257 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001258 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301259 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1260 if err != nil {
1261 log.Error("Failed to fetch nni from kv store")
1262 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001263 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301264 log.Debugw("NNI are ", log.Fields{"nni": nni})
1265 for _, nniIntfID := range nni {
1266 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1267 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1268 for _, flowID := range flowIDs {
1269 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1270 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001271 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301272 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1273 log.Error("Failed to clear nni from kv store")
1274 return err
1275 }
1276 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001277}
1278
1279// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1280func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1281 log.Debug("Function entry delete device")
1282 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001283 if dh.adminState == "deleted" {
1284 dh.lockDevice.Unlock()
1285 return nil
1286 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001287 dh.adminState = "deleted"
1288 dh.lockDevice.Unlock()
1289 /* Clear the KV store data associated with the all the UNI ports
1290 This clears up flow data and also resource map data for various
1291 other pon resources like alloc_id and gemport_id
1292 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001293 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301294 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1295 var ponPort uint32
1296 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1297 var onuGemData []rsrcMgr.OnuGemInfo
1298 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1299 if err != nil {
1300 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1301 return err
1302 }
1303 for _, onu := range onuGemData {
1304 log.Debugw("onu data ", log.Fields{"onu": onu})
1305 if err = dh.clearUNIData(&onu); err != nil {
1306 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1307 }
1308 }
1309 onuGemData = nil
1310 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1311 if err != nil {
1312 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001313 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001314 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001315 /* Clear the flows from KV store associated with NNI port.
1316 There are mostly trap rules from NNI port (like LLDP)
1317 */
1318 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301319 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001320 }
A R Karthick1f85b802019-10-11 05:06:05 +00001321
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001322 /* Clear the resource pool for each PON port in the background */
1323 go dh.resourceMgr.Delete()
1324 }
A R Karthick1f85b802019-10-11 05:06:05 +00001325
Devmalya Paul495b94a2019-08-27 19:42:00 -04001326 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301327 dh.onus.Range(func(key interface{}, value interface{}) bool {
1328 dh.onus.Delete(key)
1329 return true
1330 })
1331
Devmalya Paul495b94a2019-08-27 19:42:00 -04001332 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301333 // Stop the Stats collector
1334 dh.stopCollector <- true
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301335 // stop the heartbeat check routine
1336 dh.stopHeartbeatCheck <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001337 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001338 if dh.Client != nil {
1339 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1340 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1341 return err
1342 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001343 }
1344 cloned := proto.Clone(device).(*voltha.Device)
1345 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1346 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1347 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1348 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1349 return err
1350 }
1351 return nil
1352}
1353
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001355func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1356 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001357 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001358 return err
1359 }
1360
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001362
1363 return nil
1364}
1365
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001366func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001367 log.Debugw("Received packet-in", log.Fields{
1368 "packet-indication": *packetIn,
1369 "packet": hex.EncodeToString(packetIn.Pkt),
1370 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001371 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1372 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001373 log.Errorw("Error getting logical port from packet-in", log.Fields{
1374 "error": err,
1375 "packet": hex.EncodeToString(packetIn.Pkt),
1376 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001377 return
1378 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001379 log.Debugw("sending packet-in to core", log.Fields{
1380 "logicalPortNum": logicalPortNum,
1381 "packet": hex.EncodeToString(packetIn.Pkt),
1382 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001384 log.Errorw("Error sending packet-in to core", log.Fields{
1385 "error": err,
1386 "packet": hex.EncodeToString(packetIn.Pkt),
1387 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001388 return
1389 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001390 log.Debugw("Success sending packet-in to core!", log.Fields{
1391 "packet": hex.EncodeToString(packetIn.Pkt),
1392 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001393}
1394
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1396func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001397 log.Debugw("incoming-packet-out", log.Fields{
1398 "deviceID": dh.deviceID,
1399 "egress_port_no": egressPortNo,
1400 "pkt-length": len(packet.Data),
1401 "packet": hex.EncodeToString(packet.Data),
1402 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001403
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001405 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001406 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1407 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301408 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1409 // Do not packet-out lldp packets on uni port.
1410 // ONOS has no clue about uni/nni ports, it just packets out on all
1411 // available ports on the Logical Switch. It should not be interested
1412 // in the UNI links.
1413 log.Debug("dropping-lldp-packet-out-on-uni")
1414 return nil
1415 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001416 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1417 if innerEthType == 0x8100 {
1418 // q-in-q 802.1ad or 802.1q double tagged packet.
1419 // slice out the outer tag.
1420 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1421 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001422 }
1423 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001424 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1425 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001426 uniID := UniIDFromPortNum(uint32(egressPortNo))
1427
1428 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1429 if err != nil {
1430 // In this case the openolt agent will receive the gemPortID as 0.
1431 // The agent tries to retrieve the gemPortID in this case.
1432 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001433 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1434 "packet": hex.EncodeToString(packet.Data),
1435 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001436 }
1437
1438 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001439
Matteo Scandolo6056e822019-11-13 14:05:29 -08001440 log.Debugw("sending-packet-to-onu", log.Fields{
1441 "egress_port_no": egressPortNo,
1442 "IntfId": intfID,
1443 "onuID": onuID,
1444 "uniID": uniID,
1445 "gemPortID": gemPortID,
1446 "packet": hex.EncodeToString(packet.Data),
1447 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001448
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001449 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001450 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1451 "error": err,
1452 "packet": hex.EncodeToString(packet.Data),
1453 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001454 return err
1455 }
1456 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001458
Matteo Scandolo6056e822019-11-13 14:05:29 -08001459 log.Debugw("sending-packet-to-nni", log.Fields{
1460 "uplink_pkt": uplinkPkt,
1461 "packet": hex.EncodeToString(packet.Data),
1462 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001463
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001464 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001465 log.Errorw("Error while sending packet-out to NNI", log.Fields{
1466 "error": err,
1467 "packet": hex.EncodeToString(packet.Data),
1468 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001469 return err
1470 }
1471 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001472 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1473 "egress_port_no": egressPortNo,
1474 "egressPortType": egressPortType,
1475 "packet": hex.EncodeToString(packet.Data),
1476 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001477 }
1478 return nil
1479}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001480
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001481func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1482 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001483}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301484
1485func startHeartbeatCheck(dh *DeviceHandler) {
1486 // start the heartbeat check towards the OLT.
1487 var timerCheck *time.Timer
1488
1489 for {
1490 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1491 select {
1492 case <-heartbeatTimer.C:
1493 ctx, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1494 if heartBeat, err := dh.Client.HeartbeatCheck(ctx, new(oop.Empty)); err != nil {
1495 log.Error("Hearbeat failed")
1496 if timerCheck == nil {
1497 // start a after func, when expired will update the state to the core
1498 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, dh.updateStateUnreachable)
1499 }
1500 } else {
1501 if timerCheck != nil {
1502 if timerCheck.Stop() {
1503 log.Debug("We got hearbeat within the timeout")
1504 } else {
1505
1506 log.Debug("We got hearbeat after the timeout expired, changing the states")
1507 go dh.notifyChildDevices("up")
1508 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
1509 voltha.OperStatus_ACTIVE); err != nil {
1510 log.Errorw("Failed to update device state", log.Fields{"deviceID": dh.device.Id, "error": err})
1511 }
1512 }
1513 timerCheck = nil
1514 }
1515 log.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
1516 }
1517 cancel()
1518 case <-dh.stopHeartbeatCheck:
1519 log.Debug("Stopping heart beat check")
1520 return
1521 }
1522 }
1523}
1524
1525func (dh *DeviceHandler) updateStateUnreachable() {
1526
1527 go dh.notifyChildDevices("unreachable")
1528 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1529 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": err})
1530 return
1531 }
1532}