blob: 9f38133d44ec565cd5a5362df180e603fdbb0131 [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) {
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)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301027
1028 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001029 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301030 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1031 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
A R Karthick1f85b802019-10-11 05:06:05 +00001032 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
1033 }
1034 }
1035}
1036
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -04001038func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1039 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 -04001040 if flows != nil {
1041 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001042 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001043 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001044 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001045 for _, flow := range flows.ToRemove.Items {
1046 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
1047 dh.flowMgr.RemoveFlow(flow)
1048 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001049 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001051 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001053 // dh.flowMgr.RemoveFlow(flow)
1054 }
1055 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001056 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001057 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301058}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001059
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001060//DisableDevice disables the given device
1061//It marks the following for the given device:
1062//Device-Handler Admin-State : down
1063//Device Port-State: UNKNOWN
1064//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001065func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001066 /* On device disable ,admin state update has to be done prior sending request to agent since
1067 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001068 dh.lockDevice.Lock()
1069 dh.adminState = "down"
1070 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001071 if dh.Client != nil {
1072 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1073 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1074 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
1075 dh.lockDevice.Lock()
1076 dh.adminState = "up"
1077 dh.lockDevice.Unlock()
1078 return err
1079 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001080 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001081 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001082 log.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001083 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001084 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301085
1086 dh.discOnus = sync.Map{}
1087 dh.onus = sync.Map{}
1088
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001089 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001090 cloned := proto.Clone(device).(*voltha.Device)
1091 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1093 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001094 return err
1095 }
1096
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001097 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001098 return nil
1099}
1100
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001101func (dh *DeviceHandler) notifyChildDevices() {
1102
1103 // Update onu state as unreachable in onu adapter
1104 onuInd := oop.OnuIndication{}
1105 onuInd.OperState = "unreachable"
1106 //get the child device for the parent device
1107 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1108 if err != nil {
1109 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1110 }
1111 if onuDevices != nil {
1112 for _, onuDevice := range onuDevices.Items {
1113 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1114 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1115 if err != nil {
1116 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1117 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1118 }
1119
1120 }
1121 }
1122
1123}
1124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001125//ReenableDevice re-enables the olt device after disable
1126//It marks the following for the given device:
1127//Device-Handler Admin-State : up
1128//Device Port-State: ACTIVE
1129//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001130func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1131 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001132 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1133 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1134 return err
1135 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001136 }
1137
1138 dh.lockDevice.Lock()
1139 dh.adminState = "up"
1140 dh.lockDevice.Unlock()
1141 log.Debug("olt-reenabled")
1142
1143 cloned := proto.Clone(device).(*voltha.Device)
1144 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001145 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1146 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001147 return err
1148 }
1149
1150 //Update the device oper status as ACTIVE
1151 cloned.OperStatus = voltha.OperStatus_ACTIVE
1152 dh.device = cloned
1153
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1155 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001156 return err
1157 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001159
1160 return nil
1161}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001162
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301163func (dh *DeviceHandler) clearUNIData(onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001164 var uniID uint32
1165 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301166 for _, port := range onu.UniPorts {
1167 uniID = UniIDFromPortNum(uint32(port))
A R Karthick1f85b802019-10-11 05:06:05 +00001168 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1169 /* Delete tech-profile instance from the KV store */
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301170 if err = dh.flowMgr.DeleteTechProfileInstances(onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
1171 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001172 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301173 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
1174 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001175 for _, flowID := range flowIDs {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301176 dh.resourceMgr.FreeFlowID(onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001177 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301178 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001179 for _, tpID := range tpIDList {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301180 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1181 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001182 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301183 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
1184 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
1185 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001186 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301187 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
1188 }
1189 dh.resourceMgr.FreePONResourcesForONU(onu.IntfID, onu.OnuID, uniID)
1190 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.IntfID, onu.OnuID, uniID); err != nil {
1191 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1192 }
1193 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
1194 if err = dh.resourceMgr.DelGemPortPktIn(onu.IntfID, onu.OnuID, uint32(port)); err != nil {
1195 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 +00001196 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001197 }
1198 return nil
1199}
1200
1201func (dh *DeviceHandler) clearNNIData() error {
1202 nniUniID := -1
1203 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301204
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001205 if dh.resourceMgr == nil {
1206 return fmt.Errorf("no resource manager for deviceID %s", dh.deviceID)
1207 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001208 //Free the flow-ids for the NNI port
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301209 nni, err := dh.resourceMgr.GetNNIFromKVStore()
1210 if err != nil {
1211 log.Error("Failed to fetch nni from kv store")
1212 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001213 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301214 log.Debugw("NNI are ", log.Fields{"nni": nni})
1215 for _, nniIntfID := range nni {
1216 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
1217 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1218 for _, flowID := range flowIDs {
1219 dh.resourceMgr.FreeFlowID(uint32(nniIntfID), -1, -1, uint32(flowID))
1220 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001221 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301222 if err = dh.resourceMgr.DelNNiFromKVStore(); err != nil {
1223 log.Error("Failed to clear nni from kv store")
1224 return err
1225 }
1226 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -04001227}
1228
1229// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1230func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1231 log.Debug("Function entry delete device")
1232 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001233 if dh.adminState == "deleted" {
1234 dh.lockDevice.Unlock()
1235 return nil
1236 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001237 dh.adminState = "deleted"
1238 dh.lockDevice.Unlock()
1239 /* Clear the KV store data associated with the all the UNI ports
1240 This clears up flow data and also resource map data for various
1241 other pon resources like alloc_id and gemport_id
1242 */
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001243 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301244 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1245 var ponPort uint32
1246 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1247 var onuGemData []rsrcMgr.OnuGemInfo
1248 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ponPort, &onuGemData)
1249 if err != nil {
1250 log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
1251 return err
1252 }
1253 for _, onu := range onuGemData {
1254 log.Debugw("onu data ", log.Fields{"onu": onu})
1255 if err = dh.clearUNIData(&onu); err != nil {
1256 log.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1257 }
1258 }
1259 onuGemData = nil
1260 err = dh.resourceMgr.DelOnuGemInfoForIntf(ponPort)
1261 if err != nil {
1262 log.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001263 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001264 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001265 /* Clear the flows from KV store associated with NNI port.
1266 There are mostly trap rules from NNI port (like LLDP)
1267 */
1268 if err := dh.clearNNIData(); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301269 log.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001270 }
A R Karthick1f85b802019-10-11 05:06:05 +00001271
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001272 /* Clear the resource pool for each PON port in the background */
1273 go dh.resourceMgr.Delete()
1274 }
A R Karthick1f85b802019-10-11 05:06:05 +00001275
Devmalya Paul495b94a2019-08-27 19:42:00 -04001276 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301277 dh.onus.Range(func(key interface{}, value interface{}) bool {
1278 dh.onus.Delete(key)
1279 return true
1280 })
1281
Devmalya Paul495b94a2019-08-27 19:42:00 -04001282 log.Debug("Removed-device-from-Resource-manager-KV-store")
Naga Manjunath7615e552019-10-11 22:35:47 +05301283 // Stop the Stats collector
1284 dh.stopCollector <- true
Devmalya Paul495b94a2019-08-27 19:42:00 -04001285 //Reset the state
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001286 if dh.Client != nil {
1287 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1288 log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
1289 return err
1290 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001291 }
1292 cloned := proto.Clone(device).(*voltha.Device)
1293 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1294 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1295 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1296 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1297 return err
1298 }
1299 return nil
1300}
1301
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001302//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001303func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1304 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001305 log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001306 return err
1307 }
1308
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001309 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001310
1311 return nil
1312}
1313
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001314func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1315 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1316 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1317 if err != nil {
1318 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1319 return
1320 }
1321 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001323 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1324 return
1325 }
1326 log.Debug("Success sending packet-in to core!")
1327}
1328
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001329// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1330func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001331 log.Debugw("incoming-packet-out", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo,
1332 "pkt-length": len(packet.Data), "packetData": hex.EncodeToString(packet.Data)})
1333
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001334 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001335 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001336 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1337 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1338 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1339 if innerEthType == 0x8100 {
1340 // q-in-q 802.1ad or 802.1q double tagged packet.
1341 // slice out the outer tag.
1342 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1343 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001344 }
1345 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1347 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001348 uniID := UniIDFromPortNum(uint32(egressPortNo))
1349
1350 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1351 if err != nil {
1352 // In this case the openolt agent will receive the gemPortID as 0.
1353 // The agent tries to retrieve the gemPortID in this case.
1354 // This may not always succeed at the agent and packetOut may fail.
1355 log.Error("failed-to-retrieve-gemport-id-for-packet-out")
1356 }
1357
1358 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001359
1360 log.Debugw("sending-packet-to-onu", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
Manikkaraj kb1d51442019-07-23 10:41:02 -04001361 "uniID": uniID, "gemPortID": gemPortID, "packet": hex.EncodeToString(packet.Data)})
Matt Jeanneret1359c732019-08-01 21:40:02 -04001362
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001363 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1364 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1365 return err
1366 }
1367 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001369
1370 log.Debugw("sending-packet-to-nni", log.Fields{"uplink_pkt": uplinkPkt, "packet": hex.EncodeToString(packet.Data)})
1371
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001372 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001373 log.Errorw("Error while sending packet-out to NNI", log.Fields{"error": err})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001374 return err
1375 }
1376 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001377 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 -04001378 }
1379 return nil
1380}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001381
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1383 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001384}