blob: 9c65cee901dc4a036912df809a5c5fc323c4b4f1 [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
79 discOnus sync.Map
80 onus sync.Map
Naga Manjunath7615e552019-10-11 22:35:47 +053081 portStats *OpenOltStatisticsMgr
82 metrics *pmmetrics.PmMetrics
83 stopCollector chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070084}
85
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070087type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070089 deviceType string
90 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091 onuID uint32
92 intfID uint32
93 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000094 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070095}
96
Naga Manjunath7615e552019-10-11 22:35:47 +053097var pmNames = []string{
98 "rx_bytes",
99 "rx_packets",
100 "rx_mcast_packets",
101 "rx_bcast_packets",
102 "tx_bytes",
103 "tx_packets",
104 "tx_mcast_packets",
105 "tx_bcast_packets",
106}
107
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 device.deviceType = deviceTp
113 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 device.onuID = onuID
115 device.intfID = intfID
116 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000117 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700118 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530119}
120
121//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530122func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700123 var dh DeviceHandler
124 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400125 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400126 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700128 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400130 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700131 dh.device = cloned
132 dh.openOLT = adapter
133 dh.exitChannel = make(chan int, 1)
134 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530135 dh.stopCollector = make(chan bool, 2)
136 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
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) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 var operStatus common.OperStatus_OperStatus
230 if state == "up" {
231 operStatus = voltha.OperStatus_ACTIVE
232 } else {
233 operStatus = voltha.OperStatus_DISCOVERED
234 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400236 label := GetportLabel(portNum, portType)
237 if len(label) == 0 {
238 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
239 return
240 }
241 // Now create Port
242 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700243 PortNo: portNum,
244 Label: label,
245 Type: portType,
246 OperStatus: operStatus,
247 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400248 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700249 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700250 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
251 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400252 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
255// readIndications to read the indications from the OLT device
256func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400257 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400258 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700259 if err != nil {
260 log.Errorw("Failed to read indications", log.Fields{"err": err})
261 return
262 }
263 if indications == nil {
264 log.Errorw("Indications is nil", log.Fields{})
265 return
266 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400267 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400269 if err != nil || device == nil {
270 /*TODO: needs to handle error scenarios */
271 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400273 }
274 // When the device is in DISABLED and Adapter container restarts, we need to
275 // rebuild the locally maintained admin state.
276 if device.AdminState == voltha.AdminState_DISABLED {
277 dh.lockDevice.Lock()
278 dh.adminState = "down"
279 dh.lockDevice.Unlock()
280 }
281
David Bainbridgef5879ca2019-12-13 21:17:54 +0000282 // Create an exponential backoff around re-enabling indications. The
283 // maximum elapsed time for the back off is set to 0 so that we will
284 // continue to retry. The max interval defaults to 1m, but is set
285 // here for code clarity
286 indicationBackoff := backoff.NewExponentialBackOff()
287 indicationBackoff.MaxElapsedTime = 0
288 indicationBackoff.MaxInterval = 1 * time.Minute
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 for {
290 indication, err := indications.Recv()
291 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530292 log.Infow("EOF for indications", log.Fields{"err": err})
David Bainbridgef5879ca2019-12-13 21:17:54 +0000293 // Use an exponential back off to prevent getting into a tight loop
294 duration := indicationBackoff.NextBackOff()
295 if duration == backoff.Stop {
296 // If we reach a maximum then warn and reset the backoff
297 // timer and keep attempting.
298 log.Warnw("Maximum indication backoff reached, resetting backoff timer",
299 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
300 indicationBackoff.Reset()
301 }
302 time.Sleep(indicationBackoff.NextBackOff())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530303 indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
304 if err != nil {
305 log.Errorw("Failed to read indications", log.Fields{"err": err})
306 return
307 }
308 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700309 }
310 if err != nil {
311 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400312 if dh.adminState == "deleted" {
313 log.Debug("Device deleted stoping the read indication thread")
314 break
315 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400316 dh.transitionMap.Handle(DeviceDownInd)
317 dh.transitionMap.Handle(DeviceInit)
318 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 }
David Bainbridgef5879ca2019-12-13 21:17:54 +0000320 // Reset backoff if we have a successful receive
321 indicationBackoff.Reset()
Chaitrashree G S44124192019-08-07 20:21:36 -0400322 dh.lockDevice.RLock()
323 adminState := dh.adminState
324 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400325 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400326 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530327
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400328 log.Infow("olt is admin down, ignore indication", log.Fields{})
329 continue
330 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700331 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530332
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700333 }
334}
335
336func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000337 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000338 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700339 dh.transitionMap.Handle(DeviceUpInd)
340 } else if oltIndication.OperState == "down" {
341 dh.transitionMap.Handle(DeviceDownInd)
342 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000343 // Send or clear Alarm
344 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700345}
346
347func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400348 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700349 switch indication.Data.(type) {
350 case *oop.Indication_OltInd:
351 dh.handleOltIndication(indication.GetOltInd())
352 case *oop.Indication_IntfInd:
353 intfInd := indication.GetIntfInd()
354 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
355 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
356 case *oop.Indication_IntfOperInd:
357 intfOperInd := indication.GetIntfOperInd()
358 if intfOperInd.GetType() == "nni" {
359 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530360 dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700361 } else if intfOperInd.GetType() == "pon" {
362 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
363 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000364 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700365 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700366 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
367 case *oop.Indication_OnuDiscInd:
368 onuDiscInd := indication.GetOnuDiscInd()
369 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700370 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400371 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 case *oop.Indication_OnuInd:
373 onuInd := indication.GetOnuInd()
374 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
375 go dh.onuIndication(onuInd)
376 case *oop.Indication_OmciInd:
377 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700378 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 -0400379 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700380 case *oop.Indication_PktInd:
381 pktInd := indication.GetPktInd()
382 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
383 go dh.handlePacketIndication(pktInd)
384 case *oop.Indication_PortStats:
385 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530386 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 case *oop.Indication_FlowStats:
388 flowStats := indication.GetFlowStats()
389 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
390 case *oop.Indication_AlarmInd:
391 alarmInd := indication.GetAlarmInd()
392 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530393 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700394 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530395}
396
397// doStateUp handle the olt up indication and update to voltha core
398func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400399 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700400 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400401 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700402 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 -0400403 return err
404 }
405 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530406}
407
408// doStateDown handle the olt down indication
409func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700410 dh.lockDevice.Lock()
411 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400412 log.Debug("do-state-down-start")
413
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700414 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400415 if err != nil || device == nil {
416 /*TODO: needs to handle error scenarios */
417 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700418 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400419 }
420
421 cloned := proto.Clone(device).(*voltha.Device)
422 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700423 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
424 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
425 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400426 }
427
428 //Update the device oper state and connection status
429 cloned.OperStatus = voltha.OperStatus_UNKNOWN
430 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
431 dh.device = cloned
432
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700433 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
434 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
435 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400436 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400437
438 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400440 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400442 return err
443 }
444 for _, onuDevice := range onuDevices.Items {
445
446 // Update onu state as down in onu adapter
447 onuInd := oop.OnuIndication{}
448 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
450 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
451 if er != nil {
452 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
453 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700454 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400456 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700457 /* Discovered ONUs entries need to be cleared , since after OLT
458 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530459 dh.discOnus = sync.Map{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700461 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530462}
463
464// doStateInit dial the grpc before going to init state
465func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400466 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400467 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400468 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400470 return err
471 }
472 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530473}
474
475// postInit create olt client instance to invoke RPC on the olt device
476func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400477 dh.Client = oop.NewOpenoltClient(dh.clientCon)
478 dh.transitionMap.Handle(GrpcConnected)
479 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530480}
481
482// doStateConnected get the device info and update to voltha core
483func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400484 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400485
486 // Case where OLT is disabled and then rebooted.
487 if dh.adminState == "down" {
488 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400490 if err != nil || device == nil {
491 /*TODO: needs to handle error scenarios */
492 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
493 }
494
495 cloned := proto.Clone(device).(*voltha.Device)
496 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
497 cloned.OperStatus = voltha.OperStatus_UNKNOWN
498 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
500 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400501 }
502
Chaitrashree G S44124192019-08-07 20:21:36 -0400503 // 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 -0400504 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
505 if err != nil {
506 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
507 }
508
509 // Start reading indications
510 go dh.readIndications()
511 return nil
512 }
513
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400514 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700515 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400516 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 return err
518 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400519
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700520 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400521 if err != nil || device == nil {
522 /*TODO: needs to handle error scenarios */
523 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400525 }
526 cloned := proto.Clone(device).(*voltha.Device)
527 // Update the all ports (if available) on that device to ACTIVE.
528 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
530 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400531 return err
532 }
533
Girish Gowdru0c588b22019-04-23 23:24:56 -0400534 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
535 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400537 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400539 }
540 // Instantiate flow manager
541 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
542 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700543 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400544 }
545 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400546 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400547 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530548 // Stats config for new device
549 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530550
cuilin20187b2a8c32019-03-26 19:52:28 -0700551 // Start reading indications
552 go dh.readIndications()
553 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530554}
555
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400556func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
557 var err error
558 var deviceInfo *oop.DeviceInfo
559
560 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
561
562 if err != nil {
563 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
564 return nil, err
565 }
566 if deviceInfo == nil {
567 log.Errorw("Device info is nil", log.Fields{})
568 return nil, errors.New("failed to get device info from OLT")
569 }
570
571 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
572 dh.device.Root = true
573 dh.device.Vendor = deviceInfo.Vendor
574 dh.device.Model = deviceInfo.Model
575 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
576 dh.device.HardwareVersion = deviceInfo.HardwareVersion
577 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
578
579 if deviceInfo.DeviceId == "" {
580 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
581 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
582 genmac, err := generateMacFromHost(host)
583 if err != nil {
584 return nil, err
585 }
586 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
587 dh.device.MacAddress = genmac
588 } else {
589 dh.device.MacAddress = deviceInfo.DeviceId
590 }
591
592 // Synchronous call to update device - this method is run in its own go routine
593 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
594 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
595 return nil, err
596 }
597
598 return deviceInfo, nil
599}
600
Naga Manjunath7615e552019-10-11 22:35:47 +0530601func startCollector(dh *DeviceHandler) {
602 // Initial delay for OLT initialization
603 time.Sleep(1 * time.Minute)
604 log.Debugf("Starting-Collector")
605 context := make(map[string]string)
606 for {
607 select {
608 case <-dh.stopCollector:
609 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
610 return
611 default:
612 freq := dh.metrics.ToPmConfigs().DefaultFreq
613 time.Sleep(time.Duration(freq) * time.Second)
614 context["oltid"] = dh.deviceID
615 context["devicetype"] = dh.deviceType
616 // NNI Stats
617 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
618 log.Debugf("Collect-NNI-Metrics %v", cmnni)
619 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
620 log.Debugf("Publish-NNI-Metrics")
621 // PON Stats
622 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
623 for i := uint32(0); i < NumPonPORTS; i++ {
624 cmpon := dh.portStats.collectPONMetrics(i)
625 log.Debugf("Collect-PON-Metrics %v", cmpon)
626
627 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
628 log.Debugf("Publish-PON-Metrics")
629 }
630 }
631 }
632}
633
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530635func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700637 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530639
640 // Now, set the initial PM configuration for that device
641 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
642 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
643 }
644
645 go startCollector(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530646}
647
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530649func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700650 return &ic.SwitchCapability{
651 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530652 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700653 HwDesc: "open_pon",
654 SwDesc: "open_pon",
655 SerialNum: dh.device.SerialNumber,
656 },
657 SwitchFeatures: &of.OfpSwitchFeatures{
658 NBuffers: 256,
659 NTables: 2,
660 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
661 of.OfpCapabilities_OFPC_TABLE_STATS |
662 of.OfpCapabilities_OFPC_PORT_STATS |
663 of.OfpCapabilities_OFPC_GROUP_STATS),
664 },
665 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530666}
667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530669func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700671 return &ic.PortCapability{
672 Port: &voltha.LogicalPort{
673 OfpPort: &of.OfpPort{
674 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
675 Config: 0,
676 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 Curr: capacity,
678 Advertised: capacity,
679 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700680 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
681 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
682 },
683 DeviceId: dh.device.Id,
684 DevicePortNo: uint32(portNo),
685 },
686 }, nil
687}
688
William Kurkianff524662019-08-20 10:34:30 -0400689func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700691 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 var deviceID string
693 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700694
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700695 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530696
697 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
698
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700699 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
700 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700701 kwargs := make(map[string]interface{})
702 kwargs["onu_id"] = omciInd.OnuId
703 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
706 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400707 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
708 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700709 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 deviceType = onuDevice.Type
711 deviceID = onuDevice.Id
712 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
713 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530714 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700715 } else {
716 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530718 deviceType = onuInCache.(*OnuDevice).deviceType
719 deviceID = onuInCache.(*OnuDevice).deviceID
720 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700721 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700722
723 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
724 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
725 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400727 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
728 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700729 }
William Kurkianff524662019-08-20 10:34:30 -0400730 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530731}
732
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733//ProcessInterAdapterMessage sends the proxied messages to the target device
734// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
735// is meant, and then send the unmarshalled omci message to this onu
736func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
737 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700738 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700740 fromTopic := msg.Header.FromTopic
741 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 toDeviceID := msg.Header.ToDeviceId
743 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700744
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700746
747 msgBody := msg.GetBody()
748
749 omciMsg := &ic.InterAdapterOmciMessage{}
750 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
751 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
752 return err
753 }
754
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700755 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700756 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
757 if err != nil {
758 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700759 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700760 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
762 dh.sendProxiedMessage(onuDevice, omciMsg)
763
cuilin20187b2a8c32019-03-26 19:52:28 -0700764 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 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 -0700766 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700767 }
768
769 } else {
770 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
771 }
772 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530773}
774
cuilin20187b2a8c32019-03-26 19:52:28 -0700775func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 var intfID uint32
777 var onuID uint32
778 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700779 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780 intfID = onuDevice.ProxyAddress.GetChannelId()
781 onuID = onuDevice.ProxyAddress.GetOnuId()
782 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700783 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 intfID = omciMsg.GetProxyAddress().GetChannelId()
785 onuID = omciMsg.GetProxyAddress().GetOnuId()
786 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700787 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700788 if connectStatus != voltha.ConnectStatus_REACHABLE {
789 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700790 return
791 }
792
lcuie24ef182019-04-29 22:58:36 -0700793 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
794 isHexString := false
795 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
796 if decodeerr == nil {
797 isHexString = true
798 }
799
800 // 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.
801 var omciMessage *oop.OmciMsg
802 if isHexString {
803 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
804 } else {
805 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
806 hex.Encode(hexPkt, omciMsg.Message)
807 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
808 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700809
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700810 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
811 if err != nil {
812 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
813 return
814 }
lcuie24ef182019-04-29 22:58:36 -0700815 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700816}
817
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
819 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
820 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700821 // TODO: need resource manager
822 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700823 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530824 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400825 st, _ := status.FromError(err)
826 if st.Code() == codes.AlreadyExists {
827 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
828 } else {
829 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
830 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700831 } else {
832 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
833 }
834}
835
Matt Jeanneret53539512019-07-20 14:47:02 -0400836func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 channelID := onuDiscInd.GetIntfId()
838 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400839
840 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530841
842 if _, ok := dh.discOnus.Load(sn); ok {
843
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400844 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400845 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700846 }
847
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530848 dh.discOnus.Store(sn, true)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400849
cuilin20187b2a8c32019-03-26 19:52:28 -0700850 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400851 if sn != "" {
852 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400853 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400854 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
855 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400856 }
857
858 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
859 var onuID uint32
860 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700861 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400862 ponintfid := onuDiscInd.GetIntfId()
863 dh.lockDevice.Lock()
864 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
865 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400866 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400867 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
868 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400869 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700870 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400871 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700872 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400873 log.Errorw("Create onu error",
874 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
875 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400876 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400877 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400878 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400879
880 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700881 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400882 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400883 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700884 //Insert the ONU into cache to use in OnuIndication.
885 //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 -0700886 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
887 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700888 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400889
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530890 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
891 dh.onus.Store(onuKey, onuDev)
892 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400893
Mahir Gunyele77977b2019-06-27 05:36:22 -0700894 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
895 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400896 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
897 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700898 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700899 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
900 //TODO: We put this sleep here to prevent the race between state update and onuIndication
901 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
902 //then the initialisation fails.
903 time.Sleep(1 * time.Second)
904 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400905 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700906}
907
908func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
909 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
910
911 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700913 var onuDevice *voltha.Device
914 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700915 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
916 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700917 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530918
919 if onuInCache, ok := dh.onus.Load(onuKey); ok {
920
Mahir Gunyele77977b2019-06-27 05:36:22 -0700921 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
922 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530923 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700924 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700925 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
926 if serialNumber != "" {
927 kwargs["serial_number"] = serialNumber
928 } else {
929 kwargs["onu_id"] = onuInd.OnuId
930 kwargs["parent_port_no"] = ponPort
931 }
932 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700933 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700934
935 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400936 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 //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 -0400938 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700939 }
940
941 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
942 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})
943 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700944 if !foundInCache {
945 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530946
947 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
948
Mahir Gunyele77977b2019-06-27 05:36:22 -0700949 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700950 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700951
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700953 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700954 return
955 }
956
957}
958
Scott Baker7eb0a932019-07-26 10:33:22 -0700959func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400960 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 -0700961 dh.updateOnuAdminState(onuInd)
962 // operState
963 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400964 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 -0700965 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
966 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
967 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
968 if err != nil {
969 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
970 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
971 }
972 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700973 // Ignore operstatus if device was found in cache
974 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400975 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 -0700976 return
977 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400978 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
979 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
981 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
982 if err != nil {
983 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +0530984 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985 return
986 }
987 } else {
988 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
989 }
990}
991
992func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
993 if onuInd.AdminState == "down" {
994 if onuInd.OperState != "down" {
995 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
996 // Forcing the oper state change code to execute
997 onuInd.OperState = "down"
998 }
999 // Port and logical port update is taken care of by oper state block
1000 } else if onuInd.AdminState == "up" {
1001 log.Debugln("received-onu-admin-state up")
1002 } else {
1003 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
1004 }
1005 log.Debugln("admin-state-dealt-with")
1006}
1007
cuilin20187b2a8c32019-03-26 19:52:28 -07001008func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1009 if serialNum != nil {
1010 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001011 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001013}
1014
1015func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1016 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001018 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1019 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1020 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1021 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1022 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1023 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1024 return tmp
1025}
1026
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027//UpdateFlowsBulk upates the bulk flow
1028func (dh *DeviceHandler) UpdateFlowsBulk() error {
1029 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -07001030}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001031
1032//GetChildDevice returns the child device for given parent port and onu id
1033func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1034 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001035 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001037 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001039 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001041 return nil
1042 }
1043 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1044 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301045}
1046
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001047// SendPacketInToCore sends packet-in to core
1048// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1049// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001050func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001051 log.Debugw("send-packet-in-to-core", log.Fields{
1052 "port": logicalPort,
1053 "packet": hex.EncodeToString(packetPayload),
1054 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001056 log.Errorw("Error sending packetin to core", log.Fields{
1057 "error": err,
1058 "packet": hex.EncodeToString(packetPayload),
1059 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001060 return
1061 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001062 log.Debugw("Sent packet-in to core successfully", log.Fields{
1063 "packet": hex.EncodeToString(packetPayload),
1064 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001065}
1066
A R Karthick1f85b802019-10-11 05:06:05 +00001067// AddUniPortToOnu adds the uni port to the onu device
1068func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1069 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301070
1071 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001072 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301073 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1074 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001075 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1076 }
1077 }
1078}
1079
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001081func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1082 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 -04001083 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001084 for _, flow := range flows.ToRemove.Items {
1085 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1086 dh.flowMgr.RemoveFlow(flow)
1087 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301088
1089 for _, flow := range flows.ToAdd.Items {
1090 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
1091 dh.flowMgr.AddFlow(flow, flowMetadata)
1092 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001093 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001095 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001097 // dh.flowMgr.RemoveFlow(flow)
1098 }
1099 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001100 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001101 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301102}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001103
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001104//DisableDevice disables the given device
1105//It marks the following for the given device:
1106//Device-Handler Admin-State : down
1107//Device Port-State: UNKNOWN
1108//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001109func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001110 /* On device disable ,admin state update has to be done prior sending request to agent since
1111 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001112 dh.lockDevice.Lock()
1113 dh.adminState = "down"
1114 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001115 if dh.Client != nil {
1116 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1117 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1118 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1119 dh.lockDevice.Lock()
1120 dh.adminState = "up"
1121 dh.lockDevice.Unlock()
1122 return err
1123 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001124 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001125 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001126 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001127 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001128 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301129
1130 dh.discOnus = sync.Map{}
1131 dh.onus = sync.Map{}
1132
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001133 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001134 cloned := proto.Clone(device).(*voltha.Device)
1135 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001136 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1137 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001138 return err
1139 }
1140
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001141 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001142 return nil
1143}
1144
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001145func (dh *DeviceHandler) notifyChildDevices() {
1146
1147 // Update onu state as unreachable in onu adapter
1148 onuInd := oop.OnuIndication{}
1149 onuInd.OperState = "unreachable"
1150 //get the child device for the parent device
1151 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1152 if err != nil {
1153 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1154 }
1155 if onuDevices != nil {
1156 for _, onuDevice := range onuDevices.Items {
1157 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1158 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1159 if err != nil {
1160 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1161 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1162 }
1163
1164 }
1165 }
1166
1167}
1168
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001169//ReenableDevice re-enables the olt device after disable
1170//It marks the following for the given device:
1171//Device-Handler Admin-State : up
1172//Device Port-State: ACTIVE
1173//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001174func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1175 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001176 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1177 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1178 return err
1179 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001180 }
1181
1182 dh.lockDevice.Lock()
1183 dh.adminState = "up"
1184 dh.lockDevice.Unlock()
1185 log.Debug("olt-reenabled")
1186
1187 cloned := proto.Clone(device).(*voltha.Device)
1188 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1190 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001191 return err
1192 }
1193
1194 //Update the device oper status as ACTIVE
1195 cloned.OperStatus = voltha.OperStatus_ACTIVE
1196 dh.device = cloned
1197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1199 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001200 return err
1201 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001203
1204 return nil
1205}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001206
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301207func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001208 var uniID uint32
1209 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301210 for _, port := range onu.UniPorts {
1211 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001212 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1213 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301214 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1215 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001216 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301217 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1218 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001219 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301220 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001221 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301222 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001223 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301224 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1225 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001226 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301227 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1228 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1229 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001230 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301231 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1232 }
1233 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1234 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1235 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1236 }
1237 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1238 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1239 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 +00001240 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001241 }
1242 return nil
1243}
1244
1245func (dh *DeviceHandler) clearNNIData() error {
1246 nniUniID := -1
1247 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301248
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001249 if dh.resourceMgr == nil {
1250 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1251 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001252 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301253 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1254 if err != nil {
1255 log.Error("Failed to fetch nni from kv store")
1256 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001257 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301258 log.Debugw("NNI are ", log.Fields{"nni": nni})
1259 for _, nniIntfID := range nni {
1260 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1261 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1262 for _, flowID := range flowIDs {
1263 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1264 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001265 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301266 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1267 log.Error("Failed to clear nni from kv store")
1268 return err
1269 }
1270 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001271}
1272
1273// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1274func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1275 log.Debug("Function entry delete device")
1276 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001277 if dh.adminState == "deleted" {
1278 dh.lockDevice.Unlock()
1279 return nil
1280 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001281 dh.adminState = "deleted"
1282 dh.lockDevice.Unlock()
1283 /* Clear the KV store data associated with the all the UNI ports
1284 This clears up flow data and also resource map data for various
1285 other pon resources like alloc_id and gemport_id
1286 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001287 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301288 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1289 var ponPort uint32
1290 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1291 var onuGemData []rsrcMgr.OnuGemInfo
1292 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1293 if err != nil {
1294 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1295 return err
1296 }
1297 for _, onu := range onuGemData {
1298 log.Debugw("onu data ", log.Fields{"onu": onu})
1299 if err = dh.clearUNIData(&onu); err != nil {
1300 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1301 }
1302 }
1303 onuGemData = nil
1304 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1305 if err != nil {
1306 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001307 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001308 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001309 /* Clear the flows from KV store associated with NNI port.
1310 There are mostly trap rules from NNI port (like LLDP)
1311 */
1312 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301313 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001314 }
A R Karthick1f85b802019-10-11 05:06:05 +00001315
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001316 /* Clear the resource pool for each PON port in the background */
1317 go dh.resourceMgr.Delete()
1318 }
A R Karthick1f85b802019-10-11 05:06:05 +00001319
Devmalya Paul495b94a2019-08-27 19:42:00 -04001320 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301321 dh.onus.Range(func(key interface{}, value interface{}) bool {
1322 dh.onus.Delete(key)
1323 return true
1324 })
1325
Devmalya Paul495b94a2019-08-27 19:42:00 -04001326 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301327 // Stop the Stats collector
1328 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001329 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001330 if dh.Client != nil {
1331 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1332 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1333 return err
1334 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001335 }
1336 cloned := proto.Clone(device).(*voltha.Device)
1337 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1338 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1339 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1340 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1341 return err
1342 }
1343 return nil
1344}
1345
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001347func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1348 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001349 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001350 return err
1351 }
1352
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001354
1355 return nil
1356}
1357
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001358func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001359 log.Debugw("Received packet-in", log.Fields{
1360 "packet-indication": *packetIn,
1361 "packet": hex.EncodeToString(packetIn.Pkt),
1362 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001363 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1364 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001365 log.Errorw("Error getting logical port from packet-in", log.Fields{
1366 "error": err,
1367 "packet": hex.EncodeToString(packetIn.Pkt),
1368 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001369 return
1370 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001371 log.Debugw("sending packet-in to core", log.Fields{
1372 "logicalPortNum": logicalPortNum,
1373 "packet": hex.EncodeToString(packetIn.Pkt),
1374 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001376 log.Errorw("Error sending packet-in to core", log.Fields{
1377 "error": err,
1378 "packet": hex.EncodeToString(packetIn.Pkt),
1379 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001380 return
1381 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001382 log.Debugw("Success sending packet-in to core!", log.Fields{
1383 "packet": hex.EncodeToString(packetIn.Pkt),
1384 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001385}
1386
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1388func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001389 log.Debugw("incoming-packet-out", log.Fields{
1390 "deviceID": dh.deviceID,
1391 "egress_port_no": egressPortNo,
1392 "pkt-length": len(packet.Data),
1393 "packet": hex.EncodeToString(packet.Data),
1394 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001395
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001397 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001398 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1399 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301400 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1401 // Do not packet-out lldp packets on uni port.
1402 // ONOS has no clue about uni/nni ports, it just packets out on all
1403 // available ports on the Logical Switch. It should not be interested
1404 // in the UNI links.
1405 log.Debug("dropping-lldp-packet-out-on-uni")
1406 return nil
1407 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001408 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1409 if innerEthType == 0x8100 {
1410 // q-in-q 802.1ad or 802.1q double tagged packet.
1411 // slice out the outer tag.
1412 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1413 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001414 }
1415 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001416 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1417 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001418 uniID := UniIDFromPortNum(uint32(egressPortNo))
1419
1420 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1421 if err != nil {
1422 // In this case the openolt agent will receive the gemPortID as 0.
1423 // The agent tries to retrieve the gemPortID in this case.
1424 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001425 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1426 "packet": hex.EncodeToString(packet.Data),
1427 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001428 }
1429
1430 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001431
Matteo Scandolo6056e822019-11-13 14:05:29 -08001432 log.Debugw("sending-packet-to-onu", log.Fields{
1433 "egress_port_no": egressPortNo,
1434 "IntfId": intfID,
1435 "onuID": onuID,
1436 "uniID": uniID,
1437 "gemPortID": gemPortID,
1438 "packet": hex.EncodeToString(packet.Data),
1439 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001440
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001441 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001442 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1443 "error": err,
1444 "packet": hex.EncodeToString(packet.Data),
1445 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 return err
1447 }
1448 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001450
Matteo Scandolo6056e822019-11-13 14:05:29 -08001451 log.Debugw("sending-packet-to-nni", log.Fields{
1452 "uplink_pkt": uplinkPkt,
1453 "packet": hex.EncodeToString(packet.Data),
1454 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001455
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001456 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001457 log.Errorw("Error while sending packet-out to NNI", log.Fields{
1458 "error": err,
1459 "packet": hex.EncodeToString(packet.Data),
1460 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001461 return err
1462 }
1463 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001464 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1465 "egress_port_no": egressPortNo,
1466 "egressPortType": egressPortType,
1467 "packet": hex.EncodeToString(packet.Data),
1468 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001469 }
1470 return nil
1471}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001472
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1474 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001475}