blob: d6505c2686e78709030e19a85d2b7aca050ea24a [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()
358 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700774
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
776 if err != nil {
777 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
778 return
779 }
780 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700781}
782
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
784 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
785 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700786 // TODO: need resource manager
787 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700788 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530789 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400790 st, _ := status.FromError(err)
791 if st.Code() == codes.AlreadyExists {
792 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
793 } else {
794 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
795 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700796 } else {
797 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
798 }
799}
800
Matt Jeanneret53539512019-07-20 14:47:02 -0400801func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 channelID := onuDiscInd.GetIntfId()
803 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400804
805 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530806
807 if _, ok := dh.discOnus.Load(sn); ok {
808
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400809 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400810 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700811 }
812
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530813 dh.discOnus.Store(sn, true)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400814
cuilin20187b2a8c32019-03-26 19:52:28 -0700815 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400816 if sn != "" {
817 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400818 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400819 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
820 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400821 }
822
823 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
824 var onuID uint32
825 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700826 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400827 ponintfid := onuDiscInd.GetIntfId()
828 dh.lockDevice.Lock()
829 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
830 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400831 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400832 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
833 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400834 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700835 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400836 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700837 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400838 log.Errorw("Create onu error",
839 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
840 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400841 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400842 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400843 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400844
845 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700846 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400847 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400848 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700849 //Insert the ONU into cache to use in OnuIndication.
850 //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 -0700851 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
852 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700853 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400854
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530855 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
856 dh.onus.Store(onuKey, onuDev)
857 log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400858
Mahir Gunyele77977b2019-06-27 05:36:22 -0700859 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
860 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400861 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
862 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700863 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700864 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
865 //TODO: We put this sleep here to prevent the race between state update and onuIndication
866 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
867 //then the initialisation fails.
868 time.Sleep(1 * time.Second)
869 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400870 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700871}
872
873func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
874 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
875
876 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700877 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700878 var onuDevice *voltha.Device
879 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700880 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
881 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700882 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530883
884 if onuInCache, ok := dh.onus.Load(onuKey); ok {
885
Mahir Gunyele77977b2019-06-27 05:36:22 -0700886 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
887 foundInCache = true
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530888 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700890 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
891 if serialNumber != "" {
892 kwargs["serial_number"] = serialNumber
893 } else {
894 kwargs["onu_id"] = onuInd.OnuId
895 kwargs["parent_port_no"] = ponPort
896 }
897 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700898 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700899
900 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400901 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700902 //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 -0400903 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700904 }
905
906 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
907 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})
908 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700909 if !foundInCache {
910 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530911
912 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
913
Mahir Gunyele77977b2019-06-27 05:36:22 -0700914 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700915 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700916
cuilin20187b2a8c32019-03-26 19:52:28 -0700917 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700919 return
920 }
921
922}
923
Scott Baker7eb0a932019-07-26 10:33:22 -0700924func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400925 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 -0700926 dh.updateOnuAdminState(onuInd)
927 // operState
928 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400929 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 -0700930 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
931 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
932 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
933 if err != nil {
934 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
935 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
936 }
937 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700938 // Ignore operstatus if device was found in cache
939 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400940 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 -0700941 return
942 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400943 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
944 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700945 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
946 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
947 if err != nil {
948 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
Naga Manjunath7615e552019-10-11 22:35:47 +0530949 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 return
951 }
952 } else {
953 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
954 }
955}
956
957func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
958 if onuInd.AdminState == "down" {
959 if onuInd.OperState != "down" {
960 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
961 // Forcing the oper state change code to execute
962 onuInd.OperState = "down"
963 }
964 // Port and logical port update is taken care of by oper state block
965 } else if onuInd.AdminState == "up" {
966 log.Debugln("received-onu-admin-state up")
967 } else {
968 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
969 }
970 log.Debugln("admin-state-dealt-with")
971}
972
cuilin20187b2a8c32019-03-26 19:52:28 -0700973func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
974 if serialNum != nil {
975 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700976 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700978}
979
980func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
981 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700982 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700983 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
984 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
985 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
986 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
987 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
988 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
989 return tmp
990}
991
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992//UpdateFlowsBulk upates the bulk flow
993func (dh *DeviceHandler) UpdateFlowsBulk() error {
994 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700995}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996
997//GetChildDevice returns the child device for given parent port and onu id
998func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
999 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001000 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001002 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001004 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001006 return nil
1007 }
1008 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1009 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +05301010}
1011
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012// SendPacketInToCore sends packet-in to core
1013// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1014// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001015func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001016 log.Debugw("send-packet-in-to-core", log.Fields{
1017 "port": logicalPort,
1018 "packet": hex.EncodeToString(packetPayload),
1019 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001021 log.Errorw("Error sending packetin to core", log.Fields{
1022 "error": err,
1023 "packet": hex.EncodeToString(packetPayload),
1024 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001025 return
1026 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001027 log.Debugw("Sent packet-in to core successfully", log.Fields{
1028 "packet": hex.EncodeToString(packetPayload),
1029 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001030}
1031
A R Karthick1f85b802019-10-11 05:06:05 +00001032// AddUniPortToOnu adds the uni port to the onu device
1033func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1034 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301035
1036 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001037 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301038 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1039 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001040 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1041 }
1042 }
1043}
1044
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001045//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001046func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1047 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 -04001048 if flows != nil {
1049 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001050 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001051 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001052 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001053 for _, flow := range flows.ToRemove.Items {
1054 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1055 dh.flowMgr.RemoveFlow(flow)
1056 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001057 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001058 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001059 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001060 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001061 // dh.flowMgr.RemoveFlow(flow)
1062 }
1063 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001064 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001065 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301066}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068//DisableDevice disables the given device
1069//It marks the following for the given device:
1070//Device-Handler Admin-State : down
1071//Device Port-State: UNKNOWN
1072//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001073func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001074 /* On device disable ,admin state update has to be done prior sending request to agent since
1075 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001076 dh.lockDevice.Lock()
1077 dh.adminState = "down"
1078 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001079 if dh.Client != nil {
1080 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1081 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1082 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1083 dh.lockDevice.Lock()
1084 dh.adminState = "up"
1085 dh.lockDevice.Unlock()
1086 return err
1087 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001088 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001089 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001090 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001091 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001092 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301093
1094 dh.discOnus = sync.Map{}
1095 dh.onus = sync.Map{}
1096
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001097 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001098 cloned := proto.Clone(device).(*voltha.Device)
1099 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1101 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001102 return err
1103 }
1104
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001105 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001106 return nil
1107}
1108
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001109func (dh *DeviceHandler) notifyChildDevices() {
1110
1111 // Update onu state as unreachable in onu adapter
1112 onuInd := oop.OnuIndication{}
1113 onuInd.OperState = "unreachable"
1114 //get the child device for the parent device
1115 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1116 if err != nil {
1117 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1118 }
1119 if onuDevices != nil {
1120 for _, onuDevice := range onuDevices.Items {
1121 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1122 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1123 if err != nil {
1124 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1125 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1126 }
1127
1128 }
1129 }
1130
1131}
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133//ReenableDevice re-enables the olt device after disable
1134//It marks the following for the given device:
1135//Device-Handler Admin-State : up
1136//Device Port-State: ACTIVE
1137//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001138func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1139 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001140 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1141 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1142 return err
1143 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001144 }
1145
1146 dh.lockDevice.Lock()
1147 dh.adminState = "up"
1148 dh.lockDevice.Unlock()
1149 log.Debug("olt-reenabled")
1150
1151 cloned := proto.Clone(device).(*voltha.Device)
1152 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1154 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001155 return err
1156 }
1157
1158 //Update the device oper status as ACTIVE
1159 cloned.OperStatus = voltha.OperStatus_ACTIVE
1160 dh.device = cloned
1161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1163 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001164 return err
1165 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001166 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001167
1168 return nil
1169}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001170
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301171func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001172 var uniID uint32
1173 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301174 for _, port := range onu.UniPorts {
1175 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001176 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1177 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301178 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1179 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001180 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301181 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1182 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001183 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301184 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001185 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301186 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001187 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301188 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1189 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001190 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301191 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1192 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1193 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001194 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301195 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1196 }
1197 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1198 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1199 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1200 }
1201 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1202 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1203 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 +00001204 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001205 }
1206 return nil
1207}
1208
1209func (dh *DeviceHandler) clearNNIData() error {
1210 nniUniID := -1
1211 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301212
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001213 if dh.resourceMgr == nil {
1214 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1215 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001216 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301217 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1218 if err != nil {
1219 log.Error("Failed to fetch nni from kv store")
1220 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001221 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301222 log.Debugw("NNI are ", log.Fields{"nni": nni})
1223 for _, nniIntfID := range nni {
1224 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1225 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1226 for _, flowID := range flowIDs {
1227 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1228 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001229 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301230 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1231 log.Error("Failed to clear nni from kv store")
1232 return err
1233 }
1234 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001235}
1236
1237// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1238func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1239 log.Debug("Function entry delete device")
1240 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001241 if dh.adminState == "deleted" {
1242 dh.lockDevice.Unlock()
1243 return nil
1244 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001245 dh.adminState = "deleted"
1246 dh.lockDevice.Unlock()
1247 /* Clear the KV store data associated with the all the UNI ports
1248 This clears up flow data and also resource map data for various
1249 other pon resources like alloc_id and gemport_id
1250 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001251 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301252 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1253 var ponPort uint32
1254 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1255 var onuGemData []rsrcMgr.OnuGemInfo
1256 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1257 if err != nil {
1258 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1259 return err
1260 }
1261 for _, onu := range onuGemData {
1262 log.Debugw("onu data ", log.Fields{"onu": onu})
1263 if err = dh.clearUNIData(&onu); err != nil {
1264 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1265 }
1266 }
1267 onuGemData = nil
1268 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1269 if err != nil {
1270 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001271 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001272 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001273 /* Clear the flows from KV store associated with NNI port.
1274 There are mostly trap rules from NNI port (like LLDP)
1275 */
1276 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301277 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001278 }
A R Karthick1f85b802019-10-11 05:06:05 +00001279
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001280 /* Clear the resource pool for each PON port in the background */
1281 go dh.resourceMgr.Delete()
1282 }
A R Karthick1f85b802019-10-11 05:06:05 +00001283
Devmalya Paul495b94a2019-08-27 19:42:00 -04001284 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301285 dh.onus.Range(func(key interface{}, value interface{}) bool {
1286 dh.onus.Delete(key)
1287 return true
1288 })
1289
Devmalya Paul495b94a2019-08-27 19:42:00 -04001290 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301291 // Stop the Stats collector
1292 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001293 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001294 if dh.Client != nil {
1295 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1296 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1297 return err
1298 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001299 }
1300 cloned := proto.Clone(device).(*voltha.Device)
1301 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1302 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1303 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1304 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1305 return err
1306 }
1307 return nil
1308}
1309
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001311func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1312 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001313 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001314 return err
1315 }
1316
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001318
1319 return nil
1320}
1321
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001322func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001323 log.Debugw("Received packet-in", log.Fields{
1324 "packet-indication": *packetIn,
1325 "packet": hex.EncodeToString(packetIn.Pkt),
1326 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001327 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1328 if err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001329 log.Errorw("Error getting logical port from packet-in", log.Fields{
1330 "error": err,
1331 "packet": hex.EncodeToString(packetIn.Pkt),
1332 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001333 return
1334 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001335 log.Debugw("sending packet-in to core", log.Fields{
1336 "logicalPortNum": logicalPortNum,
1337 "packet": hex.EncodeToString(packetIn.Pkt),
1338 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001340 log.Errorw("Error sending packet-in to core", log.Fields{
1341 "error": err,
1342 "packet": hex.EncodeToString(packetIn.Pkt),
1343 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001344 return
1345 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001346 log.Debugw("Success sending packet-in to core!", log.Fields{
1347 "packet": hex.EncodeToString(packetIn.Pkt),
1348 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001349}
1350
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1352func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001353 log.Debugw("incoming-packet-out", log.Fields{
1354 "deviceID": dh.deviceID,
1355 "egress_port_no": egressPortNo,
1356 "pkt-length": len(packet.Data),
1357 "packet": hex.EncodeToString(packet.Data),
1358 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001359
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001361 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001362 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1363 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301364 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1365 // Do not packet-out lldp packets on uni port.
1366 // ONOS has no clue about uni/nni ports, it just packets out on all
1367 // available ports on the Logical Switch. It should not be interested
1368 // in the UNI links.
1369 log.Debug("dropping-lldp-packet-out-on-uni")
1370 return nil
1371 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001372 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1373 if innerEthType == 0x8100 {
1374 // q-in-q 802.1ad or 802.1q double tagged packet.
1375 // slice out the outer tag.
1376 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1377 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001378 }
1379 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1381 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001382 uniID := UniIDFromPortNum(uint32(egressPortNo))
1383
1384 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1385 if err != nil {
1386 // In this case the openolt agent will receive the gemPortID as 0.
1387 // The agent tries to retrieve the gemPortID in this case.
1388 // This may not always succeed at the agent and packetOut may fail.
Matteo Scandolo6056e822019-11-13 14:05:29 -08001389 log.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
1390 "packet": hex.EncodeToString(packet.Data),
1391 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001392 }
1393
1394 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001395
Matteo Scandolo6056e822019-11-13 14:05:29 -08001396 log.Debugw("sending-packet-to-onu", log.Fields{
1397 "egress_port_no": egressPortNo,
1398 "IntfId": intfID,
1399 "onuID": onuID,
1400 "uniID": uniID,
1401 "gemPortID": gemPortID,
1402 "packet": hex.EncodeToString(packet.Data),
1403 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001404
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001405 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001406 log.Errorw("Error while sending packet-out to ONU", log.Fields{
1407 "error": err,
1408 "packet": hex.EncodeToString(packet.Data),
1409 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001410 return err
1411 }
1412 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001414
Matteo Scandolo6056e822019-11-13 14:05:29 -08001415 log.Debugw("sending-packet-to-nni", log.Fields{
1416 "uplink_pkt": uplinkPkt,
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.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001421 log.Errorw("Error while sending packet-out to NNI", 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 {
Matteo Scandolo6056e822019-11-13 14:05:29 -08001428 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
1429 "egress_port_no": egressPortNo,
1430 "egressPortType": egressPortType,
1431 "packet": hex.EncodeToString(packet.Data),
1432 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001433 }
1434 return nil
1435}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001436
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001437func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1438 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001439}