blob: 5bf9417adf0e4753f7715c2a9b52c654000e03a7 [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"
36 com "github.com/opencord/voltha-go/adapters/common"
37 "github.com/opencord/voltha-go/common/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
Manikkaraj kb1d51442019-07-23 10:41:02 -040048const (
49 MAX_RETRY = 10
50 MAX_TIMEOUT_IN_MS = 500
51)
52
Phaneendra Manda4c62c802019-03-06 21:37:49 +053053//DeviceHandler will interact with the OLT device.
54type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070056 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040057 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070058 device *voltha.Device
59 coreProxy *com.CoreProxy
manikkaraj kbf256be2019-03-25 00:13:48 +053060 AdapterProxy *com.AdapterProxy
Devmalya Paulfb990a52019-07-09 10:01:49 -040061 EventProxy *com.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070062 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070063 exitChannel chan int
64 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053065 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070066 transitionMap *TransitionMap
67 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053068 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040069 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053070 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040071 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070072 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070073 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070074}
75
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070077type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070079 deviceType string
80 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081 onuID uint32
82 intfID uint32
83 proxyDeviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070084}
85
86//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070090 device.deviceType = deviceTp
91 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070092 device.onuID = onuID
93 device.intfID = intfID
94 device.proxyDeviceID = proxyDevID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070095 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +053096}
97
98//NewDeviceHandler creates a new device handler
Devmalya Paulfb990a52019-07-09 10:01:49 -040099func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, ep *com.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700100 var dh DeviceHandler
101 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400102 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400103 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700104 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700105 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700106 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400107 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700108 dh.device = cloned
109 dh.openOLT = adapter
110 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400111 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700112 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400115 // when the first IntfOperInd with status as "up" is received for
116 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530118
cuilin20187b2a8c32019-03-26 19:52:28 -0700119 //TODO initialize the support classes.
120 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530121}
122
123// start save the device to the data model
124func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700125 dh.lockDevice.Lock()
126 defer dh.lockDevice.Unlock()
127 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
128 // Add the initial device to the local model
129 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530130}
131
132// stop stops the device dh. Not much to do for now
133func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700134 dh.lockDevice.Lock()
135 defer dh.lockDevice.Unlock()
136 log.Debug("stopping-device-agent")
137 dh.exitChannel <- 1
138 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530139}
140
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400141func macifyIP(ip net.IP) string {
142 if len(ip) > 0 {
143 oct1 := strconv.FormatInt(int64(ip[12]), 16)
144 oct2 := strconv.FormatInt(int64(ip[13]), 16)
145 oct3 := strconv.FormatInt(int64(ip[14]), 16)
146 oct4 := strconv.FormatInt(int64(ip[15]), 16)
147 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
148 }
149 return ""
150}
151
152func generateMacFromHost(host string) (string, error) {
153 var genmac string
154 var addr net.IP
155 var ips []string
156 var err error
157
158 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
159
160 if addr = net.ParseIP(host); addr == nil {
161 log.Debugw("looking-up-hostname", log.Fields{"host": host})
162
163 if ips, err = net.LookupHost(host); err == nil {
164 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
165 if addr = net.ParseIP(ips[0]); addr == nil {
166 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
167 return "", errors.New("unable-to-parse-ip")
168 }
169 genmac = macifyIP(addr)
170 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
171 return genmac, nil
172 }
173 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
174 return "", err
175 }
176
177 genmac = macifyIP(addr)
178 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
179 return genmac, nil
180}
181
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530182func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700183 slist := strings.Split(mac, ":")
184 result := make([]uint32, len(slist))
185 var err error
186 var tmp int64
187 for index, val := range slist {
188 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
189 return []uint32{1, 2, 3, 4, 5, 6}
190 }
191 result[index] = uint32(tmp)
192 }
193 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700196//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 +0530197func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530198
Girish Gowdru0c588b22019-04-23 23:24:56 -0400199 if portType == voltha.Port_ETHERNET_NNI {
200 return fmt.Sprintf("nni-%d", portNum)
201 } else if portType == voltha.Port_PON_OLT {
202 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 } else if portType == voltha.Port_ETHERNET_UNI {
204 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400205 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700206 }
207 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530208}
209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700211 var operStatus common.OperStatus_OperStatus
212 if state == "up" {
213 operStatus = voltha.OperStatus_ACTIVE
214 } else {
215 operStatus = voltha.OperStatus_DISCOVERED
216 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400218 label := GetportLabel(portNum, portType)
219 if len(label) == 0 {
220 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
221 return
222 }
223 // Now create Port
224 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 PortNo: portNum,
226 Label: label,
227 Type: portType,
228 OperStatus: operStatus,
229 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400230 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700232 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
233 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400234 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235
Girish Gowdru1110ef22019-06-24 11:17:59 -0400236 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
238 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
239 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700240 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
243// readIndications to read the indications from the OLT device
244func (dh *DeviceHandler) readIndications() {
William Kurkian294a78b2019-08-20 10:34:30 -0400245 defer log.Errorw("Indications ended", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400246 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700247 if err != nil {
248 log.Errorw("Failed to read indications", log.Fields{"err": err})
249 return
250 }
251 if indications == nil {
252 log.Errorw("Indications is nil", log.Fields{})
253 return
254 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400255 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700256 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400257 if err != nil || device == nil {
258 /*TODO: needs to handle error scenarios */
259 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700260 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400261 }
262 // When the device is in DISABLED and Adapter container restarts, we need to
263 // rebuild the locally maintained admin state.
264 if device.AdminState == voltha.AdminState_DISABLED {
265 dh.lockDevice.Lock()
266 dh.adminState = "down"
267 dh.lockDevice.Unlock()
268 }
269
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 for {
271 indication, err := indications.Recv()
272 if err == io.EOF {
273 break
274 }
275 if err != nil {
276 log.Infow("Failed to read from indications", log.Fields{"err": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400277 dh.transitionMap.Handle(DeviceDownInd)
278 dh.transitionMap.Handle(DeviceInit)
279 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700280 }
Chaitrashree G S44124192019-08-07 20:21:36 -0400281 dh.lockDevice.RLock()
282 adminState := dh.adminState
283 dh.lockDevice.RUnlock()
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400284 // When OLT is admin down, allow only NNI operation status change indications.
Chaitrashree G S44124192019-08-07 20:21:36 -0400285 if adminState == "down" {
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400286 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
287 if isIntfOperInd {
288 intfOperInd := indication.GetIntfOperInd()
289 if intfOperInd.GetType() == "nni" {
290 log.Infow("olt is admin down, allow nni ind", log.Fields{})
291 }
292 } else {
293 log.Infow("olt is admin down, ignore indication", log.Fields{})
294 continue
295 }
296 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700298 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530299
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700300 }
301}
302
303func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
Daniele Rossi051466a2019-07-26 13:39:37 +0000304 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700305 if oltIndication.OperState == "up" {
306 dh.transitionMap.Handle(DeviceUpInd)
307 } else if oltIndication.OperState == "down" {
308 dh.transitionMap.Handle(DeviceDownInd)
309 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000310 // Send or clear Alarm
311 dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700312}
313
314func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400315 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700316 switch indication.Data.(type) {
317 case *oop.Indication_OltInd:
318 dh.handleOltIndication(indication.GetOltInd())
319 case *oop.Indication_IntfInd:
320 intfInd := indication.GetIntfInd()
321 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
322 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
323 case *oop.Indication_IntfOperInd:
324 intfOperInd := indication.GetIntfOperInd()
325 if intfOperInd.GetType() == "nni" {
326 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
327 } else if intfOperInd.GetType() == "pon" {
328 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
329 // Handle pon port update
cuilin20187b2a8c32019-03-26 19:52:28 -0700330 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700331 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
332 case *oop.Indication_OnuDiscInd:
333 onuDiscInd := indication.GetOnuDiscInd()
334 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Matt Jeanneret53539512019-07-20 14:47:02 -0400336 go dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700337 case *oop.Indication_OnuInd:
338 onuInd := indication.GetOnuInd()
339 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
340 go dh.onuIndication(onuInd)
341 case *oop.Indication_OmciInd:
342 omciInd := indication.GetOmciInd()
343 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
William Kurkian294a78b2019-08-20 10:34:30 -0400344 go dh.omciIndication(omciInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700345 case *oop.Indication_PktInd:
346 pktInd := indication.GetPktInd()
347 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
348 go dh.handlePacketIndication(pktInd)
349 case *oop.Indication_PortStats:
350 portStats := indication.GetPortStats()
351 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
352 case *oop.Indication_FlowStats:
353 flowStats := indication.GetFlowStats()
354 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
355 case *oop.Indication_AlarmInd:
356 alarmInd := indication.GetAlarmInd()
357 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Devmalya Paulfb990a52019-07-09 10:01:49 -0400358 dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
359
cuilin20187b2a8c32019-03-26 19:52:28 -0700360 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530361}
362
363// doStateUp handle the olt up indication and update to voltha core
364func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400365 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700366 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400367 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 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 -0400369 return err
370 }
371 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530372}
373
374// doStateDown handle the olt down indication
375func (dh *DeviceHandler) doStateDown() error {
Girish Gowdrud4245152019-05-10 00:47:31 -0400376 log.Debug("do-state-down-start")
377
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700378 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400379 if err != nil || device == nil {
380 /*TODO: needs to handle error scenarios */
381 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700382 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400383 }
384
385 cloned := proto.Clone(device).(*voltha.Device)
386 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
388 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
389 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400390 }
391
392 //Update the device oper state and connection status
393 cloned.OperStatus = voltha.OperStatus_UNKNOWN
394 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
395 dh.device = cloned
396
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700397 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
398 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
399 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400400 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400401
402 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400404 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700405 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400406 return err
407 }
408 for _, onuDevice := range onuDevices.Items {
409
410 // Update onu state as down in onu adapter
411 onuInd := oop.OnuIndication{}
412 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700413 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
414 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
415 if er != nil {
416 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
417 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
418 return er
419 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400420 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700421 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700422 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530423}
424
425// doStateInit dial the grpc before going to init state
426func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400427 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400428 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400429 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400431 return err
432 }
433 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530434}
435
436// postInit create olt client instance to invoke RPC on the olt device
437func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400438 dh.Client = oop.NewOpenoltClient(dh.clientCon)
439 dh.transitionMap.Handle(GrpcConnected)
440 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530441}
442
443// doStateConnected get the device info and update to voltha core
444func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400445 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400446
447 // Case where OLT is disabled and then rebooted.
448 if dh.adminState == "down" {
449 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700450 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400451 if err != nil || device == nil {
452 /*TODO: needs to handle error scenarios */
453 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
454 }
455
456 cloned := proto.Clone(device).(*voltha.Device)
457 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
458 cloned.OperStatus = voltha.OperStatus_UNKNOWN
459 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
461 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400462 }
463
Chaitrashree G S44124192019-08-07 20:21:36 -0400464 // 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 -0400465 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
466 if err != nil {
467 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
468 }
469
470 // Start reading indications
471 go dh.readIndications()
472 return nil
473 }
474
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400475 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700476 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400477 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700478 return err
479 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400480
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700481 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400482 if err != nil || device == nil {
483 /*TODO: needs to handle error scenarios */
484 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700485 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400486 }
487 cloned := proto.Clone(device).(*voltha.Device)
488 // Update the all ports (if available) on that device to ACTIVE.
489 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
491 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400492 return err
493 }
494
Girish Gowdru0c588b22019-04-23 23:24:56 -0400495 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
496 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700497 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400498 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400500 }
501 // Instantiate flow manager
502 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
503 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400505 }
506 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400507 /* Instantiating Event Manager to handle Alarms and KPIs */
508 dh.eventMgr = NewEventMgr(dh.EventProxy)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530509
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 // Start reading indications
511 go dh.readIndications()
512 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530513}
514
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400515func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
516 var err error
517 var deviceInfo *oop.DeviceInfo
518
519 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
520
521 if err != nil {
522 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
523 return nil, err
524 }
525 if deviceInfo == nil {
526 log.Errorw("Device info is nil", log.Fields{})
527 return nil, errors.New("failed to get device info from OLT")
528 }
529
530 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
531 dh.device.Root = true
532 dh.device.Vendor = deviceInfo.Vendor
533 dh.device.Model = deviceInfo.Model
534 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
535 dh.device.HardwareVersion = deviceInfo.HardwareVersion
536 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
537
538 if deviceInfo.DeviceId == "" {
539 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
540 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
541 genmac, err := generateMacFromHost(host)
542 if err != nil {
543 return nil, err
544 }
545 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
546 dh.device.MacAddress = genmac
547 } else {
548 dh.device.MacAddress = deviceInfo.DeviceId
549 }
550
551 // Synchronous call to update device - this method is run in its own go routine
552 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
553 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
554 return nil, err
555 }
556
557 return deviceInfo, nil
558}
559
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700560//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530561func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400562 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400564 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530565}
566
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530568func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700569 return &ic.SwitchCapability{
570 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530571 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700572 HwDesc: "open_pon",
573 SwDesc: "open_pon",
574 SerialNum: dh.device.SerialNumber,
575 },
576 SwitchFeatures: &of.OfpSwitchFeatures{
577 NBuffers: 256,
578 NTables: 2,
579 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
580 of.OfpCapabilities_OFPC_TABLE_STATS |
581 of.OfpCapabilities_OFPC_PORT_STATS |
582 of.OfpCapabilities_OFPC_GROUP_STATS),
583 },
584 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530585}
586
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530588func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700590 return &ic.PortCapability{
591 Port: &voltha.LogicalPort{
592 OfpPort: &of.OfpPort{
593 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
594 Config: 0,
595 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700596 Curr: capacity,
597 Advertised: capacity,
598 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700599 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
600 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
601 },
602 DeviceId: dh.device.Id,
603 DevicePortNo: uint32(portNo),
604 },
605 }, nil
606}
607
William Kurkian294a78b2019-08-20 10:34:30 -0400608func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700610 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 var deviceID string
612 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700613
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700614 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
615 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
617 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700618 kwargs := make(map[string]interface{})
619 kwargs["onu_id"] = omciInd.OnuId
620 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700621
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
623 if err != nil {
William Kurkian294a78b2019-08-20 10:34:30 -0400624 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
625 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700626 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700627 deviceType = onuDevice.Type
628 deviceID = onuDevice.Id
629 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
630 //if not exist in cache, then add to cache.
631 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700632 } else {
633 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700635 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636 deviceID = onuInCache.deviceID
637 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700638 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700639
640 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
641 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
642 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 deviceID, proxyDeviceID, ""); sendErr != nil {
William Kurkian294a78b2019-08-20 10:34:30 -0400644 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
645 return
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700646 }
William Kurkian294a78b2019-08-20 10:34:30 -0400647 return
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530648}
649
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650//ProcessInterAdapterMessage sends the proxied messages to the target device
651// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
652// is meant, and then send the unmarshalled omci message to this onu
653func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
654 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700655 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700657 fromTopic := msg.Header.FromTopic
658 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 toDeviceID := msg.Header.ToDeviceId
660 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700663
664 msgBody := msg.GetBody()
665
666 omciMsg := &ic.InterAdapterOmciMessage{}
667 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
668 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
669 return err
670 }
671
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700672 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
674 if err != nil {
675 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700676 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700677 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
679 dh.sendProxiedMessage(onuDevice, omciMsg)
680
cuilin20187b2a8c32019-03-26 19:52:28 -0700681 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 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 -0700683 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700684 }
685
686 } else {
687 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
688 }
689 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530690}
691
cuilin20187b2a8c32019-03-26 19:52:28 -0700692func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 var intfID uint32
694 var onuID uint32
695 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700696 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 intfID = onuDevice.ProxyAddress.GetChannelId()
698 onuID = onuDevice.ProxyAddress.GetOnuId()
699 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700700 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 intfID = omciMsg.GetProxyAddress().GetChannelId()
702 onuID = omciMsg.GetProxyAddress().GetOnuId()
703 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700704 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 if connectStatus != voltha.ConnectStatus_REACHABLE {
706 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700707 return
708 }
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
713 if err != nil {
714 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
715 return
716 }
717 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700718}
719
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
721 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
722 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700723 // TODO: need resource manager
724 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530726 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400727 st, _ := status.FromError(err)
728 if st.Code() == codes.AlreadyExists {
729 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
730 } else {
731 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
732 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700733 } else {
734 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
735 }
736}
737
Matt Jeanneret53539512019-07-20 14:47:02 -0400738func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 channelID := onuDiscInd.GetIntfId()
740 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400741
742 log.Debugw("new-discovery-indication", log.Fields{"sn": sn})
743 dh.lockDevice.Lock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400744 if _, ok := dh.discOnus[sn]; ok {
Matt Jeanneret53539512019-07-20 14:47:02 -0400745 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400746 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Matt Jeanneret53539512019-07-20 14:47:02 -0400747 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700748 }
749
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400750 dh.discOnus[sn] = true
Matt Jeanneret53539512019-07-20 14:47:02 -0400751 log.Debugw("new-discovery-indications-list", log.Fields{"discOnus": dh.discOnus})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400752 dh.lockDevice.Unlock()
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400753
cuilin20187b2a8c32019-03-26 19:52:28 -0700754 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400755 if sn != "" {
756 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400757 } else {
Matt Jeanneret53539512019-07-20 14:47:02 -0400758 log.Errorw("invalid onu serial number", log.Fields{"sn": sn})
759 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400760 }
761
762 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
763 var onuID uint32
764 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700765 //This is the first time ONU discovered. Create an OnuID for it.
Matt Jeanneret53539512019-07-20 14:47:02 -0400766 ponintfid := onuDiscInd.GetIntfId()
767 dh.lockDevice.Lock()
768 onuID, err = dh.resourceMgr.GetONUID(ponintfid)
769 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400770 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400771 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"pon-intf-id": ponintfid, "err": err})
772 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400773 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700774 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G See824a22019-07-28 18:28:27 -0400775 "", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700776 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400777 log.Errorw("Create onu error",
778 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
779 "onuID": onuID, "sn": sn, "error": err})
Matt Jeanneret53539512019-07-20 14:47:02 -0400780 return
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400781 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400782 log.Debugw("onu-child-device-added", log.Fields{"onuDevice": onuDevice})
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400783
784 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700785 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400786 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400787 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700788 //Insert the ONU into cache to use in OnuIndication.
789 //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 -0700790 log.Debugw("ONU discovery indication key create", log.Fields{"onuID": onuID,
791 "intfId": onuDiscInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700792 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -0400793
794 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700795 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400796 log.Debugw("new-onu-device-discovered", log.Fields{"onu": dh.onus[onuKey]})
797 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400798
Mahir Gunyele77977b2019-06-27 05:36:22 -0700799 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
800 if err != nil {
Matt Jeanneret53539512019-07-20 14:47:02 -0400801 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id, "err": err})
802 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700803 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700804 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
805 //TODO: We put this sleep here to prevent the race between state update and onuIndication
806 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
807 //then the initialisation fails.
808 time.Sleep(1 * time.Second)
809 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
Matt Jeanneret53539512019-07-20 14:47:02 -0400810 return
cuilin20187b2a8c32019-03-26 19:52:28 -0700811}
812
813func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
814 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
815
816 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700818 var onuDevice *voltha.Device
819 foundInCache := false
Scott Baker7eb0a932019-07-26 10:33:22 -0700820 log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
821 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -0700822 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
823 if onuInCache, ok := dh.onus[onuKey]; ok {
824 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
825 foundInCache = true
826 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700827 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700828 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
829 if serialNumber != "" {
830 kwargs["serial_number"] = serialNumber
831 } else {
832 kwargs["onu_id"] = onuInd.OnuId
833 kwargs["parent_port_no"] = ponPort
834 }
835 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700836 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700837
838 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400839 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 //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 -0400841 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700842 }
843
844 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
845 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})
846 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700847 if !foundInCache {
848 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
Matt Jeanneret53539512019-07-20 14:47:02 -0400849 dh.lockDevice.Lock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700850 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Matt Jeanneret53539512019-07-20 14:47:02 -0400851 dh.lockDevice.Unlock()
Mahir Gunyele77977b2019-06-27 05:36:22 -0700852 }
Scott Baker7eb0a932019-07-26 10:33:22 -0700853 dh.updateOnuStates(onuDevice, onuInd, foundInCache)
cuilin20187b2a8c32019-03-26 19:52:28 -0700854
cuilin20187b2a8c32019-03-26 19:52:28 -0700855 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700857 return
858 }
859
860}
861
Scott Baker7eb0a932019-07-26 10:33:22 -0700862func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
Matt Jeanneret53539512019-07-20 14:47:02 -0400863 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 -0700864 dh.updateOnuAdminState(onuInd)
865 // operState
866 if onuInd.OperState == "down" {
Matt Jeanneret53539512019-07-20 14:47:02 -0400867 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 -0700868 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
869 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
870 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
871 if err != nil {
872 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
873 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
874 }
875 } else if onuInd.OperState == "up" {
Scott Baker7eb0a932019-07-26 10:33:22 -0700876 // Ignore operstatus if device was found in cache
877 if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
Matt Jeanneret53539512019-07-20 14:47:02 -0400878 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 -0700879 return
880 }
Matt Jeanneret53539512019-07-20 14:47:02 -0400881 log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
882 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
884 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
885 if err != nil {
886 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
887 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
888 return
889 }
890 } else {
891 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
892 }
893}
894
895func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
896 if onuInd.AdminState == "down" {
897 if onuInd.OperState != "down" {
898 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
899 // Forcing the oper state change code to execute
900 onuInd.OperState = "down"
901 }
902 // Port and logical port update is taken care of by oper state block
903 } else if onuInd.AdminState == "up" {
904 log.Debugln("received-onu-admin-state up")
905 } else {
906 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
907 }
908 log.Debugln("admin-state-dealt-with")
909}
910
cuilin20187b2a8c32019-03-26 19:52:28 -0700911func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
912 if serialNum != nil {
913 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700914 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700915 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700916}
917
918func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
919 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700921 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
922 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
923 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
924 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
925 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
926 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
927 return tmp
928}
929
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930//UpdateFlowsBulk upates the bulk flow
931func (dh *DeviceHandler) UpdateFlowsBulk() error {
932 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700933}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934
935//GetChildDevice returns the child device for given parent port and onu id
936func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
937 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400938 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400940 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400942 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400944 return nil
945 }
946 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
947 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530948}
949
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950// SendPacketInToCore sends packet-in to core
951// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
952// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400953func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
954 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700955 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400956 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
957 return
958 }
959 log.Debug("Sent packet-in to core successfully")
960}
961
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700962//UpdateFlowsIncrementally updates the device flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400963func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
964 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 -0400965 if flows != nil {
966 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400967 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400968 dh.flowMgr.AddFlow(flow, flowMetadata)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400969 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400970 for _, flow := range flows.ToRemove.Items {
971 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
972 dh.flowMgr.RemoveFlow(flow)
973 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400974 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400976 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400978 // dh.flowMgr.RemoveFlow(flow)
979 }
980 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400981 log.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400982 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530983}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985//DisableDevice disables the given device
986//It marks the following for the given device:
987//Device-Handler Admin-State : down
988//Device Port-State: UNKNOWN
989//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400990func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -0400991 /* On device disable ,admin state update has to be done prior sending request to agent since
992 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400993 dh.lockDevice.Lock()
994 dh.adminState = "down"
995 dh.lockDevice.Unlock()
Chaitrashree G S44124192019-08-07 20:21:36 -0400996 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
997 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
998 dh.lockDevice.Lock()
999 dh.adminState = "up"
1000 dh.lockDevice.Unlock()
1001 return err
1002 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001003 log.Debug("olt-disabled")
Chaitrashree G S44124192019-08-07 20:21:36 -04001004 dh.lockDevice.Lock()
1005 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
1006 UNREACHABLE state which needs to be configured again*/
1007 dh.discOnus = make(map[string]bool)
1008 dh.lockDevice.Unlock()
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001009
1010 cloned := proto.Clone(device).(*voltha.Device)
1011 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
1013 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001014 return err
1015 }
1016
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 log.Debugw("Disable_device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001018 return nil
1019}
1020
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021//ReenableDevice re-enables the olt device after disable
1022//It marks the following for the given device:
1023//Device-Handler Admin-State : up
1024//Device Port-State: ACTIVE
1025//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001026func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1027 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1028 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1029 return err
1030 }
1031
1032 dh.lockDevice.Lock()
1033 dh.adminState = "up"
1034 dh.lockDevice.Unlock()
1035 log.Debug("olt-reenabled")
1036
1037 cloned := proto.Clone(device).(*voltha.Device)
1038 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); 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
1044 //Update the device oper status as ACTIVE
1045 cloned.OperStatus = voltha.OperStatus_ACTIVE
1046 dh.device = cloned
1047
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001048 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1049 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001050 return err
1051 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001053
1054 return nil
1055}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001056
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001058func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1059 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1060 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
1061 return err
1062 }
1063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001064 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001065
1066 return nil
1067}
1068
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001069func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1070 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1071 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1072 if err != nil {
1073 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1074 return
1075 }
1076 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001078 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1079 return
1080 }
1081 log.Debug("Success sending packet-in to core!")
1082}
1083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1085func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001086 log.Debugw("incoming-packet-out", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo,
1087 "pkt-length": len(packet.Data), "packetData": hex.EncodeToString(packet.Data)})
1088
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001089 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001090 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001091 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1092 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1093 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1094 if innerEthType == 0x8100 {
1095 // q-in-q 802.1ad or 802.1q double tagged packet.
1096 // slice out the outer tag.
1097 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
1098 log.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001099 }
1100 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1102 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001103 uniID := UniIDFromPortNum(uint32(egressPortNo))
1104
1105 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(intfID, onuID, uint32(egressPortNo))
1106 if err != nil {
1107 // In this case the openolt agent will receive the gemPortID as 0.
1108 // The agent tries to retrieve the gemPortID in this case.
1109 // This may not always succeed at the agent and packetOut may fail.
1110 log.Error("failed-to-retrieve-gemport-id-for-packet-out")
1111 }
1112
1113 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001114
1115 log.Debugw("sending-packet-to-onu", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
Manikkaraj kb1d51442019-07-23 10:41:02 -04001116 "uniID": uniID, "gemPortID": gemPortID, "packet": hex.EncodeToString(packet.Data)})
Matt Jeanneret1359c732019-08-01 21:40:02 -04001117
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001118 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1119 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1120 return err
1121 }
1122 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001123 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001124
1125 log.Debugw("sending-packet-to-nni", log.Fields{"uplink_pkt": uplinkPkt, "packet": hex.EncodeToString(packet.Data)})
1126
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001127 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001128 log.Errorw("Error while sending packet-out to NNI", log.Fields{"error": err})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001129 return err
1130 }
1131 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 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 -04001133 }
1134 return nil
1135}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001136
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1138 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001139}