blob: 26b62b330a0f97984e6914543314a71a2561a744 [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
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040077 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070078 onus map[string]*OnuDevice
Naga Manjunath7615e552019-10-11 22:35:47 +053079 portStats *OpenOltStatisticsMgr
80 metrics *pmmetrics.PmMetrics
81 stopCollector chan bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070082}
83
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070087 deviceType string
88 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 onuID uint32
90 intfID uint32
91 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000092 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070093}
94
Naga Manjunath7615e552019-10-11 22:35:47 +053095var pmNames = []string{
96 "rx_bytes",
97 "rx_packets",
98 "rx_mcast_packets",
99 "rx_bcast_packets",
100 "tx_bytes",
101 "tx_packets",
102 "tx_mcast_packets",
103 "tx_bcast_packets",
104}
105
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110 device.deviceType = deviceTp
111 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 device.onuID = onuID
113 device.intfID = intfID
114 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000115 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530117}
118
119//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530120func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700121 var dh DeviceHandler
122 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400123 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400124 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700125 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400128 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.device = cloned
130 dh.openOLT = adapter
131 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400132 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700133 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134 dh.onus = make(map[string]*OnuDevice)
Naga Manjunath7615e552019-10-11 22:35:47 +0530135 dh.stopCollector = make(chan bool, 2)
136 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
cuilin20187b2a8c32019-03-26 19:52:28 -0700137 //TODO initialize the support classes.
138 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530139}
140
141// start save the device to the data model
142func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700143 dh.lockDevice.Lock()
144 defer dh.lockDevice.Unlock()
145 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
146 // Add the initial device to the local model
147 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530148}
149
150// stop stops the device dh. Not much to do for now
151func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 dh.lockDevice.Lock()
153 defer dh.lockDevice.Unlock()
154 log.Debug("stopping-device-agent")
155 dh.exitChannel <- 1
156 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530157}
158
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400159func macifyIP(ip net.IP) string {
160 if len(ip) > 0 {
161 oct1 := strconv.FormatInt(int64(ip[12]), 16)
162 oct2 := strconv.FormatInt(int64(ip[13]), 16)
163 oct3 := strconv.FormatInt(int64(ip[14]), 16)
164 oct4 := strconv.FormatInt(int64(ip[15]), 16)
165 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
166 }
167 return ""
168}
169
170func generateMacFromHost(host string) (string, error) {
171 var genmac string
172 var addr net.IP
173 var ips []string
174 var err error
175
176 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
177
178 if addr = net.ParseIP(host); addr == nil {
179 log.Debugw("looking-up-hostname", log.Fields{"host": host})
180
181 if ips, err = net.LookupHost(host); err == nil {
182 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
183 if addr = net.ParseIP(ips[0]); addr == nil {
184 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
185 return "", errors.New("unable-to-parse-ip")
186 }
187 genmac = macifyIP(addr)
188 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
189 return genmac, nil
190 }
191 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
192 return "", err
193 }
194
195 genmac = macifyIP(addr)
196 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
197 return genmac, nil
198}
199
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530200func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 slist := strings.Split(mac, ":")
202 result := make([]uint32, len(slist))
203 var err error
204 var tmp int64
205 for index, val := range slist {
206 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
207 return []uint32{1, 2, 3, 4, 5, 6}
208 }
209 result[index] = uint32(tmp)
210 }
211 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530212}
213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214//GetportLabel returns the label for the NNI and the PON port based on port number and port type
manikkaraj kbf256be2019-03-25 00:13:48 +0530215func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530216
Girish Gowdru0c588b22019-04-23 23:24:56 -0400217 if portType == voltha.Port_ETHERNET_NNI {
218 return fmt.Sprintf("nni-%d", portNum)
219 } else if portType == voltha.Port_PON_OLT {
220 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 } else if portType == voltha.Port_ETHERNET_UNI {
222 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400223 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 }
225 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 var operStatus common.OperStatus_OperStatus
230 if state == "up" {
231 operStatus = voltha.OperStatus_ACTIVE
232 } else {
233 operStatus = voltha.OperStatus_DISCOVERED
234 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400236 label := GetportLabel(portNum, portType)
237 if len(label) == 0 {
238 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
239 return
240 }
241 // Now create Port
242 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700243 PortNo: portNum,
244 Label: label,
245 Type: portType,
246 OperStatus: operStatus,
247 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400248 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700249 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700250 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
251 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400252 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
255// readIndications to read the indications from the OLT device
256func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400257 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400258 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700259 if err != nil {
260 log.Errorw("Failed to read indications", log.Fields{"err": err})
261 return
262 }
263 if indications == nil {
264 log.Errorw("Indications is nil", log.Fields{})
265 return
266 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400267 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400269 if err != nil || device == nil {
270 /*TODO: needs to handle error scenarios */
271 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400273 }
274 // When the device is in DISABLED and Adapter container restarts, we need to
275 // rebuild the locally maintained admin state.
276 if device.AdminState == voltha.AdminState_DISABLED {
277 dh.lockDevice.Lock()
278 dh.adminState = "down"
279 dh.lockDevice.Unlock()
280 }
281
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 for {
283 indication, err := indications.Recv()
284 if err == io.EOF {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530285 log.Infow("EOF for indications", log.Fields{"err": err})
286 indications, err = dh.Client.EnableIndication(context.Background(), new(oop.Empty))
287 if err != nil {
288 log.Errorw("Failed to read indications", log.Fields{"err": err})
289 return
290 }
291 continue
cuilin20187b2a8c32019-03-26 19:52:28 -0700292 }
293 if err != nil {
294 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400295 if dh.adminState == "deleted" {
296 log.Debug("Device deleted stoping the read indication thread")
297 break
298 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400299 dh.transitionMap.Handle(DeviceDownInd)
300 dh.transitionMap.Handle(DeviceInit)
301 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700302 }
Chaitrashree G S44124192019-08-07 20:21:36 -0400303 dh.lockDevice.RLock()
304 adminState := dh.adminState
305 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400306 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400307 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400309 log.Infow("olt is admin down, ignore indication", log.Fields{})
310 continue
311 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700312 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530313
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700314 }
315}
316
317func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000318 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000319 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700320 dh.transitionMap.Handle(DeviceUpInd)
321 } else if oltIndication.OperState == "down" {
322 dh.transitionMap.Handle(DeviceDownInd)
323 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000324 // Send or clear Alarm
325 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700326}
327
328func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400329 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700330 switch indication.Data.(type) {
331 case *oop.Indication_OltInd:
332 dh.handleOltIndication(indication.GetOltInd())
333 case *oop.Indication_IntfInd:
334 intfInd := indication.GetIntfInd()
335 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
336 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
337 case *oop.Indication_IntfOperInd:
338 intfOperInd := indication.GetIntfOperInd()
339 if intfOperInd.GetType() == "nni" {
340 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530341 dh.resourceMgr.AddNNIToKVStore(intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700342 } else if intfOperInd.GetType() == "pon" {
343 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
344 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000345 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700346 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700347 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
348 case *oop.Indication_OnuDiscInd:
349 onuDiscInd := indication.GetOnuDiscInd()
350 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700351 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400352 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700353 case *oop.Indication_OnuInd:
354 onuInd := indication.GetOnuInd()
355 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
356 go dh.onuIndication(onuInd)
357 case *oop.Indication_OmciInd:
358 omciInd := indication.GetOmciInd()
359 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
William Kurkianff524662019-08-20 10:34:30 -0400360 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700361 case *oop.Indication_PktInd:
362 pktInd := indication.GetPktInd()
363 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
364 go dh.handlePacketIndication(pktInd)
365 case *oop.Indication_PortStats:
366 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530367 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 case *oop.Indication_FlowStats:
369 flowStats := indication.GetFlowStats()
370 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
371 case *oop.Indication_AlarmInd:
372 alarmInd := indication.GetAlarmInd()
373 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530374 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700375 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376}
377
378// doStateUp handle the olt up indication and update to voltha core
379func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400380 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700381 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400382 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700383 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 -0400384 return err
385 }
386 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530387}
388
389// doStateDown handle the olt down indication
390func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700391 dh.lockDevice.Lock()
392 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400393 log.Debug("do-state-down-start")
394
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700395 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400396 if err != nil || device == nil {
397 /*TODO: needs to handle error scenarios */
398 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700399 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400400 }
401
402 cloned := proto.Clone(device).(*voltha.Device)
403 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700404 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
405 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
406 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400407 }
408
409 //Update the device oper state and connection status
410 cloned.OperStatus = voltha.OperStatus_UNKNOWN
411 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
412 dh.device = cloned
413
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700414 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
415 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
416 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400417 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400418
419 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400421 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700422 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400423 return err
424 }
425 for _, onuDevice := range onuDevices.Items {
426
427 // Update onu state as down in onu adapter
428 onuInd := oop.OnuIndication{}
429 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
431 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
432 if er != nil {
433 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
434 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700435 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400437 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700438 /* Discovered ONUs entries need to be cleared , since after OLT
439 is up, it starts sending discovery indications again*/
440 dh.discOnus = make(map[string]bool)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700441 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700442 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530443}
444
445// doStateInit dial the grpc before going to init state
446func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400447 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400448 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400449 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700450 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400451 return err
452 }
453 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530454}
455
456// postInit create olt client instance to invoke RPC on the olt device
457func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400458 dh.Client = oop.NewOpenoltClient(dh.clientCon)
459 dh.transitionMap.Handle(GrpcConnected)
460 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530461}
462
463// doStateConnected get the device info and update to voltha core
464func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400465 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400466
467 // Case where OLT is disabled and then rebooted.
468 if dh.adminState == "down" {
469 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700470 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400471 if err != nil || device == nil {
472 /*TODO: needs to handle error scenarios */
473 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
474 }
475
476 cloned := proto.Clone(device).(*voltha.Device)
477 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
478 cloned.OperStatus = voltha.OperStatus_UNKNOWN
479 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
481 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400482 }
483
Chaitrashree G S44124192019-08-07 20:21:36 -0400484 // 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 -0400485 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
486 if err != nil {
487 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
488 }
489
490 // Start reading indications
491 go dh.readIndications()
492 return nil
493 }
494
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400495 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700496 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400497 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700498 return err
499 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400500
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400502 if err != nil || device == nil {
503 /*TODO: needs to handle error scenarios */
504 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400506 }
507 cloned := proto.Clone(device).(*voltha.Device)
508 // Update the all ports (if available) on that device to ACTIVE.
509 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700510 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
511 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400512 return err
513 }
514
Girish Gowdru0c588b22019-04-23 23:24:56 -0400515 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
516 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400518 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400520 }
521 // Instantiate flow manager
522 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
523 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400525 }
526 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400527 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400528 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Naga Manjunath7615e552019-10-11 22:35:47 +0530529 // Stats config for new device
530 dh.portStats = NewOpenOltStatsMgr(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530531
cuilin20187b2a8c32019-03-26 19:52:28 -0700532 // Start reading indications
533 go dh.readIndications()
534 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530535}
536
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400537func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
538 var err error
539 var deviceInfo *oop.DeviceInfo
540
541 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
542
543 if err != nil {
544 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
545 return nil, err
546 }
547 if deviceInfo == nil {
548 log.Errorw("Device info is nil", log.Fields{})
549 return nil, errors.New("failed to get device info from OLT")
550 }
551
552 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
553 dh.device.Root = true
554 dh.device.Vendor = deviceInfo.Vendor
555 dh.device.Model = deviceInfo.Model
556 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
557 dh.device.HardwareVersion = deviceInfo.HardwareVersion
558 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
559
560 if deviceInfo.DeviceId == "" {
561 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
562 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
563 genmac, err := generateMacFromHost(host)
564 if err != nil {
565 return nil, err
566 }
567 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
568 dh.device.MacAddress = genmac
569 } else {
570 dh.device.MacAddress = deviceInfo.DeviceId
571 }
572
573 // Synchronous call to update device - this method is run in its own go routine
574 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
575 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
576 return nil, err
577 }
578
579 return deviceInfo, nil
580}
581
Naga Manjunath7615e552019-10-11 22:35:47 +0530582func startCollector(dh *DeviceHandler) {
583 // Initial delay for OLT initialization
584 time.Sleep(1 * time.Minute)
585 log.Debugf("Starting-Collector")
586 context := make(map[string]string)
587 for {
588 select {
589 case <-dh.stopCollector:
590 log.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
591 return
592 default:
593 freq := dh.metrics.ToPmConfigs().DefaultFreq
594 time.Sleep(time.Duration(freq) * time.Second)
595 context["oltid"] = dh.deviceID
596 context["devicetype"] = dh.deviceType
597 // NNI Stats
598 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
599 log.Debugf("Collect-NNI-Metrics %v", cmnni)
600 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
601 log.Debugf("Publish-NNI-Metrics")
602 // PON Stats
603 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
604 for i := uint32(0); i < NumPonPORTS; i++ {
605 cmpon := dh.portStats.collectPONMetrics(i)
606 log.Debugf("Collect-PON-Metrics %v", cmpon)
607
608 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
609 log.Debugf("Publish-PON-Metrics")
610 }
611 }
612 }
613}
614
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530616func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400617 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400619 dh.transitionMap.Handle(DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530620
621 // Now, set the initial PM configuration for that device
622 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
623 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
624 }
625
626 go startCollector(dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530627}
628
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530630func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700631 return &ic.SwitchCapability{
632 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530633 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700634 HwDesc: "open_pon",
635 SwDesc: "open_pon",
636 SerialNum: dh.device.SerialNumber,
637 },
638 SwitchFeatures: &of.OfpSwitchFeatures{
639 NBuffers: 256,
640 NTables: 2,
641 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
642 of.OfpCapabilities_OFPC_TABLE_STATS |
643 of.OfpCapabilities_OFPC_PORT_STATS |
644 of.OfpCapabilities_OFPC_GROUP_STATS),
645 },
646 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530647}
648
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530650func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700652 return &ic.PortCapability{
653 Port: &voltha.LogicalPort{
654 OfpPort: &of.OfpPort{
655 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
656 Config: 0,
657 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 Curr: capacity,
659 Advertised: capacity,
660 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700661 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
662 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
663 },
664 DeviceId: dh.device.Id,
665 DevicePortNo: uint32(portNo),
666 },
667 }, nil
668}
669
William Kurkianff524662019-08-20 10:34:30 -0400670func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700672 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 var deviceID string
674 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700675
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700676 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
677 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
679 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700680 kwargs := make(map[string]interface{})
681 kwargs["onu_id"] = omciInd.OnuId
682 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700683
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
685 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400686 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
687 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700688 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689 deviceType = onuDevice.Type
690 deviceID = onuDevice.Id
691 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
692 //if not exist in cache, then add to cache.
693 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700694 } else {
695 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700696 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700697 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 deviceID = onuInCache.deviceID
699 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700700 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700701
702 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
703 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
704 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400706 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
707 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700708 }
William Kurkianff524662019-08-20 10:34:30 -0400709 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530710}
711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712//ProcessInterAdapterMessage sends the proxied messages to the target device
713// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
714// is meant, and then send the unmarshalled omci message to this onu
715func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
716 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700717 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700718 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700719 fromTopic := msg.Header.FromTopic
720 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 toDeviceID := msg.Header.ToDeviceId
722 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700723
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700725
726 msgBody := msg.GetBody()
727
728 omciMsg := &ic.InterAdapterOmciMessage{}
729 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
730 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
731 return err
732 }
733
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700734 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
736 if err != nil {
737 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700738 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700739 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
741 dh.sendProxiedMessage(onuDevice, omciMsg)
742
cuilin20187b2a8c32019-03-26 19:52:28 -0700743 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 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 -0700745 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700746 }
747
748 } else {
749 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
750 }
751 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530752}
753
cuilin20187b2a8c32019-03-26 19:52:28 -0700754func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 var intfID uint32
756 var onuID uint32
757 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700758 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 intfID = onuDevice.ProxyAddress.GetChannelId()
760 onuID = onuDevice.ProxyAddress.GetOnuId()
761 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700762 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 intfID = omciMsg.GetProxyAddress().GetChannelId()
764 onuID = omciMsg.GetProxyAddress().GetOnuId()
765 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700766 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 if connectStatus != voltha.ConnectStatus_REACHABLE {
768 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700769 return
770 }
771
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700773
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
775 if err != nil {
776 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
777 return
778 }
779 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700780}
781
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
783 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
784 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700785 // TODO: need resource manager
786 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530788 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400789 st, _ := status.FromError(err)
790 if st.Code() == codes.AlreadyExists {
791 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
792 } else {
793 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
794 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700795 } else {
796 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
797 }
798}
799
Matt Jeanneret53539512019-07-20 14:47:02 -0400800func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 channelID := onuDiscInd.GetIntfId()
802 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400803
804 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
805 dh.lockDevice.Lock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400806 if _, ok := dh.discOnus[sn]; ok {
Matt Jeanneret53539512019-07-20 14:47:02 -0400807 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400808 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400809 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700810 }
811
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400812 dh.discOnus[sn] = true
Matt Jeanneret53539512019-07-20 14:47:02 -0400813 log.Debugw("new-discovery-indications-list", log.Fields{"discOnus": dh.discOnus})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400814 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400815
cuilin20187b2a8c32019-03-26 19:52:28 -0700816 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400817 if sn != "" {
818 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400819 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400820 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
821 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400822 }
823
824 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
825 var onuID uint32
826 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700827 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400828 ponintfid := onuDiscInd.GetIntfId()
829 dh.lockDevice.Lock()
830 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
831 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400832 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400833 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
834 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400835 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700836 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400837 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700838 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400839 log.Errorw("Create onu error",
840 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
841 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400842 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400843 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400844 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400845
846 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700847 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400848 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400849 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700850 //Insert the ONU into cache to use in OnuIndication.
851 //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 -0700852 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
853 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700854 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400855
856 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700857 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400858 log.Debugw("new-onu-device-discovered", log.Fields{"onu": dh.onus[onuKey]})
859 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400860
Mahir Gunyele77977b2019-06-27 05:36:22 -0700861 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
862 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400863 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
864 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700865 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700866 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
867 //TODO: We put this sleep here to prevent the race between state update and onuIndication
868 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
869 //then the initialisation fails.
870 time.Sleep(1 * time.Second)
871 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400872 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700873}
874
875func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
876 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
877
878 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700880 var onuDevice *voltha.Device
881 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700882 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
883 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700884 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
885 if onuInCache, ok := dh.onus[onuKey]; ok {
886 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
887 foundInCache = true
888 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.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())
Matt Jeanneret53539512019-07-20 14:47:02 -0400911 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700912 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400913 dh.lockDevice.Unlock()
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) {
1016 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001018 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
1019 return
1020 }
1021 log.Debug("Sent packet-in to core successfully")
1022}
1023
A R Karthick1f85b802019-10-11 05:06:05 +00001024// AddUniPortToOnu adds the uni port to the onu device
1025func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1026 onuKey := dh.formOnuKey(intfID, onuID)
1027 dh.lockDevice.Lock()
1028 defer dh.lockDevice.Unlock()
1029 if onuDevice, ok := dh.onus[onuKey]; ok {
1030 // add it to the uniPort map for the onu device
1031 if _, ok = onuDevice.uniPorts[uniPort]; !ok {
1032 onuDevice.uniPorts[uniPort] = struct{}{}
1033 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1034 }
1035 }
1036}
1037
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001039func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1040 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 -04001041 if flows != nil {
1042 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001043 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001044 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001045 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001046 for _, flow := range flows.ToRemove.Items {
1047 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1048 dh.flowMgr.RemoveFlow(flow)
1049 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001050 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001052 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001053 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001054 // dh.flowMgr.RemoveFlow(flow)
1055 }
1056 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001057 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001058 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301059}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061//DisableDevice disables the given device
1062//It marks the following for the given device:
1063//Device-Handler Admin-State : down
1064//Device Port-State: UNKNOWN
1065//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001066func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001067 /* On device disable ,admin state update has to be done prior sending request to agent since
1068 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001069 dh.lockDevice.Lock()
1070 dh.adminState = "down"
1071 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001072 if dh.Client != nil {
1073 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1074 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1075 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1076 dh.lockDevice.Lock()
1077 dh.adminState = "up"
1078 dh.lockDevice.Unlock()
1079 return err
1080 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001081 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001082 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001083 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001084 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001085 UNREACHABLE state which needs to be configured again*/
1086 dh.lockDevice.Lock()
Chaitrashree G S44124192019-08-07 20:21:36 -04001087 dh.discOnus = make(map[string]bool)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001088 dh.onus = make(map[string]*OnuDevice)
Chaitrashree G S44124192019-08-07 20:21:36 -04001089 dh.lockDevice.Unlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001090 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001091 cloned := proto.Clone(device).(*voltha.Device)
1092 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001093 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1094 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001095 return err
1096 }
1097
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001098 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001099 return nil
1100}
1101
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001102func (dh *DeviceHandler) notifyChildDevices() {
1103
1104 // Update onu state as unreachable in onu adapter
1105 onuInd := oop.OnuIndication{}
1106 onuInd.OperState = "unreachable"
1107 //get the child device for the parent device
1108 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1109 if err != nil {
1110 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1111 }
1112 if onuDevices != nil {
1113 for _, onuDevice := range onuDevices.Items {
1114 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1115 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1116 if err != nil {
1117 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1118 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1119 }
1120
1121 }
1122 }
1123
1124}
1125
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001126//ReenableDevice re-enables the olt device after disable
1127//It marks the following for the given device:
1128//Device-Handler Admin-State : up
1129//Device Port-State: ACTIVE
1130//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001131func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1132 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001133 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1134 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1135 return err
1136 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001137 }
1138
1139 dh.lockDevice.Lock()
1140 dh.adminState = "up"
1141 dh.lockDevice.Unlock()
1142 log.Debug("olt-reenabled")
1143
1144 cloned := proto.Clone(device).(*voltha.Device)
1145 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1147 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001148 return err
1149 }
1150
1151 //Update the device oper status as ACTIVE
1152 cloned.OperStatus = voltha.OperStatus_ACTIVE
1153 dh.device = cloned
1154
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1156 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001157 return err
1158 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001160
1161 return nil
1162}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001163
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301164func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001165 var uniID uint32
1166 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301167 for _, port := range onu.UniPorts {
1168 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001169 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1170 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301171 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1172 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001173 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301174 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1175 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001176 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301177 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001178 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301179 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001180 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301181 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1182 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001183 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301184 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1185 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1186 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001187 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301188 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1189 }
1190 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1191 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1192 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1193 }
1194 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1195 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1196 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 +00001197 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001198 }
1199 return nil
1200}
1201
1202func (dh *DeviceHandler) clearNNIData() error {
1203 nniUniID := -1
1204 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301205
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001206 if dh.resourceMgr == nil {
1207 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1208 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001209 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301210 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1211 if err != nil {
1212 log.Error("Failed to fetch nni from kv store")
1213 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001214 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301215 log.Debugw("NNI are ", log.Fields{"nni": nni})
1216 for _, nniIntfID := range nni {
1217 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1218 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1219 for _, flowID := range flowIDs {
1220 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1221 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001222 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301223 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1224 log.Error("Failed to clear nni from kv store")
1225 return err
1226 }
1227 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001228}
1229
1230// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1231func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1232 log.Debug("Function entry delete device")
1233 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001234 if dh.adminState == "deleted" {
1235 dh.lockDevice.Unlock()
1236 return nil
1237 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001238 dh.adminState = "deleted"
1239 dh.lockDevice.Unlock()
1240 /* Clear the KV store data associated with the all the UNI ports
1241 This clears up flow data and also resource map data for various
1242 other pon resources like alloc_id and gemport_id
1243 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001244 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1246 var ponPort uint32
1247 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1248 var onuGemData []rsrcMgr.OnuGemInfo
1249 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1250 if err != nil {
1251 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1252 return err
1253 }
1254 for _, onu := range onuGemData {
1255 log.Debugw("onu data ", log.Fields{"onu": onu})
1256 if err = dh.clearUNIData(&onu); err != nil {
1257 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1258 }
1259 }
1260 onuGemData = nil
1261 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1262 if err != nil {
1263 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001264 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001265 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001266 /* Clear the flows from KV store associated with NNI port.
1267 There are mostly trap rules from NNI port (like LLDP)
1268 */
1269 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301270 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001271 }
A R Karthick1f85b802019-10-11 05:06:05 +00001272
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001273 /* Clear the resource pool for each PON port in the background */
1274 go dh.resourceMgr.Delete()
1275 }
A R Karthick1f85b802019-10-11 05:06:05 +00001276
Devmalya Paul495b94a2019-08-27 19:42:00 -04001277 /*Delete ONU map for the device*/
1278 for onu := range dh.onus {
1279 delete(dh.onus, onu)
1280 }
1281 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301282 // Stop the Stats collector
1283 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001284 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001285 if dh.Client != nil {
1286 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1287 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1288 return err
1289 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001290 }
1291 cloned := proto.Clone(device).(*voltha.Device)
1292 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1293 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1294 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1295 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1296 return err
1297 }
1298 return nil
1299}
1300
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001302func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1303 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001304 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001305 return err
1306 }
1307
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001309
1310 return nil
1311}
1312
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001313func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1314 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1315 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1316 if err != nil {
1317 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1318 return
1319 }
1320 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001322 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1323 return
1324 }
1325 log.Debug("Success sending packet-in to core!")
1326}
1327
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1329func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001330 log.Debugw("incoming-packet-out", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo,
1331 "pkt-length": len(packet.Data), "packetData": hex.EncodeToString(packet.Data)})
1332
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001334 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001335 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1336 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1337 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1338 if innerEthType == 0x8100 {
1339 // q-in-q 802.1ad or 802.1q double tagged packet.
1340 // slice out the outer tag.
1341 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1342 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001343 }
1344 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1346 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001347 uniID := UniIDFromPortNum(uint32(egressPortNo))
1348
1349 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1350 if err != nil {
1351 // In this case the openolt agent will receive the gemPortID as 0.
1352 // The agent tries to retrieve the gemPortID in this case.
1353 // This may not always succeed at the agent and packetOut may fail.
1354 log.Error("failed-to-retrieve-gemport-id-for-packet-out")
1355 }
1356
1357 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001358
1359 log.Debugw("sending-packet-to-onu", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
Manikkaraj kb1d51442019-07-23 10:41:02 -04001360 "uniID": uniID, "gemPortID": gemPortID, "packet": hex.EncodeToString(packet.Data)})
Matt Jeanneret1359c732019-08-01 21:40:02 -04001361
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001362 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1363 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1364 return err
1365 }
1366 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001368
1369 log.Debugw("sending-packet-to-nni", log.Fields{"uplink_pkt": uplinkPkt, "packet": hex.EncodeToString(packet.Data)})
1370
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001371 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001372 log.Errorw("Error while sending packet-out to NNI", log.Fields{"error": err})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001373 return err
1374 }
1375 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{"egress_port_no": egressPortNo, "egressPortType": egressPortType})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001377 }
1378 return nil
1379}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001380
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1382 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001383}