blob: 7f2b9cfca113d52a801f485b68340b490c120c29 [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"
Girish Gowdru0c588b22019-04-23 23:24:56 -040038 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053039 "github.com/opencord/voltha-protos/go/common"
40 ic "github.com/opencord/voltha-protos/go/inter_container"
41 of "github.com/opencord/voltha-protos/go/openflow_13"
42 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053043 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070044 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040045 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053046)
47
salmansiddiqui7ac62132019-08-22 03:58:50 +000048// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040049const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000050 MaxRetry = 10
51 MaxTimeOutInMs = 500
Manikkaraj kb1d51442019-07-23 10:41:02 -040052)
53
kdarapu381c6902019-07-31 18:23:16 +053054func init() {
55 _, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
56}
57
Phaneendra Manda4c62c802019-03-06 21:37:49 +053058//DeviceHandler will interact with the OLT device.
59type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070061 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040062 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070063 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053064 coreProxy adapterif.CoreProxy
65 AdapterProxy adapterif.AdapterProxy
66 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070067 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070068 exitChannel chan int
69 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053070 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070071 transitionMap *TransitionMap
72 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053073 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040074 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053075 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040076 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070077 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070079}
80
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070082type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070084 deviceType string
85 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 onuID uint32
87 intfID uint32
88 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +000089 uniPorts map[uint32]struct{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -070090}
91
92//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070094 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070095 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070096 device.deviceType = deviceTp
97 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 device.onuID = onuID
99 device.intfID = intfID
100 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000101 device.uniPorts = make(map[uint32]struct{})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700102 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530103}
104
105//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530106func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700107 var dh DeviceHandler
108 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400109 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400110 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700111 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700113 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400114 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700115 dh.device = cloned
116 dh.openOLT = adapter
117 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400118 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700119 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400122 // when the first IntfOperInd with status as "up" is received for
123 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700124 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530125
cuilin20187b2a8c32019-03-26 19:52:28 -0700126 //TODO initialize the support classes.
127 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530128}
129
130// start save the device to the data model
131func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 dh.lockDevice.Lock()
133 defer dh.lockDevice.Unlock()
134 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
135 // Add the initial device to the local model
136 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530137}
138
139// stop stops the device dh. Not much to do for now
140func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700141 dh.lockDevice.Lock()
142 defer dh.lockDevice.Unlock()
143 log.Debug("stopping-device-agent")
144 dh.exitChannel <- 1
145 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530146}
147
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400148func macifyIP(ip net.IP) string {
149 if len(ip) > 0 {
150 oct1 := strconv.FormatInt(int64(ip[12]), 16)
151 oct2 := strconv.FormatInt(int64(ip[13]), 16)
152 oct3 := strconv.FormatInt(int64(ip[14]), 16)
153 oct4 := strconv.FormatInt(int64(ip[15]), 16)
154 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
155 }
156 return ""
157}
158
159func generateMacFromHost(host string) (string, error) {
160 var genmac string
161 var addr net.IP
162 var ips []string
163 var err error
164
165 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
166
167 if addr = net.ParseIP(host); addr == nil {
168 log.Debugw("looking-up-hostname", log.Fields{"host": host})
169
170 if ips, err = net.LookupHost(host); err == nil {
171 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
172 if addr = net.ParseIP(ips[0]); addr == nil {
173 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
174 return "", errors.New("unable-to-parse-ip")
175 }
176 genmac = macifyIP(addr)
177 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
178 return genmac, nil
179 }
180 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
181 return "", err
182 }
183
184 genmac = macifyIP(addr)
185 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
186 return genmac, nil
187}
188
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530189func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700190 slist := strings.Split(mac, ":")
191 result := make([]uint32, len(slist))
192 var err error
193 var tmp int64
194 for index, val := range slist {
195 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
196 return []uint32{1, 2, 3, 4, 5, 6}
197 }
198 result[index] = uint32(tmp)
199 }
200 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530201}
202
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700203//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 +0530204func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530205
Girish Gowdru0c588b22019-04-23 23:24:56 -0400206 if portType == voltha.Port_ETHERNET_NNI {
207 return fmt.Sprintf("nni-%d", portNum)
208 } else if portType == voltha.Port_PON_OLT {
209 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 } else if portType == voltha.Port_ETHERNET_UNI {
211 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400212 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700213 }
214 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530215}
216
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 var operStatus common.OperStatus_OperStatus
219 if state == "up" {
220 operStatus = voltha.OperStatus_ACTIVE
221 } else {
222 operStatus = voltha.OperStatus_DISCOVERED
223 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400225 label := GetportLabel(portNum, portType)
226 if len(label) == 0 {
227 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
228 return
229 }
230 // Now create Port
231 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700232 PortNo: portNum,
233 Label: label,
234 Type: portType,
235 OperStatus: operStatus,
236 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400237 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700238 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
240 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400241 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700242
Girish Gowdru1110ef22019-06-24 11:17:59 -0400243 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700244 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
245 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
246 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700247 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530248}
249
250// readIndications to read the indications from the OLT device
251func (dh *DeviceHandler) readIndications() {
William Kurkianff524662019-08-20 10:34:30 -0400252 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400253 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700254 if err != nil {
255 log.Errorw("Failed to read indications", log.Fields{"err": err})
256 return
257 }
258 if indications == nil {
259 log.Errorw("Indications is nil", log.Fields{})
260 return
261 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400262 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700263 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400264 if err != nil || device == nil {
265 /*TODO: needs to handle error scenarios */
266 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400268 }
269 // When the device is in DISABLED and Adapter container restarts, we need to
270 // rebuild the locally maintained admin state.
271 if device.AdminState == voltha.AdminState_DISABLED {
272 dh.lockDevice.Lock()
273 dh.adminState = "down"
274 dh.lockDevice.Unlock()
275 }
276
cuilin20187b2a8c32019-03-26 19:52:28 -0700277 for {
278 indication, err := indications.Recv()
279 if err == io.EOF {
280 break
281 }
282 if err != nil {
283 log.Infow("Failed to read from indications", log.Fields{"err": err})
Devmalya Paul495b94a2019-08-27 19:42:00 -0400284 if dh.adminState == "deleted" {
285 log.Debug("Device deleted stoping the read indication thread")
286 break
287 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400288 dh.transitionMap.Handle(DeviceDownInd)
289 dh.transitionMap.Handle(DeviceInit)
290 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 }
Chaitrashree G S44124192019-08-07 20:21:36 -0400292 dh.lockDevice.RLock()
293 adminState := dh.adminState
294 dh.lockDevice.RUnlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400295 // When OLT is admin down, ignore all indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400296 if adminState == "down" {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297
Chaitrashree G S3b4c0352019-09-09 20:59:29 -0400298 log.Infow("olt is admin down, ignore indication", log.Fields{})
299 continue
300 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530302
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700303 }
304}
305
306func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000307 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000308 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700309 dh.transitionMap.Handle(DeviceUpInd)
310 } else if oltIndication.OperState == "down" {
311 dh.transitionMap.Handle(DeviceDownInd)
312 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000313 // Send or clear Alarm
314 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700315}
316
317func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400318 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319 switch indication.Data.(type) {
320 case *oop.Indication_OltInd:
321 dh.handleOltIndication(indication.GetOltInd())
322 case *oop.Indication_IntfInd:
323 intfInd := indication.GetIntfInd()
324 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
325 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
326 case *oop.Indication_IntfOperInd:
327 intfOperInd := indication.GetIntfOperInd()
328 if intfOperInd.GetType() == "nni" {
329 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
330 } else if intfOperInd.GetType() == "pon" {
331 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
332 // Handle pon port update
Gamze Abaka8539e202019-10-03 19:22:48 +0000333 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
cuilin20187b2a8c32019-03-26 19:52:28 -0700334 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
336 case *oop.Indication_OnuDiscInd:
337 onuDiscInd := indication.GetOnuDiscInd()
338 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700339 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400340 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700341 case *oop.Indication_OnuInd:
342 onuInd := indication.GetOnuInd()
343 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
344 go dh.onuIndication(onuInd)
345 case *oop.Indication_OmciInd:
346 omciInd := indication.GetOmciInd()
347 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
William Kurkianff524662019-08-20 10:34:30 -0400348 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700349 case *oop.Indication_PktInd:
350 pktInd := indication.GetPktInd()
351 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
352 go dh.handlePacketIndication(pktInd)
353 case *oop.Indication_PortStats:
354 portStats := indication.GetPortStats()
355 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
356 case *oop.Indication_FlowStats:
357 flowStats := indication.GetFlowStats()
358 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
359 case *oop.Indication_AlarmInd:
360 alarmInd := indication.GetAlarmInd()
361 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Devmalya Paulfb990a52019-07-09 10:01:49 -0400362 dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
363
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530365}
366
367// doStateUp handle the olt up indication and update to voltha core
368func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400369 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700370 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400371 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 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 -0400373 return err
374 }
375 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376}
377
378// doStateDown handle the olt down indication
379func (dh *DeviceHandler) doStateDown() error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700380 dh.lockDevice.Lock()
381 defer dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400382 log.Debug("do-state-down-start")
383
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700384 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400385 if err != nil || device == nil {
386 /*TODO: needs to handle error scenarios */
387 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700388 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400389 }
390
391 cloned := proto.Clone(device).(*voltha.Device)
392 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700393 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
394 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
395 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400396 }
397
398 //Update the device oper state and connection status
399 cloned.OperStatus = voltha.OperStatus_UNKNOWN
400 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
401 dh.device = cloned
402
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
404 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
405 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400406 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400407
408 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700409 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400410 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700411 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400412 return err
413 }
414 for _, onuDevice := range onuDevices.Items {
415
416 // Update onu state as down in onu adapter
417 onuInd := oop.OnuIndication{}
418 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700419 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
420 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
421 if er != nil {
422 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
423 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -0700424 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700425 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400426 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700427 /* Discovered ONUs entries need to be cleared , since after OLT
428 is up, it starts sending discovery indications again*/
429 dh.discOnus = make(map[string]bool)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700431 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530432}
433
434// doStateInit dial the grpc before going to init state
435func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400436 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400437 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400438 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400440 return err
441 }
442 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530443}
444
445// postInit create olt client instance to invoke RPC on the olt device
446func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400447 dh.Client = oop.NewOpenoltClient(dh.clientCon)
448 dh.transitionMap.Handle(GrpcConnected)
449 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530450}
451
452// doStateConnected get the device info and update to voltha core
453func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400454 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400455
456 // Case where OLT is disabled and then rebooted.
457 if dh.adminState == "down" {
458 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700459 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400460 if err != nil || device == nil {
461 /*TODO: needs to handle error scenarios */
462 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
463 }
464
465 cloned := proto.Clone(device).(*voltha.Device)
466 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
467 cloned.OperStatus = voltha.OperStatus_UNKNOWN
468 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
470 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400471 }
472
Chaitrashree G S44124192019-08-07 20:21:36 -0400473 // 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 -0400474 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
475 if err != nil {
476 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
477 }
478
479 // Start reading indications
480 go dh.readIndications()
481 return nil
482 }
483
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400484 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700485 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400486 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700487 return err
488 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400489
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400491 if err != nil || device == nil {
492 /*TODO: needs to handle error scenarios */
493 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400495 }
496 cloned := proto.Clone(device).(*voltha.Device)
497 // Update the all ports (if available) on that device to ACTIVE.
498 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
500 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400501 return err
502 }
503
Girish Gowdru0c588b22019-04-23 23:24:56 -0400504 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
505 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700506 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400507 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700508 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400509 }
510 // Instantiate flow manager
511 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
512 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400514 }
515 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400516 /* Instantiating Event Manager to handle Alarms and KPIs */
Devmalya Paul90ca3012019-09-02 21:55:45 -0400517 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530518
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 // Start reading indications
520 go dh.readIndications()
521 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530522}
523
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400524func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
525 var err error
526 var deviceInfo *oop.DeviceInfo
527
528 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
529
530 if err != nil {
531 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
532 return nil, err
533 }
534 if deviceInfo == nil {
535 log.Errorw("Device info is nil", log.Fields{})
536 return nil, errors.New("failed to get device info from OLT")
537 }
538
539 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
540 dh.device.Root = true
541 dh.device.Vendor = deviceInfo.Vendor
542 dh.device.Model = deviceInfo.Model
543 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
544 dh.device.HardwareVersion = deviceInfo.HardwareVersion
545 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
546
547 if deviceInfo.DeviceId == "" {
548 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
549 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
550 genmac, err := generateMacFromHost(host)
551 if err != nil {
552 return nil, err
553 }
554 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
555 dh.device.MacAddress = genmac
556 } else {
557 dh.device.MacAddress = deviceInfo.DeviceId
558 }
559
560 // Synchronous call to update device - this method is run in its own go routine
561 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
562 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
563 return nil, err
564 }
565
566 return deviceInfo, nil
567}
568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530570func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400571 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400573 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530574}
575
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530577func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700578 return &ic.SwitchCapability{
579 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530580 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700581 HwDesc: "open_pon",
582 SwDesc: "open_pon",
583 SerialNum: dh.device.SerialNumber,
584 },
585 SwitchFeatures: &of.OfpSwitchFeatures{
586 NBuffers: 256,
587 NTables: 2,
588 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
589 of.OfpCapabilities_OFPC_TABLE_STATS |
590 of.OfpCapabilities_OFPC_PORT_STATS |
591 of.OfpCapabilities_OFPC_GROUP_STATS),
592 },
593 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530594}
595
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700596//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530597func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700599 return &ic.PortCapability{
600 Port: &voltha.LogicalPort{
601 OfpPort: &of.OfpPort{
602 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
603 Config: 0,
604 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 Curr: capacity,
606 Advertised: capacity,
607 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700608 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
609 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
610 },
611 DeviceId: dh.device.Id,
612 DevicePortNo: uint32(portNo),
613 },
614 }, nil
615}
616
William Kurkianff524662019-08-20 10:34:30 -0400617func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700619 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 var deviceID string
621 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700622
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700623 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
624 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
626 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700627 kwargs := make(map[string]interface{})
628 kwargs["onu_id"] = omciInd.OnuId
629 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700630
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
632 if err != nil {
William Kurkianff524662019-08-20 10:34:30 -0400633 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
634 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700635 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636 deviceType = onuDevice.Type
637 deviceID = onuDevice.Id
638 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
639 //if not exist in cache, then add to cache.
640 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700641 } else {
642 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700644 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 deviceID = onuInCache.deviceID
646 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700647 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700648
649 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
650 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
651 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkianff524662019-08-20 10:34:30 -0400653 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
654 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700655 }
William Kurkianff524662019-08-20 10:34:30 -0400656 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530657}
658
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659//ProcessInterAdapterMessage sends the proxied messages to the target device
660// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
661// is meant, and then send the unmarshalled omci message to this onu
662func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
663 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700664 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700666 fromTopic := msg.Header.FromTopic
667 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 toDeviceID := msg.Header.ToDeviceId
669 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700670
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700672
673 msgBody := msg.GetBody()
674
675 omciMsg := &ic.InterAdapterOmciMessage{}
676 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
677 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
678 return err
679 }
680
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700681 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
683 if err != nil {
684 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700685 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700686 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700687 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
688 dh.sendProxiedMessage(onuDevice, omciMsg)
689
cuilin20187b2a8c32019-03-26 19:52:28 -0700690 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 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 -0700692 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700693 }
694
695 } else {
696 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
697 }
698 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530699}
700
cuilin20187b2a8c32019-03-26 19:52:28 -0700701func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 var intfID uint32
703 var onuID uint32
704 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700705 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 intfID = onuDevice.ProxyAddress.GetChannelId()
707 onuID = onuDevice.ProxyAddress.GetOnuId()
708 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700709 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 intfID = omciMsg.GetProxyAddress().GetChannelId()
711 onuID = omciMsg.GetProxyAddress().GetOnuId()
712 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700713 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 if connectStatus != voltha.ConnectStatus_REACHABLE {
715 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700716 return
717 }
718
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700719 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700720
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
722 if err != nil {
723 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
724 return
725 }
726 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700727}
728
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
730 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
731 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700732 // TODO: need resource manager
733 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400736 st, _ := status.FromError(err)
737 if st.Code() == codes.AlreadyExists {
738 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
739 } else {
740 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
741 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700742 } else {
743 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
744 }
745}
746
Matt Jeanneret53539512019-07-20 14:47:02 -0400747func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 channelID := onuDiscInd.GetIntfId()
749 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400750
751 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
752 dh.lockDevice.Lock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400753 if _, ok := dh.discOnus[sn]; ok {
Matt Jeanneret53539512019-07-20 14:47:02 -0400754 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400755 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400756 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700757 }
758
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400759 dh.discOnus[sn] = true
Matt Jeanneret53539512019-07-20 14:47:02 -0400760 log.Debugw("new-discovery-indications-list", log.Fields{"discOnus": dh.discOnus})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400761 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400762
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400764 if sn != "" {
765 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400766 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400767 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
768 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400769 }
770
771 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
772 var onuID uint32
773 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700774 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400775 ponintfid := onuDiscInd.GetIntfId()
776 dh.lockDevice.Lock()
777 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
778 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400779 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400780 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
781 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400782 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700783 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400784 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700785 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400786 log.Errorw("Create onu error",
787 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
788 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400789 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400790 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400791 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400792
793 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700794 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400795 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400796 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700797 //Insert the ONU into cache to use in OnuIndication.
798 //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 -0700799 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
800 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700801 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400802
803 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700804 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400805 log.Debugw("new-onu-device-discovered", log.Fields{"onu": dh.onus[onuKey]})
806 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400807
Mahir Gunyele77977b2019-06-27 05:36:22 -0700808 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
809 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400810 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
811 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700812 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700813 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
814 //TODO: We put this sleep here to prevent the race between state update and onuIndication
815 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
816 //then the initialisation fails.
817 time.Sleep(1 * time.Second)
818 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400819 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700820}
821
822func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
823 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
824
825 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700826 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700827 var onuDevice *voltha.Device
828 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700829 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
830 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700831 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
832 if onuInCache, ok := dh.onus[onuKey]; ok {
833 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
834 foundInCache = true
835 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700836 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700837 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
838 if serialNumber != "" {
839 kwargs["serial_number"] = serialNumber
840 } else {
841 kwargs["onu_id"] = onuInd.OnuId
842 kwargs["parent_port_no"] = ponPort
843 }
844 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700845 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700846
847 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400848 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849 //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 -0400850 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700851 }
852
853 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
854 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})
855 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700856 if !foundInCache {
857 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Matt Jeanneret53539512019-07-20 14:47:02 -0400858 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700859 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400860 dh.lockDevice.Unlock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700861 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700862 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700863
cuilin20187b2a8c32019-03-26 19:52:28 -0700864 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700865 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700866 return
867 }
868
869}
870
Scott Baker7eb0a932019-07-26 10:33:22 -0700871func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400872 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 -0700873 dh.updateOnuAdminState(onuInd)
874 // operState
875 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400876 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 -0700877 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
878 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
879 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
880 if err != nil {
881 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
882 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
883 }
884 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700885 // Ignore operstatus if device was found in cache
886 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400887 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 -0700888 return
889 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400890 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
891 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
893 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
894 if err != nil {
895 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
William Kurkian740a09c2019-10-23 17:07:38 -0400896 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id, "Error": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 return
898 }
899 } else {
900 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
901 }
902}
903
904func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
905 if onuInd.AdminState == "down" {
906 if onuInd.OperState != "down" {
907 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
908 // Forcing the oper state change code to execute
909 onuInd.OperState = "down"
910 }
911 // Port and logical port update is taken care of by oper state block
912 } else if onuInd.AdminState == "up" {
913 log.Debugln("received-onu-admin-state up")
914 } else {
915 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
916 }
917 log.Debugln("admin-state-dealt-with")
918}
919
cuilin20187b2a8c32019-03-26 19:52:28 -0700920func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
921 if serialNum != nil {
922 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700923 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700925}
926
927func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
928 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700930 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
931 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
932 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
933 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
934 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
935 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
936 return tmp
937}
938
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939//UpdateFlowsBulk upates the bulk flow
940func (dh *DeviceHandler) UpdateFlowsBulk() error {
941 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700942}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943
944//GetChildDevice returns the child device for given parent port and onu id
945func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
946 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400947 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700948 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400949 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400951 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700952 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400953 return nil
954 }
955 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
956 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530957}
958
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700959// SendPacketInToCore sends packet-in to core
960// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
961// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400962func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
963 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700964 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400965 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
966 return
967 }
968 log.Debug("Sent packet-in to core successfully")
969}
970
A R Karthick1f85b802019-10-11 05:06:05 +0000971// AddUniPortToOnu adds the uni port to the onu device
972func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
973 onuKey := dh.formOnuKey(intfID, onuID)
974 dh.lockDevice.Lock()
975 defer dh.lockDevice.Unlock()
976 if onuDevice, ok := dh.onus[onuKey]; ok {
977 // add it to the uniPort map for the onu device
978 if _, ok = onuDevice.uniPorts[uniPort]; !ok {
979 onuDevice.uniPorts[uniPort] = struct{}{}
980 log.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
981 }
982 }
983}
984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400986func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
987 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 -0400988 if flows != nil {
989 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400990 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400991 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400992 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400993 for _, flow := range flows.ToRemove.Items {
994 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
995 dh.flowMgr.RemoveFlow(flow)
996 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400997 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400999 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001001 // dh.flowMgr.RemoveFlow(flow)
1002 }
1003 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001004 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001005 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301006}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008//DisableDevice disables the given device
1009//It marks the following for the given device:
1010//Device-Handler Admin-State : down
1011//Device Port-State: UNKNOWN
1012//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001013func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001014 /* On device disable ,admin state update has to be done prior sending request to agent since
1015 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001016 dh.lockDevice.Lock()
1017 dh.adminState = "down"
1018 dh.lockDevice.Unlock()
Chaitrashree G S44124192019-08-07 20:21:36 -04001019 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001020 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1021 log.Errorw("failed-to-disable-olt ", log.Fields{"err": err})
1022 dh.lockDevice.Lock()
1023 dh.adminState = "up"
1024 dh.lockDevice.Unlock()
1025 return err
1026 }
1027
Chaitrashree G S44124192019-08-07 20:21:36 -04001028 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001029 log.Debug("olt-disabled")
Chaitrashree G S44124192019-08-07 20:21:36 -04001030 dh.lockDevice.Lock()
1031 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
1032 UNREACHABLE state which needs to be configured again*/
1033 dh.discOnus = make(map[string]bool)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001034 dh.onus = make(map[string]*OnuDevice)
Chaitrashree G S44124192019-08-07 20:21:36 -04001035 dh.lockDevice.Unlock()
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001036 go dh.notifyChildDevices()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001037 cloned := proto.Clone(device).(*voltha.Device)
1038 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1040 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001041 return err
1042 }
1043
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001044 log.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001045 return nil
1046}
1047
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001048func (dh *DeviceHandler) notifyChildDevices() {
1049
1050 // Update onu state as unreachable in onu adapter
1051 onuInd := oop.OnuIndication{}
1052 onuInd.OperState = "unreachable"
1053 //get the child device for the parent device
1054 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1055 if err != nil {
1056 log.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
1057 }
1058 if onuDevices != nil {
1059 for _, onuDevice := range onuDevices.Items {
1060 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1061 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1062 if err != nil {
1063 log.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
1064 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1065 }
1066
1067 }
1068 }
1069
1070}
1071
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001072//ReenableDevice re-enables the olt device after disable
1073//It marks the following for the given device:
1074//Device-Handler Admin-State : up
1075//Device Port-State: ACTIVE
1076//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001077func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1078 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001079 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
1080 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1081 return err
1082 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001083 }
1084
1085 dh.lockDevice.Lock()
1086 dh.adminState = "up"
1087 dh.lockDevice.Unlock()
1088 log.Debug("olt-reenabled")
1089
1090 cloned := proto.Clone(device).(*voltha.Device)
1091 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); 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
1097 //Update the device oper status as ACTIVE
1098 cloned.OperStatus = voltha.OperStatus_ACTIVE
1099 dh.device = cloned
1100
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1102 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001103 return err
1104 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001106
1107 return nil
1108}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001109
A R Karthick1f85b802019-10-11 05:06:05 +00001110func (dh *DeviceHandler) clearUNIData(onu *OnuDevice) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001111 var uniID uint32
1112 var err error
A R Karthick1f85b802019-10-11 05:06:05 +00001113 for port := range onu.uniPorts {
1114 delete(onu.uniPorts, port)
1115 uniID = UniIDFromPortNum(port)
1116 log.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
1117 /* Delete tech-profile instance from the KV store */
Gamze Abakafee36392019-10-03 11:17:24 +00001118 if err = dh.flowMgr.DeleteTechProfileInstances(onu.intfID, onu.onuID, uniID, onu.serialNumber); err != nil {
A R Karthick1f85b802019-10-11 05:06:05 +00001119 log.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001120 }
A R Karthick1f85b802019-10-11 05:06:05 +00001121 log.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.onuID})
1122 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(onu.intfID, onu.onuID, uniID)
1123 for _, flowID := range flowIDs {
1124 dh.resourceMgr.FreeFlowID(onu.intfID, int32(onu.onuID), int32(uniID), flowID)
1125 }
1126 dh.resourceMgr.FreePONResourcesForONU(onu.intfID, onu.onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001127 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(onu.intfID, onu.onuID, uniID); err != nil {
A R Karthick1f85b802019-10-11 05:06:05 +00001128 log.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
1129 }
1130 log.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.onuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001131 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(onu.intfID, onu.onuID, uniID)
1132 for _, tpID := range tpIDList {
1133 if err = dh.resourceMgr.RemoveMeterIDForOnu("upstream", onu.intfID, onu.onuID, uniID, tpID); err != nil {
1134 log.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
1135 }
1136 log.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.onuID})
1137 if err = dh.resourceMgr.RemoveMeterIDForOnu("downstream", onu.intfID, onu.onuID, uniID, tpID); err != nil {
1138 log.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
1139 }
1140 log.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001141 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001142 }
1143 return nil
1144}
1145
1146func (dh *DeviceHandler) clearNNIData() error {
1147 nniUniID := -1
1148 nniOnuID := -1
1149 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
1150 log.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
1151 for _, flowID := range flowIDs {
1152 dh.resourceMgr.FreeFlowID(uint32(dh.nniIntfID), -1, -1, uint32(flowID))
1153 }
1154 //Free the flow-ids for the NNI port
1155 dh.resourceMgr.FreePONResourcesForONU(uint32(dh.nniIntfID), uint32(nniOnuID), uint32(nniUniID))
1156 /* Free ONU IDs for each pon port
1157 intfIDToONUIds is a map of intf-id: [onu-ids]*/
1158 intfIDToONUIds := make(map[uint32][]uint32)
1159 for _, onu := range dh.onus {
1160 intfIDToONUIds[onu.intfID] = append(intfIDToONUIds[onu.intfID], onu.onuID)
1161 }
1162 for intfID, onuIds := range intfIDToONUIds {
1163 dh.resourceMgr.FreeonuID(intfID, onuIds)
1164 }
1165 return nil
1166}
1167
1168// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
1169func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) error {
1170 log.Debug("Function entry delete device")
1171 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001172 if dh.adminState == "deleted" {
1173 dh.lockDevice.Unlock()
1174 return nil
1175 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001176 dh.adminState = "deleted"
1177 dh.lockDevice.Unlock()
1178 /* Clear the KV store data associated with the all the UNI ports
1179 This clears up flow data and also resource map data for various
1180 other pon resources like alloc_id and gemport_id
1181 */
1182 for _, onu := range dh.onus {
A R Karthick1f85b802019-10-11 05:06:05 +00001183 if err := dh.clearUNIData(onu); err != nil {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001184 log.Debugw("Failed to clear data for onu", log.Fields{"onu-device": onu})
1185 }
1186 }
1187 /* Clear the flows from KV store associated with NNI port.
1188 There are mostly trap rules from NNI port (like LLDP)
1189 */
1190 if err := dh.clearNNIData(); err != nil {
1191 log.Debugw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
1192 }
A R Karthick1f85b802019-10-11 05:06:05 +00001193
1194 /* Clear the resource pool for each PON port in the background */
1195 go dh.resourceMgr.Delete()
1196
Devmalya Paul495b94a2019-08-27 19:42:00 -04001197 /*Delete ONU map for the device*/
1198 for onu := range dh.onus {
1199 delete(dh.onus, onu)
1200 }
1201 log.Debug("Removed-device-from-Resource-manager-KV-store")
1202 //Reset the state
1203 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1204 log.Errorw("Failed-to-reboot-olt ", log.Fields{"err": err})
1205 return err
1206 }
1207 cloned := proto.Clone(device).(*voltha.Device)
1208 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1209 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1210 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1211 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
1212 return err
1213 }
1214 return nil
1215}
1216
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001217//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001218func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1219 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1220 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
1221 return err
1222 }
1223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001225
1226 return nil
1227}
1228
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001229func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1230 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1231 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1232 if err != nil {
1233 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1234 return
1235 }
1236 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001237 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001238 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1239 return
1240 }
1241 log.Debug("Success sending packet-in to core!")
1242}
1243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1245func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001246 log.Debugw("incoming-packet-out", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo,
1247 "pkt-length": len(packet.Data), "packetData": hex.EncodeToString(packet.Data)})
1248
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001250 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001251 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1252 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1253 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1254 if innerEthType == 0x8100 {
1255 // q-in-q 802.1ad or 802.1q double tagged packet.
1256 // slice out the outer tag.
1257 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1258 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001259 }
1260 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1262 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001263 uniID := UniIDFromPortNum(uint32(egressPortNo))
1264
1265 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1266 if err != nil {
1267 // In this case the openolt agent will receive the gemPortID as 0.
1268 // The agent tries to retrieve the gemPortID in this case.
1269 // This may not always succeed at the agent and packetOut may fail.
1270 log.Error("failed-to-retrieve-gemport-id-for-packet-out")
1271 }
1272
1273 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001274
1275 log.Debugw("sending-packet-to-onu", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
Manikkaraj kb1d51442019-07-23 10:41:02 -04001276 "uniID": uniID, "gemPortID": gemPortID, "packet": hex.EncodeToString(packet.Data)})
Matt Jeanneret1359c732019-08-01 21:40:02 -04001277
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001278 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1279 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1280 return err
1281 }
1282 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001284
1285 log.Debugw("sending-packet-to-nni", log.Fields{"uplink_pkt": uplinkPkt, "packet": hex.EncodeToString(packet.Data)})
1286
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001287 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001288 log.Errorw("Error while sending packet-out to NNI", log.Fields{"error": err})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001289 return err
1290 }
1291 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 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 -04001293 }
1294 return nil
1295}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001296
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1298 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001299}