blob: dbf301f93233004028971f9b52daec0b16fba961 [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
cuilin20187b2a8c32019-03-26 19:52:28 -070034 "github.com/gogo/protobuf/proto"
35 "github.com/golang/protobuf/ptypes"
Scott Baker51290152019-10-24 14:23:20 -070036 "github.com/opencord/voltha-lib-go/v2/pkg/adapters/adapterif"
37 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Naga Manjunath7615e552019-10-11 22:35:47 +053038 "github.com/opencord/voltha-lib-go/v2/pkg/pmmetrics"
Girish Gowdru0c588b22019-04-23 23:24:56 -040039 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053040 "github.com/opencord/voltha-protos/go/common"
41 ic "github.com/opencord/voltha-protos/go/inter_container"
42 of "github.com/opencord/voltha-protos/go/openflow_13"
43 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053044 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070045 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040046 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053047)
48
salmansiddiqui7ac62132019-08-22 03:58:50 +000049// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040050const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000051 MaxRetry = 10
52 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040053)
54
kdarapu381c6902019-07-31 18:23:16 +053055func init() {
56 _, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
57}
58
Phaneendra Manda4c62c802019-03-06 21:37:49 +053059//DeviceHandler will interact with the OLT device.
60type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070062 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040063 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070064 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053065 coreProxy adapterif.CoreProxy
66 AdapterProxy adapterif.AdapterProxy
67 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070068 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070069 exitChannel chan int
70 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053071 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070072 transitionMap *TransitionMap
73 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053074 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040075 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053076 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040077 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070078 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 nniIntfID int
Naga Manjunath7615e552019-10-11 22:35:47 +053080 portStats *OpenOltStatisticsMgr
81 metrics *pmmetrics.PmMetrics
82 stopCollector chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070083}
84
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070086type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088 deviceType string
89 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090 onuID uint32
91 intfID uint32
92 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000093 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070094}
95
Naga Manjunath7615e552019-10-11 22:35:47 +053096var pmNames = []string{
97 "rx_bytes",
98 "rx_packets",
99 "rx_mcast_packets",
100 "rx_bcast_packets",
101 "tx_bytes",
102 "tx_packets",
103 "tx_mcast_packets",
104 "tx_bcast_packets",
105}
106
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 device.deviceType = deviceTp
112 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 device.onuID = onuID
114 device.intfID = intfID
115 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000116 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700117 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530118}
119
120//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530121func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700122 var dh DeviceHandler
123 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400124 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400125 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700126 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700127 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400129 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700130 dh.device = cloned
131 dh.openOLT = adapter
132 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400133 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700134 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400137 // when the first IntfOperInd with status as "up" is received for
138 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 dh.nniIntfID = -1
Naga Manjunath7615e552019-10-11 22:35:47 +0530140 dh.stopCollector = make(chan bool, 2)
141 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
cuilin20187b2a8c32019-03-26 19:52:28 -0700142 //TODO initialize the support classes.
143 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530144}
145
146// start save the device to the data model
147func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 dh.lockDevice.Lock()
149 defer dh.lockDevice.Unlock()
150 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
151 // Add the initial device to the local model
152 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530153}
154
155// stop stops the device dh. Not much to do for now
156func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700157 dh.lockDevice.Lock()
158 defer dh.lockDevice.Unlock()
159 log.Debug("stopping-device-agent")
160 dh.exitChannel <- 1
161 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530162}
163
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400164func macifyIP(ip net.IP) string {
165 if len(ip) > 0 {
166 oct1 := strconv.FormatInt(int64(ip[12]), 16)
167 oct2 := strconv.FormatInt(int64(ip[13]), 16)
168 oct3 := strconv.FormatInt(int64(ip[14]), 16)
169 oct4 := strconv.FormatInt(int64(ip[15]), 16)
170 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
171 }
172 return ""
173}
174
175func generateMacFromHost(host string) (string, error) {
176 var genmac string
177 var addr net.IP
178 var ips []string
179 var err error
180
181 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
182
183 if addr = net.ParseIP(host); addr == nil {
184 log.Debugw("looking-up-hostname", log.Fields{"host": host})
185
186 if ips, err = net.LookupHost(host); err == nil {
187 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
188 if addr = net.ParseIP(ips[0]); addr == nil {
189 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
190 return "", errors.New("unable-to-parse-ip")
191 }
192 genmac = macifyIP(addr)
193 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
194 return genmac, nil
195 }
196 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
197 return "", err
198 }
199
200 genmac = macifyIP(addr)
201 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
202 return genmac, nil
203}
204
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530205func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700206 slist := strings.Split(mac, ":")
207 result := make([]uint32, len(slist))
208 var err error
209 var tmp int64
210 for index, val := range slist {
211 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
212 return []uint32{1, 2, 3, 4, 5, 6}
213 }
214 result[index] = uint32(tmp)
215 }
216 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530217}
218
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219//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 +0530220func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530221
Girish Gowdru0c588b22019-04-23 23:24:56 -0400222 if portType == voltha.Port_ETHERNET_NNI {
223 return fmt.Sprintf("nni-%d", portNum)
224 } else if portType == voltha.Port_PON_OLT {
225 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 } else if portType == voltha.Port_ETHERNET_UNI {
227 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400228 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 }
230 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530231}
232
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700233func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 var operStatus common.OperStatus_OperStatus
235 if state == "up" {
236 operStatus = voltha.OperStatus_ACTIVE
237 } else {
238 operStatus = voltha.OperStatus_DISCOVERED
239 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700240 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400241 label := GetportLabel(portNum, portType)
242 if len(label) == 0 {
243 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
244 return
245 }
246 // Now create Port
247 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700248 PortNo: portNum,
249 Label: label,
250 Type: portType,
251 OperStatus: operStatus,
252 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400253 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700254 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700255 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
256 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400257 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700258
Girish Gowdru1110ef22019-06-24 11:17:59 -0400259 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700260 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
261 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
262 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530264}
265
266// readIndications to read the indications from the OLT device
267func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400268 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400269 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 if err != nil {
271 log.Errorw("Failed to read indications", log.Fields{"err": err})
272 return
273 }
274 if indications == nil {
275 log.Errorw("Indications is nil", log.Fields{})
276 return
277 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400278 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700279 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400280 if err != nil || device == nil {
281 /*TODO: needs to handle error scenarios */
282 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700283 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400284 }
285 // When the device is in DISABLED and Adapter container restarts, we need to
286 // rebuild the locally maintained admin state.
287 if device.AdminState == voltha.AdminState_DISABLED {
288 dh.lockDevice.Lock()
289 dh.adminState = "down"
290 dh.lockDevice.Unlock()
291 }
292
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 for {
294 indication, err := indications.Recv()
295 if err == io.EOF {
296 break
297 }
298 if err != nil {
299 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400300 if dh.adminState == "deleted" {
301 log.Debug("Device deleted stoping the read indication thread")
302 break
303 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400304 dh.transitionMap.Handle(DeviceDownInd)
305 dh.transitionMap.Handle(DeviceInit)
306 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700307 }
Chaitrashree G S44124192019-08-07 20:21:36 -0400308 dh.lockDevice.RLock()
309 adminState := dh.adminState
310 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400311 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400312 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400314 log.Infow("olt is admin down, ignore indication", log.Fields{})
315 continue
316 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700317 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530318
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319 }
320}
321
322func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000323 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000324 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700325 dh.transitionMap.Handle(DeviceUpInd)
326 } else if oltIndication.OperState == "down" {
327 dh.transitionMap.Handle(DeviceDownInd)
328 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000329 // Send or clear Alarm
330 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700331}
332
333func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400334 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 switch indication.Data.(type) {
336 case *oop.Indication_OltInd:
337 dh.handleOltIndication(indication.GetOltInd())
338 case *oop.Indication_IntfInd:
339 intfInd := indication.GetIntfInd()
340 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
341 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
342 case *oop.Indication_IntfOperInd:
343 intfOperInd := indication.GetIntfOperInd()
344 if intfOperInd.GetType() == "nni" {
345 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
346 } else if intfOperInd.GetType() == "pon" {
347 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
348 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000349 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700350 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700351 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
352 case *oop.Indication_OnuDiscInd:
353 onuDiscInd := indication.GetOnuDiscInd()
354 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700355 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400356 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700357 case *oop.Indication_OnuInd:
358 onuInd := indication.GetOnuInd()
359 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
360 go dh.onuIndication(onuInd)
361 case *oop.Indication_OmciInd:
362 omciInd := indication.GetOmciInd()
363 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
William Kurkianff524662019-08-20 10:34:30 -0400364 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700365 case *oop.Indication_PktInd:
366 pktInd := indication.GetPktInd()
367 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
368 go dh.handlePacketIndication(pktInd)
369 case *oop.Indication_PortStats:
370 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530371 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 case *oop.Indication_FlowStats:
373 flowStats := indication.GetFlowStats()
374 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
375 case *oop.Indication_AlarmInd:
376 alarmInd := indication.GetAlarmInd()
377 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530378 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700379 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530380}
381
382// doStateUp handle the olt up indication and update to voltha core
383func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400384 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700385 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400386 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 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 -0400388 return err
389 }
390 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530391}
392
393// doStateDown handle the olt down indication
394func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700395 dh.lockDevice.Lock()
396 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400397 log.Debug("do-state-down-start")
398
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700399 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400400 if err != nil || device == nil {
401 /*TODO: needs to handle error scenarios */
402 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400404 }
405
406 cloned := proto.Clone(device).(*voltha.Device)
407 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700408 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
409 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
410 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400411 }
412
413 //Update the device oper state and connection status
414 cloned.OperStatus = voltha.OperStatus_UNKNOWN
415 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
416 dh.device = cloned
417
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700418 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
419 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
420 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400421 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400422
423 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700424 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400425 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400427 return err
428 }
429 for _, onuDevice := range onuDevices.Items {
430
431 // Update onu state as down in onu adapter
432 onuInd := oop.OnuIndication{}
433 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700434 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
435 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
436 if er != nil {
437 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
438 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700439 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400441 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700442 /* Discovered ONUs entries need to be cleared , since after OLT
443 is up, it starts sending discovery indications again*/
444 dh.discOnus = make(map[string]bool)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700445 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700446 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530447}
448
449// doStateInit dial the grpc before going to init state
450func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400451 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400452 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400453 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700454 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400455 return err
456 }
457 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530458}
459
460// postInit create olt client instance to invoke RPC on the olt device
461func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400462 dh.Client = oop.NewOpenoltClient(dh.clientCon)
463 dh.transitionMap.Handle(GrpcConnected)
464 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530465}
466
467// doStateConnected get the device info and update to voltha core
468func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400469 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400470
471 // Case where OLT is disabled and then rebooted.
472 if dh.adminState == "down" {
473 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400475 if err != nil || device == nil {
476 /*TODO: needs to handle error scenarios */
477 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
478 }
479
480 cloned := proto.Clone(device).(*voltha.Device)
481 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
482 cloned.OperStatus = voltha.OperStatus_UNKNOWN
483 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700484 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
485 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400486 }
487
Chaitrashree G S44124192019-08-07 20:21:36 -0400488 // 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 -0400489 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
490 if err != nil {
491 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
492 }
493
494 // Start reading indications
495 go dh.readIndications()
496 return nil
497 }
498
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400499 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700500 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400501 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700502 return err
503 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400504
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400506 if err != nil || device == nil {
507 /*TODO: needs to handle error scenarios */
508 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400510 }
511 cloned := proto.Clone(device).(*voltha.Device)
512 // Update the all ports (if available) on that device to ACTIVE.
513 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700514 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
515 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400516 return err
517 }
518
Girish Gowdru0c588b22019-04-23 23:24:56 -0400519 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
520 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400522 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400524 }
525 // Instantiate flow manager
526 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
527 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400529 }
530 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400531 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400532 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530533 // Stats config for new device
534 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530535
cuilin20187b2a8c32019-03-26 19:52:28 -0700536 // Start reading indications
537 go dh.readIndications()
538 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530539}
540
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400541func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
542 var err error
543 var deviceInfo *oop.DeviceInfo
544
545 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
546
547 if err != nil {
548 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
549 return nil, err
550 }
551 if deviceInfo == nil {
552 log.Errorw("Device info is nil", log.Fields{})
553 return nil, errors.New("failed to get device info from OLT")
554 }
555
556 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
557 dh.device.Root = true
558 dh.device.Vendor = deviceInfo.Vendor
559 dh.device.Model = deviceInfo.Model
560 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
561 dh.device.HardwareVersion = deviceInfo.HardwareVersion
562 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
563
564 if deviceInfo.DeviceId == "" {
565 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
566 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
567 genmac, err := generateMacFromHost(host)
568 if err != nil {
569 return nil, err
570 }
571 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
572 dh.device.MacAddress = genmac
573 } else {
574 dh.device.MacAddress = deviceInfo.DeviceId
575 }
576
577 // Synchronous call to update device - this method is run in its own go routine
578 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
579 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
580 return nil, err
581 }
582
583 return deviceInfo, nil
584}
585
Naga Manjunath7615e552019-10-11 22:35:47 +0530586func startCollector(dh *DeviceHandler) {
587 // Initial delay for OLT initialization
588 time.Sleep(1 * time.Minute)
589 log.Debugf("Starting-Collector")
590 context := make(map[string]string)
591 for {
592 select {
593 case <-dh.stopCollector:
594 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
595 return
596 default:
597 freq := dh.metrics.ToPmConfigs().DefaultFreq
598 time.Sleep(time.Duration(freq) * time.Second)
599 context["oltid"] = dh.deviceID
600 context["devicetype"] = dh.deviceType
601 // NNI Stats
602 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
603 log.Debugf("Collect-NNI-Metrics %v", cmnni)
604 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
605 log.Debugf("Publish-NNI-Metrics")
606 // PON Stats
607 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
608 for i := uint32(0); i < NumPonPORTS; i++ {
609 cmpon := dh.portStats.collectPONMetrics(i)
610 log.Debugf("Collect-PON-Metrics %v", cmpon)
611
612 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
613 log.Debugf("Publish-PON-Metrics")
614 }
615 }
616 }
617}
618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530620func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400621 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400623 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530624
625 // Now, set the initial PM configuration for that device
626 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
627 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
628 }
629
630 go startCollector(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530631}
632
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530634func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700635 return &ic.SwitchCapability{
636 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530637 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700638 HwDesc: "open_pon",
639 SwDesc: "open_pon",
640 SerialNum: dh.device.SerialNumber,
641 },
642 SwitchFeatures: &of.OfpSwitchFeatures{
643 NBuffers: 256,
644 NTables: 2,
645 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
646 of.OfpCapabilities_OFPC_TABLE_STATS |
647 of.OfpCapabilities_OFPC_PORT_STATS |
648 of.OfpCapabilities_OFPC_GROUP_STATS),
649 },
650 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530651}
652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530654func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700656 return &ic.PortCapability{
657 Port: &voltha.LogicalPort{
658 OfpPort: &of.OfpPort{
659 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
660 Config: 0,
661 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 Curr: capacity,
663 Advertised: capacity,
664 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700665 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
666 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
667 },
668 DeviceId: dh.device.Id,
669 DevicePortNo: uint32(portNo),
670 },
671 }, nil
672}
673
William Kurkianff524662019-08-20 10:34:30 -0400674func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700675 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700676 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 var deviceID string
678 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700679
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700680 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
681 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
683 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700684 kwargs := make(map[string]interface{})
685 kwargs["onu_id"] = omciInd.OnuId
686 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700687
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
689 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400690 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
691 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700692 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 deviceType = onuDevice.Type
694 deviceID = onuDevice.Id
695 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
696 //if not exist in cache, then add to cache.
697 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700698 } else {
699 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700700 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700701 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 deviceID = onuInCache.deviceID
703 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700704 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700705
706 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
707 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
708 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400710 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
711 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700712 }
William Kurkianff524662019-08-20 10:34:30 -0400713 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530714}
715
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700716//ProcessInterAdapterMessage sends the proxied messages to the target device
717// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
718// is meant, and then send the unmarshalled omci message to this onu
719func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
720 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700721 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700722 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700723 fromTopic := msg.Header.FromTopic
724 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 toDeviceID := msg.Header.ToDeviceId
726 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700729
730 msgBody := msg.GetBody()
731
732 omciMsg := &ic.InterAdapterOmciMessage{}
733 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
734 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
735 return err
736 }
737
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700738 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
740 if err != nil {
741 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700742 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700743 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
745 dh.sendProxiedMessage(onuDevice, omciMsg)
746
cuilin20187b2a8c32019-03-26 19:52:28 -0700747 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 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 -0700749 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700750 }
751
752 } else {
753 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
754 }
755 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530756}
757
cuilin20187b2a8c32019-03-26 19:52:28 -0700758func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 var intfID uint32
760 var onuID uint32
761 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700762 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 intfID = onuDevice.ProxyAddress.GetChannelId()
764 onuID = onuDevice.ProxyAddress.GetOnuId()
765 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700766 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 intfID = omciMsg.GetProxyAddress().GetChannelId()
768 onuID = omciMsg.GetProxyAddress().GetOnuId()
769 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700770 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 if connectStatus != voltha.ConnectStatus_REACHABLE {
772 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700773 return
774 }
775
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700777
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
779 if err != nil {
780 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
781 return
782 }
783 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700784}
785
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700786func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
787 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
788 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700789 // TODO: need resource manager
790 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700791 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400793 st, _ := status.FromError(err)
794 if st.Code() == codes.AlreadyExists {
795 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
796 } else {
797 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
798 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700799 } else {
800 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
801 }
802}
803
Matt Jeanneret53539512019-07-20 14:47:02 -0400804func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 channelID := onuDiscInd.GetIntfId()
806 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400807
808 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
809 dh.lockDevice.Lock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400810 if _, ok := dh.discOnus[sn]; ok {
Matt Jeanneret53539512019-07-20 14:47:02 -0400811 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400812 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400813 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700814 }
815
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400816 dh.discOnus[sn] = true
Matt Jeanneret53539512019-07-20 14:47:02 -0400817 log.Debugw("new-discovery-indications-list", log.Fields{"discOnus": dh.discOnus})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400818 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400819
cuilin20187b2a8c32019-03-26 19:52:28 -0700820 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400821 if sn != "" {
822 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400823 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400824 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
825 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400826 }
827
828 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
829 var onuID uint32
830 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700831 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400832 ponintfid := onuDiscInd.GetIntfId()
833 dh.lockDevice.Lock()
834 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
835 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400836 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400837 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
838 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400839 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700840 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400841 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700842 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400843 log.Errorw("Create onu error",
844 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
845 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400846 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400847 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400848 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400849
850 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700851 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400852 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400853 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700854 //Insert the ONU into cache to use in OnuIndication.
855 //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 -0700856 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
857 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700858 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400859
860 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700861 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400862 log.Debugw("new-onu-device-discovered", log.Fields{"onu": dh.onus[onuKey]})
863 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400864
Mahir Gunyele77977b2019-06-27 05:36:22 -0700865 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
866 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400867 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
868 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700869 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700870 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
871 //TODO: We put this sleep here to prevent the race between state update and onuIndication
872 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
873 //then the initialisation fails.
874 time.Sleep(1 * time.Second)
875 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400876 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700877}
878
879func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
880 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
881
882 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700884 var onuDevice *voltha.Device
885 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700886 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
887 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700888 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
889 if onuInCache, ok := dh.onus[onuKey]; ok {
890 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
891 foundInCache = true
892 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700893 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700894 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
895 if serialNumber != "" {
896 kwargs["serial_number"] = serialNumber
897 } else {
898 kwargs["onu_id"] = onuInd.OnuId
899 kwargs["parent_port_no"] = ponPort
900 }
901 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700902 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700903
904 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400905 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 //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 -0400907 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700908 }
909
910 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
911 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})
912 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700913 if !foundInCache {
914 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Matt Jeanneret53539512019-07-20 14:47:02 -0400915 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700916 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400917 dh.lockDevice.Unlock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700918 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700919 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700920
cuilin20187b2a8c32019-03-26 19:52:28 -0700921 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700923 return
924 }
925
926}
927
Scott Baker7eb0a932019-07-26 10:33:22 -0700928func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400929 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 -0700930 dh.updateOnuAdminState(onuInd)
931 // operState
932 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400933 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 -0700934 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
935 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
936 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
937 if err != nil {
938 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
939 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
940 }
941 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700942 // Ignore operstatus if device was found in cache
943 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400944 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 -0700945 return
946 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400947 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
948 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
950 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
951 if err != nil {
952 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +0530953 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 return
955 }
956 } else {
957 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
958 }
959}
960
961func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
962 if onuInd.AdminState == "down" {
963 if onuInd.OperState != "down" {
964 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
965 // Forcing the oper state change code to execute
966 onuInd.OperState = "down"
967 }
968 // Port and logical port update is taken care of by oper state block
969 } else if onuInd.AdminState == "up" {
970 log.Debugln("received-onu-admin-state up")
971 } else {
972 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
973 }
974 log.Debugln("admin-state-dealt-with")
975}
976
cuilin20187b2a8c32019-03-26 19:52:28 -0700977func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
978 if serialNum != nil {
979 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700980 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700982}
983
984func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
985 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700987 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
988 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
989 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
990 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
991 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
992 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
993 return tmp
994}
995
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996//UpdateFlowsBulk upates the bulk flow
997func (dh *DeviceHandler) UpdateFlowsBulk() error {
998 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700999}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000
1001//GetChildDevice returns the child device for given parent port and onu id
1002func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1003 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001004 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001006 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001008 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001009 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001010 return nil
1011 }
1012 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1013 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301014}
1015
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001016// SendPacketInToCore sends packet-in to core
1017// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1018// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001019func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
1020 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001022 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
1023 return
1024 }
1025 log.Debug("Sent packet-in to core successfully")
1026}
1027
A R Karthick1f85b802019-10-11 05:06:05 +00001028// AddUniPortToOnu adds the uni port to the onu device
1029func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1030 onuKey := dh.formOnuKey(intfID, onuID)
1031 dh.lockDevice.Lock()
1032 defer dh.lockDevice.Unlock()
1033 if onuDevice, ok := dh.onus[onuKey]; ok {
1034 // add it to the uniPort map for the onu device
1035 if _, ok = onuDevice.uniPorts[uniPort]; !ok {
1036 onuDevice.uniPorts[uniPort] = struct{}{}
1037 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1038 }
1039 }
1040}
1041
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001042//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001043func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1044 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 -04001045 if flows != nil {
1046 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001047 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001048 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001049 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001050 for _, flow := range flows.ToRemove.Items {
1051 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1052 dh.flowMgr.RemoveFlow(flow)
1053 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001054 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001056 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001058 // dh.flowMgr.RemoveFlow(flow)
1059 }
1060 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001061 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001062 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301063}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001065//DisableDevice disables the given device
1066//It marks the following for the given device:
1067//Device-Handler Admin-State : down
1068//Device Port-State: UNKNOWN
1069//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001070func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001071 /* On device disable ,admin state update has to be done prior sending request to agent since
1072 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001073 dh.lockDevice.Lock()
1074 dh.adminState = "down"
1075 dh.lockDevice.Unlock()
Chaitrashree G S44124192019-08-07 20:21:36 -04001076 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001077 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1078 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err})
1079 dh.lockDevice.Lock()
1080 dh.adminState = "up"
1081 dh.lockDevice.Unlock()
1082 return err
1083 }
1084
Chaitrashree G S44124192019-08-07 20:21:36 -04001085 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001086 log.Debug("olt-disabled")
Chaitrashree G S44124192019-08-07 20:21:36 -04001087 dh.lockDevice.Lock()
1088 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
1089 UNREACHABLE state which needs to be configured again*/
1090 dh.discOnus = make(map[string]bool)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001091 dh.onus = make(map[string]*OnuDevice)
Chaitrashree G S44124192019-08-07 20:21:36 -04001092 dh.lockDevice.Unlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001093 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001094 cloned := proto.Clone(device).(*voltha.Device)
1095 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1097 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001098 return err
1099 }
1100
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001101 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001102 return nil
1103}
1104
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001105func (dh *DeviceHandler) notifyChildDevices() {
1106
1107 // Update onu state as unreachable in onu adapter
1108 onuInd := oop.OnuIndication{}
1109 onuInd.OperState = "unreachable"
1110 //get the child device for the parent device
1111 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1112 if err != nil {
1113 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1114 }
1115 if onuDevices != nil {
1116 for _, onuDevice := range onuDevices.Items {
1117 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1118 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1119 if err != nil {
1120 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1121 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1122 }
1123
1124 }
1125 }
1126
1127}
1128
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129//ReenableDevice re-enables the olt device after disable
1130//It marks the following for the given device:
1131//Device-Handler Admin-State : up
1132//Device Port-State: ACTIVE
1133//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001134func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1135 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001136 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1137 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1138 return err
1139 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001140 }
1141
1142 dh.lockDevice.Lock()
1143 dh.adminState = "up"
1144 dh.lockDevice.Unlock()
1145 log.Debug("olt-reenabled")
1146
1147 cloned := proto.Clone(device).(*voltha.Device)
1148 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1150 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001151 return err
1152 }
1153
1154 //Update the device oper status as ACTIVE
1155 cloned.OperStatus = voltha.OperStatus_ACTIVE
1156 dh.device = cloned
1157
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1159 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001160 return err
1161 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001163
1164 return nil
1165}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001166
A R Karthick1f85b802019-10-11 05:06:05 +00001167func (dh *DeviceHandler) clearUNIData(onu *OnuDevice) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001168 var uniID uint32
1169 var err error
A R Karthick1f85b802019-10-11 05:06:05 +00001170 for port := range onu.uniPorts {
1171 delete(onu.uniPorts, port)
1172 uniID = UniIDFromPortNum(port)
1173 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1174 /* Delete tech-profile instance from the KV store */
Gamze Abakafee36392019-10-03 11:17:24 +00001175 if err = dh.flowMgr.DeleteTechProfileInstances(onu.intfID, onu.onuID, uniID, onu.serialNumber); err != nil {
A R Karthick1f85b802019-10-11 05:06:05 +00001176 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001177 }
A R Karthick1f85b802019-10-11 05:06:05 +00001178 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
1179 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.intfID, onu.onuID, uniID)
1180 for _, flowID := range flowIDs {
1181 dh.resourceMgr.FreeFlowID(onu.intfID, int32(onu.onuID), int32(uniID), flowID)
1182 }
1183 dh.resourceMgr.FreePONResourcesForONU(onu.intfID, onu.onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001184 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.intfID, onu.onuID, uniID); err != nil {
A R Karthick1f85b802019-10-11 05:06:05 +00001185 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
1186 }
1187 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001188 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.intfID, onu.onuID, uniID)
1189 for _, tpID := range tpIDList {
1190 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.intfID, onu.onuID, uniID, tpID); err != nil {
1191 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
1192 }
1193 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
1194 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.intfID, onu.onuID, uniID, tpID); err != nil {
1195 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
1196 }
1197 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001198 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001199 }
1200 return nil
1201}
1202
1203func (dh *DeviceHandler) clearNNIData() error {
1204 nniUniID := -1
1205 nniOnuID := -1
1206 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
1207 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1208 for _, flowID := range flowIDs {
1209 dh.resourceMgr.FreeFlowID(uint32(dh.nniIntfID), -1, -1, uint32(flowID))
1210 }
1211 //Free the flow-ids for the NNI port
1212 dh.resourceMgr.FreePONResourcesForONU(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
1213 /* Free ONU IDs for each pon port
1214 intfIDToONUIds is a map of intf-id: [onu-ids]*/
1215 intfIDToONUIds := make(map[uint32][]uint32)
1216 for _, onu := range dh.onus {
1217 intfIDToONUIds[onu.intfID] = append(intfIDToONUIds[onu.intfID], onu.onuID)
1218 }
1219 for intfID, onuIds := range intfIDToONUIds {
1220 dh.resourceMgr.FreeonuID(intfID, onuIds)
1221 }
1222 return nil
1223}
1224
1225// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1226func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1227 log.Debug("Function entry delete device")
1228 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001229 if dh.adminState == "deleted" {
1230 dh.lockDevice.Unlock()
1231 return nil
1232 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001233 dh.adminState = "deleted"
1234 dh.lockDevice.Unlock()
1235 /* Clear the KV store data associated with the all the UNI ports
1236 This clears up flow data and also resource map data for various
1237 other pon resources like alloc_id and gemport_id
1238 */
1239 for _, onu := range dh.onus {
A R Karthick1f85b802019-10-11 05:06:05 +00001240 if err := dh.clearUNIData(onu); err != nil {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001241 log.Debugw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1242 }
1243 }
1244 /* Clear the flows from KV store associated with NNI port.
1245 There are mostly trap rules from NNI port (like LLDP)
1246 */
1247 if err := dh.clearNNIData(); err != nil {
1248 log.Debugw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
1249 }
A R Karthick1f85b802019-10-11 05:06:05 +00001250
1251 /* Clear the resource pool for each PON port in the background */
1252 go dh.resourceMgr.Delete()
1253
Devmalya Paul495b94a2019-08-27 19:42:00 -04001254 /*Delete ONU map for the device*/
1255 for onu := range dh.onus {
1256 delete(dh.onus, onu)
1257 }
1258 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301259 // Stop the Stats collector
1260 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001261 //Reset the state
1262 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1263 log.Errorw("Failed-to-reboot-olt ", log.Fields{"err": err})
1264 return err
1265 }
1266 cloned := proto.Clone(device).(*voltha.Device)
1267 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1268 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1269 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1270 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1271 return err
1272 }
1273 return nil
1274}
1275
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001276//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001277func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1278 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1279 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
1280 return err
1281 }
1282
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001284
1285 return nil
1286}
1287
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001288func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1289 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1290 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1291 if err != nil {
1292 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1293 return
1294 }
1295 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001297 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1298 return
1299 }
1300 log.Debug("Success sending packet-in to core!")
1301}
1302
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1304func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001305 log.Debugw("incoming-packet-out", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo,
1306 "pkt-length": len(packet.Data), "packetData": hex.EncodeToString(packet.Data)})
1307
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001309 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001310 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1311 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1312 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1313 if innerEthType == 0x8100 {
1314 // q-in-q 802.1ad or 802.1q double tagged packet.
1315 // slice out the outer tag.
1316 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1317 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001318 }
1319 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1321 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001322 uniID := UniIDFromPortNum(uint32(egressPortNo))
1323
1324 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1325 if err != nil {
1326 // In this case the openolt agent will receive the gemPortID as 0.
1327 // The agent tries to retrieve the gemPortID in this case.
1328 // This may not always succeed at the agent and packetOut may fail.
1329 log.Error("failed-to-retrieve-gemport-id-for-packet-out")
1330 }
1331
1332 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001333
1334 log.Debugw("sending-packet-to-onu", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
Manikkaraj kb1d51442019-07-23 10:41:02 -04001335 "uniID": uniID, "gemPortID": gemPortID, "packet": hex.EncodeToString(packet.Data)})
Matt Jeanneret1359c732019-08-01 21:40:02 -04001336
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001337 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1338 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1339 return err
1340 }
1341 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001343
1344 log.Debugw("sending-packet-to-nni", log.Fields{"uplink_pkt": uplinkPkt, "packet": hex.EncodeToString(packet.Data)})
1345
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001346 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001347 log.Errorw("Error while sending packet-out to NNI", log.Fields{"error": err})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001348 return err
1349 }
1350 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{"egress_port_no": egressPortNo, "egressPortType": egressPortType})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001352 }
1353 return nil
1354}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001355
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1357 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001358}