blob: 80d706abb8b2fb9059a33e69b005d9bab4433942 [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"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080040 "github.com/opencord/voltha-protos/v2/go/common"
41 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
42 of "github.com/opencord/voltha-protos/v2/go/openflow_13"
43 oop "github.com/opencord/voltha-protos/v2/go/openolt"
44 "github.com/opencord/voltha-protos/v2/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
Naga Manjunatha8dc9372019-10-31 23:01:18 +053077
78 discOnus sync.Map
79 onus sync.Map
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)
133 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530134 dh.stopCollector = make(chan bool, 2)
135 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
cuilin20187b2a8c32019-03-26 19:52:28 -0700136 //TODO initialize the support classes.
137 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530138}
139
140// start save the device to the data model
141func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700142 dh.lockDevice.Lock()
143 defer dh.lockDevice.Unlock()
144 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
145 // Add the initial device to the local model
146 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530147}
148
149// stop stops the device dh. Not much to do for now
150func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700151 dh.lockDevice.Lock()
152 defer dh.lockDevice.Unlock()
153 log.Debug("stopping-device-agent")
154 dh.exitChannel <- 1
155 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530156}
157
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400158func macifyIP(ip net.IP) string {
159 if len(ip) > 0 {
160 oct1 := strconv.FormatInt(int64(ip[12]), 16)
161 oct2 := strconv.FormatInt(int64(ip[13]), 16)
162 oct3 := strconv.FormatInt(int64(ip[14]), 16)
163 oct4 := strconv.FormatInt(int64(ip[15]), 16)
164 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
165 }
166 return ""
167}
168
169func generateMacFromHost(host string) (string, error) {
170 var genmac string
171 var addr net.IP
172 var ips []string
173 var err error
174
175 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
176
177 if addr = net.ParseIP(host); addr == nil {
178 log.Debugw("looking-up-hostname", log.Fields{"host": host})
179
180 if ips, err = net.LookupHost(host); err == nil {
181 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
182 if addr = net.ParseIP(ips[0]); addr == nil {
183 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
184 return "", errors.New("unable-to-parse-ip")
185 }
186 genmac = macifyIP(addr)
187 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
188 return genmac, nil
189 }
190 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
191 return "", err
192 }
193
194 genmac = macifyIP(addr)
195 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
196 return genmac, nil
197}
198
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530199func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700200 slist := strings.Split(mac, ":")
201 result := make([]uint32, len(slist))
202 var err error
203 var tmp int64
204 for index, val := range slist {
205 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
206 return []uint32{1, 2, 3, 4, 5, 6}
207 }
208 result[index] = uint32(tmp)
209 }
210 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530211}
212
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700213//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 +0530214func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530215
Girish Gowdru0c588b22019-04-23 23:24:56 -0400216 if portType == voltha.Port_ETHERNET_NNI {
217 return fmt.Sprintf("nni-%d", portNum)
218 } else if portType == voltha.Port_PON_OLT {
219 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 } else if portType == voltha.Port_ETHERNET_UNI {
221 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400222 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700223 }
224 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530225}
226
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700228 var operStatus common.OperStatus_OperStatus
229 if state == "up" {
230 operStatus = voltha.OperStatus_ACTIVE
231 } else {
232 operStatus = voltha.OperStatus_DISCOVERED
233 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400235 label := GetportLabel(portNum, portType)
236 if len(label) == 0 {
237 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
238 return
239 }
240 // Now create Port
241 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700242 PortNo: portNum,
243 Label: label,
244 Type: portType,
245 OperStatus: operStatus,
246 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400247 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700248 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700249 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
250 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400251 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530252}
253
254// readIndications to read the indications from the OLT device
255func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400256 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400257 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if err != nil {
259 log.Errorw("Failed to read indications", log.Fields{"err": err})
260 return
261 }
262 if indications == nil {
263 log.Errorw("Indications is nil", log.Fields{})
264 return
265 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400266 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400268 if err != nil || device == nil {
269 /*TODO: needs to handle error scenarios */
270 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400272 }
273 // When the device is in DISABLED and Adapter container restarts, we need to
274 // rebuild the locally maintained admin state.
275 if device.AdminState == voltha.AdminState_DISABLED {
276 dh.lockDevice.Lock()
277 dh.adminState = "down"
278 dh.lockDevice.Unlock()
279 }
280
cuilin20187b2a8c32019-03-26 19:52:28 -0700281 for {
282 indication, err := indications.Recv()
283 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530284 log.Infow("EOF for indications", log.Fields{"err": err})
285 indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
286 if err != nil {
287 log.Errorw("Failed to read indications", log.Fields{"err": err})
288 return
289 }
290 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 }
292 if err != nil {
293 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400294 if dh.adminState == "deleted" {
295 log.Debug("Device deleted stoping the read indication thread")
296 break
297 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400298 dh.transitionMap.Handle(DeviceDownInd)
299 dh.transitionMap.Handle(DeviceInit)
300 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700301 }
Chaitrashree G S44124192019-08-07 20:21:36 -0400302 dh.lockDevice.RLock()
303 adminState := dh.adminState
304 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400305 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400306 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530307
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400308 log.Infow("olt is admin down, ignore indication", log.Fields{})
309 continue
310 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700311 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530312
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700313 }
314}
315
316func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000317 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000318 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319 dh.transitionMap.Handle(DeviceUpInd)
320 } else if oltIndication.OperState == "down" {
321 dh.transitionMap.Handle(DeviceDownInd)
322 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000323 // Send or clear Alarm
324 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700325}
326
327func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400328 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700329 switch indication.Data.(type) {
330 case *oop.Indication_OltInd:
331 dh.handleOltIndication(indication.GetOltInd())
332 case *oop.Indication_IntfInd:
333 intfInd := indication.GetIntfInd()
334 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
335 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
336 case *oop.Indication_IntfOperInd:
337 intfOperInd := indication.GetIntfOperInd()
338 if intfOperInd.GetType() == "nni" {
339 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530340 dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700341 } else if intfOperInd.GetType() == "pon" {
342 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
343 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000344 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700345 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700346 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
347 case *oop.Indication_OnuDiscInd:
348 onuDiscInd := indication.GetOnuDiscInd()
349 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700350 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400351 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700352 case *oop.Indication_OnuInd:
353 onuInd := indication.GetOnuInd()
354 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
355 go dh.onuIndication(onuInd)
356 case *oop.Indication_OmciInd:
357 omciInd := indication.GetOmciInd()
lcuie24ef182019-04-29 22:58:36 -0700358 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 -0400359 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700360 case *oop.Indication_PktInd:
361 pktInd := indication.GetPktInd()
362 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
363 go dh.handlePacketIndication(pktInd)
364 case *oop.Indication_PortStats:
365 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530366 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700367 case *oop.Indication_FlowStats:
368 flowStats := indication.GetFlowStats()
369 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
370 case *oop.Indication_AlarmInd:
371 alarmInd := indication.GetAlarmInd()
372 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530373 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700374 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530375}
376
377// doStateUp handle the olt up indication and update to voltha core
378func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400379 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700380 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400381 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700382 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 -0400383 return err
384 }
385 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530386}
387
388// doStateDown handle the olt down indication
389func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700390 dh.lockDevice.Lock()
391 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400392 log.Debug("do-state-down-start")
393
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700394 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400395 if err != nil || device == nil {
396 /*TODO: needs to handle error scenarios */
397 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700398 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400399 }
400
401 cloned := proto.Clone(device).(*voltha.Device)
402 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
404 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
405 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400406 }
407
408 //Update the device oper state and connection status
409 cloned.OperStatus = voltha.OperStatus_UNKNOWN
410 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
411 dh.device = cloned
412
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700413 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
414 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
415 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400416 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400417
418 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700419 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400420 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700421 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400422 return err
423 }
424 for _, onuDevice := range onuDevices.Items {
425
426 // Update onu state as down in onu adapter
427 onuInd := oop.OnuIndication{}
428 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700429 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
430 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
431 if er != nil {
432 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
433 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700434 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700435 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400436 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700437 /* Discovered ONUs entries need to be cleared , since after OLT
438 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530439 dh.discOnus = sync.Map{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700441 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530442}
443
444// doStateInit dial the grpc before going to init state
445func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400446 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400447 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400448 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400450 return err
451 }
452 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530453}
454
455// postInit create olt client instance to invoke RPC on the olt device
456func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400457 dh.Client = oop.NewOpenoltClient(dh.clientCon)
458 dh.transitionMap.Handle(GrpcConnected)
459 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530460}
461
462// doStateConnected get the device info and update to voltha core
463func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400464 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400465
466 // Case where OLT is disabled and then rebooted.
467 if dh.adminState == "down" {
468 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400470 if err != nil || device == nil {
471 /*TODO: needs to handle error scenarios */
472 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
473 }
474
475 cloned := proto.Clone(device).(*voltha.Device)
476 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
477 cloned.OperStatus = voltha.OperStatus_UNKNOWN
478 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
480 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400481 }
482
Chaitrashree G S44124192019-08-07 20:21:36 -0400483 // 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 -0400484 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
485 if err != nil {
486 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
487 }
488
489 // Start reading indications
490 go dh.readIndications()
491 return nil
492 }
493
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400494 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700495 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400496 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700497 return err
498 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400499
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400501 if err != nil || device == nil {
502 /*TODO: needs to handle error scenarios */
503 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400505 }
506 cloned := proto.Clone(device).(*voltha.Device)
507 // Update the all ports (if available) on that device to ACTIVE.
508 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
510 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400511 return err
512 }
513
Girish Gowdru0c588b22019-04-23 23:24:56 -0400514 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
515 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700516 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400517 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700518 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400519 }
520 // Instantiate flow manager
521 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
522 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400524 }
525 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400526 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400527 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530528 // Stats config for new device
529 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530530
cuilin20187b2a8c32019-03-26 19:52:28 -0700531 // Start reading indications
532 go dh.readIndications()
533 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530534}
535
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400536func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
537 var err error
538 var deviceInfo *oop.DeviceInfo
539
540 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
541
542 if err != nil {
543 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
544 return nil, err
545 }
546 if deviceInfo == nil {
547 log.Errorw("Device info is nil", log.Fields{})
548 return nil, errors.New("failed to get device info from OLT")
549 }
550
551 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
552 dh.device.Root = true
553 dh.device.Vendor = deviceInfo.Vendor
554 dh.device.Model = deviceInfo.Model
555 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
556 dh.device.HardwareVersion = deviceInfo.HardwareVersion
557 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
558
559 if deviceInfo.DeviceId == "" {
560 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
561 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
562 genmac, err := generateMacFromHost(host)
563 if err != nil {
564 return nil, err
565 }
566 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
567 dh.device.MacAddress = genmac
568 } else {
569 dh.device.MacAddress = deviceInfo.DeviceId
570 }
571
572 // Synchronous call to update device - this method is run in its own go routine
573 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
574 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
575 return nil, err
576 }
577
578 return deviceInfo, nil
579}
580
Naga Manjunath7615e552019-10-11 22:35:47 +0530581func startCollector(dh *DeviceHandler) {
582 // Initial delay for OLT initialization
583 time.Sleep(1 * time.Minute)
584 log.Debugf("Starting-Collector")
585 context := make(map[string]string)
586 for {
587 select {
588 case <-dh.stopCollector:
589 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
590 return
591 default:
592 freq := dh.metrics.ToPmConfigs().DefaultFreq
593 time.Sleep(time.Duration(freq) * time.Second)
594 context["oltid"] = dh.deviceID
595 context["devicetype"] = dh.deviceType
596 // NNI Stats
597 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
598 log.Debugf("Collect-NNI-Metrics %v", cmnni)
599 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
600 log.Debugf("Publish-NNI-Metrics")
601 // PON Stats
602 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
603 for i := uint32(0); i < NumPonPORTS; i++ {
604 cmpon := dh.portStats.collectPONMetrics(i)
605 log.Debugf("Collect-PON-Metrics %v", cmpon)
606
607 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
608 log.Debugf("Publish-PON-Metrics")
609 }
610 }
611 }
612}
613
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530615func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400616 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400618 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530619
620 // Now, set the initial PM configuration for that device
621 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
622 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
623 }
624
625 go startCollector(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530626}
627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530629func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700630 return &ic.SwitchCapability{
631 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530632 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700633 HwDesc: "open_pon",
634 SwDesc: "open_pon",
635 SerialNum: dh.device.SerialNumber,
636 },
637 SwitchFeatures: &of.OfpSwitchFeatures{
638 NBuffers: 256,
639 NTables: 2,
640 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
641 of.OfpCapabilities_OFPC_TABLE_STATS |
642 of.OfpCapabilities_OFPC_PORT_STATS |
643 of.OfpCapabilities_OFPC_GROUP_STATS),
644 },
645 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530646}
647
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530649func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700651 return &ic.PortCapability{
652 Port: &voltha.LogicalPort{
653 OfpPort: &of.OfpPort{
654 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
655 Config: 0,
656 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 Curr: capacity,
658 Advertised: capacity,
659 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700660 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
661 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
662 },
663 DeviceId: dh.device.Id,
664 DevicePortNo: uint32(portNo),
665 },
666 }, nil
667}
668
William Kurkianff524662019-08-20 10:34:30 -0400669func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700671 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 var deviceID string
673 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700674
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700675 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530676
677 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
678
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700679 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
680 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700681 kwargs := make(map[string]interface{})
682 kwargs["onu_id"] = omciInd.OnuId
683 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
686 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400687 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
688 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700689 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 deviceType = onuDevice.Type
691 deviceID = onuDevice.Id
692 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
693 //if not exist in cache, then add to cache.
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530694 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700695 } else {
696 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530698 deviceType = onuInCache.(*OnuDevice).deviceType
699 deviceID = onuInCache.(*OnuDevice).deviceID
700 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700701 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700702
703 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
704 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
705 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400707 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
708 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700709 }
William Kurkianff524662019-08-20 10:34:30 -0400710 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530711}
712
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713//ProcessInterAdapterMessage sends the proxied messages to the target device
714// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
715// is meant, and then send the unmarshalled omci message to this onu
716func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
717 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700718 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700719 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700720 fromTopic := msg.Header.FromTopic
721 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700722 toDeviceID := msg.Header.ToDeviceId
723 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700724
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700726
727 msgBody := msg.GetBody()
728
729 omciMsg := &ic.InterAdapterOmciMessage{}
730 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
731 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
732 return err
733 }
734
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700735 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
737 if err != nil {
738 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700739 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700740 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
742 dh.sendProxiedMessage(onuDevice, omciMsg)
743
cuilin20187b2a8c32019-03-26 19:52:28 -0700744 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 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 -0700746 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700747 }
748
749 } else {
750 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
751 }
752 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530753}
754
cuilin20187b2a8c32019-03-26 19:52:28 -0700755func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700756 var intfID uint32
757 var onuID uint32
758 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700759 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700760 intfID = onuDevice.ProxyAddress.GetChannelId()
761 onuID = onuDevice.ProxyAddress.GetOnuId()
762 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700763 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 intfID = omciMsg.GetProxyAddress().GetChannelId()
765 onuID = omciMsg.GetProxyAddress().GetOnuId()
766 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700767 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 if connectStatus != voltha.ConnectStatus_REACHABLE {
769 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700770 return
771 }
772
lcuie24ef182019-04-29 22:58:36 -0700773 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
774 isHexString := false
775 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
776 if decodeerr == nil {
777 isHexString = true
778 }
779
780 // 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.
781 var omciMessage *oop.OmciMsg
782 if isHexString {
783 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
784 } else {
785 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
786 hex.Encode(hexPkt, omciMsg.Message)
787 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
788 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700789
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700790 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
791 if err != nil {
792 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
793 return
794 }
lcuie24ef182019-04-29 22:58:36 -0700795 log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700796}
797
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700798func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
799 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
800 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700801 // TODO: need resource manager
802 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700803 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530804 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400805 st, _ := status.FromError(err)
806 if st.Code() == codes.AlreadyExists {
807 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
808 } else {
809 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
810 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700811 } else {
812 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
813 }
814}
815
Matt Jeanneret53539512019-07-20 14:47:02 -0400816func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 channelID := onuDiscInd.GetIntfId()
818 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400819
820 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530821
822 if _, ok := dh.discOnus.Load(sn); ok {
823
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400824 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400825 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700826 }
827
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530828 dh.discOnus.Store(sn, true)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400829
cuilin20187b2a8c32019-03-26 19:52:28 -0700830 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400831 if sn != "" {
832 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400833 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400834 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
835 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400836 }
837
838 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
839 var onuID uint32
840 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700841 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400842 ponintfid := onuDiscInd.GetIntfId()
843 dh.lockDevice.Lock()
844 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
845 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400846 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400847 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
848 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400849 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700850 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400851 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700852 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400853 log.Errorw("Create onu error",
854 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
855 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400856 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400857 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400858 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400859
860 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700861 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400862 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400863 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700864 //Insert the ONU into cache to use in OnuIndication.
865 //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 -0700866 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
867 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700868 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400869
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530870 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
871 dh.onus.Store(onuKey, onuDev)
872 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400873
Mahir Gunyele77977b2019-06-27 05:36:22 -0700874 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
875 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400876 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
877 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700878 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700879 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
880 //TODO: We put this sleep here to prevent the race between state update and onuIndication
881 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
882 //then the initialisation fails.
883 time.Sleep(1 * time.Second)
884 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400885 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700886}
887
888func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
889 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
890
891 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700893 var onuDevice *voltha.Device
894 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700895 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
896 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700897 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530898
899 if onuInCache, ok := dh.onus.Load(onuKey); ok {
900
Mahir Gunyele77977b2019-06-27 05:36:22 -0700901 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
902 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530903 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700904 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700905 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
906 if serialNumber != "" {
907 kwargs["serial_number"] = serialNumber
908 } else {
909 kwargs["onu_id"] = onuInd.OnuId
910 kwargs["parent_port_no"] = ponPort
911 }
912 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700913 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700914
915 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400916 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917 //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 -0400918 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700919 }
920
921 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
922 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})
923 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700924 if !foundInCache {
925 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530926
927 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
928
Mahir Gunyele77977b2019-06-27 05:36:22 -0700929 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700930 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700931
cuilin20187b2a8c32019-03-26 19:52:28 -0700932 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700934 return
935 }
936
937}
938
Scott Baker7eb0a932019-07-26 10:33:22 -0700939func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400940 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 -0700941 dh.updateOnuAdminState(onuInd)
942 // operState
943 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400944 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 -0700945 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
946 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
947 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
948 if err != nil {
949 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
950 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
951 }
952 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700953 // Ignore operstatus if device was found in cache
954 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400955 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 -0700956 return
957 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400958 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
959 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
961 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
962 if err != nil {
963 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +0530964 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 return
966 }
967 } else {
968 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
969 }
970}
971
972func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
973 if onuInd.AdminState == "down" {
974 if onuInd.OperState != "down" {
975 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
976 // Forcing the oper state change code to execute
977 onuInd.OperState = "down"
978 }
979 // Port and logical port update is taken care of by oper state block
980 } else if onuInd.AdminState == "up" {
981 log.Debugln("received-onu-admin-state up")
982 } else {
983 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
984 }
985 log.Debugln("admin-state-dealt-with")
986}
987
cuilin20187b2a8c32019-03-26 19:52:28 -0700988func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
989 if serialNum != nil {
990 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700991 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700993}
994
995func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
996 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700998 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
999 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1000 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1001 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1002 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1003 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1004 return tmp
1005}
1006
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007//UpdateFlowsBulk upates the bulk flow
1008func (dh *DeviceHandler) UpdateFlowsBulk() error {
1009 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -07001010}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011
1012//GetChildDevice returns the child device for given parent port and onu id
1013func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
1014 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001015 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001016 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001017 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001019 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001021 return nil
1022 }
1023 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1024 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301025}
1026
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027// SendPacketInToCore sends packet-in to core
1028// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1029// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001030func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001031 log.Debugw("send-packet-in-to-core", log.Fields{
1032 "port": logicalPort,
1033 "packet": hex.EncodeToString(packetPayload),
1034 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001036 log.Errorw("Error sending packetin to core", log.Fields{
1037 "error": err,
1038 "packet": hex.EncodeToString(packetPayload),
1039 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001040 return
1041 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001042 log.Debugw("Sent packet-in to core successfully", log.Fields{
1043 "packet": hex.EncodeToString(packetPayload),
1044 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001045}
1046
A R Karthick1f85b802019-10-11 05:06:05 +00001047// AddUniPortToOnu adds the uni port to the onu device
1048func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1049 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301050
1051 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001052 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301053 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1054 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001055 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1056 }
1057 }
1058}
1059
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001060//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001061func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1062 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 -04001063 if flows != nil {
1064 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001065 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001066 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001067 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001068 for _, flow := range flows.ToRemove.Items {
1069 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1070 dh.flowMgr.RemoveFlow(flow)
1071 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001072 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001073 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001074 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001076 // dh.flowMgr.RemoveFlow(flow)
1077 }
1078 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001079 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001080 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301081}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083//DisableDevice disables the given device
1084//It marks the following for the given device:
1085//Device-Handler Admin-State : down
1086//Device Port-State: UNKNOWN
1087//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001088func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001089 /* On device disable ,admin state update has to be done prior sending request to agent since
1090 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001091 dh.lockDevice.Lock()
1092 dh.adminState = "down"
1093 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001094 if dh.Client != nil {
1095 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1096 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1097 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1098 dh.lockDevice.Lock()
1099 dh.adminState = "up"
1100 dh.lockDevice.Unlock()
1101 return err
1102 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001103 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001104 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001105 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001106 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001107 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301108
1109 dh.discOnus = sync.Map{}
1110 dh.onus = sync.Map{}
1111
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001112 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001113 cloned := proto.Clone(device).(*voltha.Device)
1114 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1116 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001117 return err
1118 }
1119
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001120 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001121 return nil
1122}
1123
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001124func (dh *DeviceHandler) notifyChildDevices() {
1125
1126 // Update onu state as unreachable in onu adapter
1127 onuInd := oop.OnuIndication{}
1128 onuInd.OperState = "unreachable"
1129 //get the child device for the parent device
1130 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1131 if err != nil {
1132 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1133 }
1134 if onuDevices != nil {
1135 for _, onuDevice := range onuDevices.Items {
1136 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1137 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1138 if err != nil {
1139 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1140 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1141 }
1142
1143 }
1144 }
1145
1146}
1147
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001148//ReenableDevice re-enables the olt device after disable
1149//It marks the following for the given device:
1150//Device-Handler Admin-State : up
1151//Device Port-State: ACTIVE
1152//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001153func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1154 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001155 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1156 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1157 return err
1158 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001159 }
1160
1161 dh.lockDevice.Lock()
1162 dh.adminState = "up"
1163 dh.lockDevice.Unlock()
1164 log.Debug("olt-reenabled")
1165
1166 cloned := proto.Clone(device).(*voltha.Device)
1167 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1169 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001170 return err
1171 }
1172
1173 //Update the device oper status as ACTIVE
1174 cloned.OperStatus = voltha.OperStatus_ACTIVE
1175 dh.device = cloned
1176
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001177 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1178 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001179 return err
1180 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001182
1183 return nil
1184}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001185
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301186func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001187 var uniID uint32
1188 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301189 for _, port := range onu.UniPorts {
1190 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001191 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1192 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301193 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1194 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001195 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301196 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1197 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001198 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301199 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001200 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301201 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001202 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301203 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1204 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001205 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301206 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1207 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1208 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001209 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301210 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1211 }
1212 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1213 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1214 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1215 }
1216 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1217 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1218 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 +00001219 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001220 }
1221 return nil
1222}
1223
1224func (dh *DeviceHandler) clearNNIData() error {
1225 nniUniID := -1
1226 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301227
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001228 if dh.resourceMgr == nil {
1229 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1230 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001231 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301232 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1233 if err != nil {
1234 log.Error("Failed to fetch nni from kv store")
1235 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001236 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301237 log.Debugw("NNI are ", log.Fields{"nni": nni})
1238 for _, nniIntfID := range nni {
1239 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1240 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1241 for _, flowID := range flowIDs {
1242 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1243 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001244 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1246 log.Error("Failed to clear nni from kv store")
1247 return err
1248 }
1249 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001250}
1251
1252// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1253func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1254 log.Debug("Function entry delete device")
1255 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001256 if dh.adminState == "deleted" {
1257 dh.lockDevice.Unlock()
1258 return nil
1259 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001260 dh.adminState = "deleted"
1261 dh.lockDevice.Unlock()
1262 /* Clear the KV store data associated with the all the UNI ports
1263 This clears up flow data and also resource map data for various
1264 other pon resources like alloc_id and gemport_id
1265 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001266 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301267 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1268 var ponPort uint32
1269 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1270 var onuGemData []rsrcMgr.OnuGemInfo
1271 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1272 if err != nil {
1273 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1274 return err
1275 }
1276 for _, onu := range onuGemData {
1277 log.Debugw("onu data ", log.Fields{"onu": onu})
1278 if err = dh.clearUNIData(&onu); err != nil {
1279 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1280 }
1281 }
1282 onuGemData = nil
1283 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1284 if err != nil {
1285 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001286 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001287 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001288 /* Clear the flows from KV store associated with NNI port.
1289 There are mostly trap rules from NNI port (like LLDP)
1290 */
1291 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301292 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001293 }
A R Karthick1f85b802019-10-11 05:06:05 +00001294
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001295 /* Clear the resource pool for each PON port in the background */
1296 go dh.resourceMgr.Delete()
1297 }
A R Karthick1f85b802019-10-11 05:06:05 +00001298
Devmalya Paul495b94a2019-08-27 19:42:00 -04001299 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301300 dh.onus.Range(func(key interface{}, value interface{}) bool {
1301 dh.onus.Delete(key)
1302 return true
1303 })
1304
Devmalya Paul495b94a2019-08-27 19:42:00 -04001305 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301306 // Stop the Stats collector
1307 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001308 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001309 if dh.Client != nil {
1310 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1311 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1312 return err
1313 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001314 }
1315 cloned := proto.Clone(device).(*voltha.Device)
1316 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1317 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1318 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1319 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1320 return err
1321 }
1322 return nil
1323}
1324
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001325//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001326func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1327 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001328 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001329 return err
1330 }
1331
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001332 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001333
1334 return nil
1335}
1336
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001337func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001338 log.Debugw("Received packet-in", log.Fields{
1339 "packet-indication": *packetIn,
1340 "packet": hex.EncodeToString(packetIn.Pkt),
1341 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001342 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1343 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001344 log.Errorw("Error getting logical port from packet-in", log.Fields{
1345 "error": err,
1346 "packet": hex.EncodeToString(packetIn.Pkt),
1347 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001348 return
1349 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001350 log.Debugw("sending packet-in to core", log.Fields{
1351 "logicalPortNum": logicalPortNum,
1352 "packet": hex.EncodeToString(packetIn.Pkt),
1353 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001355 log.Errorw("Error sending packet-in to core", log.Fields{
1356 "error": err,
1357 "packet": hex.EncodeToString(packetIn.Pkt),
1358 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001359 return
1360 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001361 log.Debugw("Success sending packet-in to core!", log.Fields{
1362 "packet": hex.EncodeToString(packetIn.Pkt),
1363 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001364}
1365
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1367func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001368 log.Debugw("incoming-packet-out", log.Fields{
1369 "deviceID": dh.deviceID,
1370 "egress_port_no": egressPortNo,
1371 "pkt-length": len(packet.Data),
1372 "packet": hex.EncodeToString(packet.Data),
1373 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001374
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001376 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001377 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1378 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301379 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1380 // Do not packet-out lldp packets on uni port.
1381 // ONOS has no clue about uni/nni ports, it just packets out on all
1382 // available ports on the Logical Switch. It should not be interested
1383 // in the UNI links.
1384 log.Debug("dropping-lldp-packet-out-on-uni")
1385 return nil
1386 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001387 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1388 if innerEthType == 0x8100 {
1389 // q-in-q 802.1ad or 802.1q double tagged packet.
1390 // slice out the outer tag.
1391 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1392 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001393 }
1394 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1396 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001397 uniID := UniIDFromPortNum(uint32(egressPortNo))
1398
1399 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1400 if err != nil {
1401 // In this case the openolt agent will receive the gemPortID as 0.
1402 // The agent tries to retrieve the gemPortID in this case.
1403 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001404 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1405 "packet": hex.EncodeToString(packet.Data),
1406 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001407 }
1408
1409 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001410
Matteo Scandolo6056e822019-11-13 14:05:29 -08001411 log.Debugw("sending-packet-to-onu", log.Fields{
1412 "egress_port_no": egressPortNo,
1413 "IntfId": intfID,
1414 "onuID": onuID,
1415 "uniID": uniID,
1416 "gemPortID": gemPortID,
1417 "packet": hex.EncodeToString(packet.Data),
1418 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001419
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001420 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001421 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1422 "error": err,
1423 "packet": hex.EncodeToString(packet.Data),
1424 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001425 return err
1426 }
1427 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001429
Matteo Scandolo6056e822019-11-13 14:05:29 -08001430 log.Debugw("sending-packet-to-nni", log.Fields{
1431 "uplink_pkt": uplinkPkt,
1432 "packet": hex.EncodeToString(packet.Data),
1433 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001434
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001435 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001436 log.Errorw("Error while sending packet-out to NNI", log.Fields{
1437 "error": err,
1438 "packet": hex.EncodeToString(packet.Data),
1439 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001440 return err
1441 }
1442 } else {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001443 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1444 "egress_port_no": egressPortNo,
1445 "egressPortType": egressPortType,
1446 "packet": hex.EncodeToString(packet.Data),
1447 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001448 }
1449 return nil
1450}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001451
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1453 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001454}