blob: 3bb34dbf7cea010c401faf605c97e3a67cdceda1 [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 */
16package adaptercore
17
18import (
cuilin20187b2a8c32019-03-26 19:52:28 -070019 "context"
20 "errors"
21 "fmt"
22 "io"
23 "strconv"
24 "strings"
25 "sync"
26 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053027
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "github.com/gogo/protobuf/proto"
29 "github.com/golang/protobuf/ptypes"
30 com "github.com/opencord/voltha-go/adapters/common"
31 "github.com/opencord/voltha-go/common/log"
Girish Gowdru0c588b22019-04-23 23:24:56 -040032 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053033 "github.com/opencord/voltha-protos/go/common"
34 ic "github.com/opencord/voltha-protos/go/inter_container"
35 of "github.com/opencord/voltha-protos/go/openflow_13"
36 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053037 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070038 "google.golang.org/grpc"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053039)
40
41//DeviceHandler will interact with the OLT device.
42type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070043 deviceId string
44 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040045 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070046 device *voltha.Device
47 coreProxy *com.CoreProxy
manikkaraj kbf256be2019-03-25 00:13:48 +053048 AdapterProxy *com.AdapterProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070049 openOLT *OpenOLT
50 nniPort *voltha.Port
51 ponPort *voltha.Port
52 exitChannel chan int
53 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053054 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070055 transitionMap *TransitionMap
56 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053057 flowMgr *OpenOltFlowMgr
58 resourceMgr *rsrcMgr.OpenOltResourceMgr
Phaneendra Manda4c62c802019-03-06 21:37:49 +053059}
60
61//NewDeviceHandler creates a new device handler
cuilin20187b2a8c32019-03-26 19:52:28 -070062func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
63 var dh DeviceHandler
64 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -040065 dh.AdapterProxy = ap
cuilin20187b2a8c32019-03-26 19:52:28 -070066 cloned := (proto.Clone(device)).(*voltha.Device)
67 dh.deviceId = cloned.Id
68 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -040069 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -070070 dh.device = cloned
71 dh.openOLT = adapter
72 dh.exitChannel = make(chan int, 1)
73 dh.lockDevice = sync.RWMutex{}
Phaneendra Manda4c62c802019-03-06 21:37:49 +053074
cuilin20187b2a8c32019-03-26 19:52:28 -070075 //TODO initialize the support classes.
76 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +053077}
78
79// start save the device to the data model
80func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -070081 dh.lockDevice.Lock()
82 defer dh.lockDevice.Unlock()
83 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
84 // Add the initial device to the local model
85 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +053086}
87
88// stop stops the device dh. Not much to do for now
89func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -070090 dh.lockDevice.Lock()
91 defer dh.lockDevice.Unlock()
92 log.Debug("stopping-device-agent")
93 dh.exitChannel <- 1
94 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +053095}
96
97func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -070098 slist := strings.Split(mac, ":")
99 result := make([]uint32, len(slist))
100 var err error
101 var tmp int64
102 for index, val := range slist {
103 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
104 return []uint32{1, 2, 3, 4, 5, 6}
105 }
106 result[index] = uint32(tmp)
107 }
108 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530109}
110
manikkaraj kbf256be2019-03-25 00:13:48 +0530111func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530112
Girish Gowdru0c588b22019-04-23 23:24:56 -0400113 if portType == voltha.Port_ETHERNET_NNI {
114 return fmt.Sprintf("nni-%d", portNum)
115 } else if portType == voltha.Port_PON_OLT {
116 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700117 } else if portType == voltha.Port_ETHERNET_UNI {
118 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400119 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700120 }
121 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530122}
123
124func (dh *DeviceHandler) addPort(intfId uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700125 var operStatus common.OperStatus_OperStatus
126 if state == "up" {
127 operStatus = voltha.OperStatus_ACTIVE
128 } else {
129 operStatus = voltha.OperStatus_DISCOVERED
130 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400131 // portNum := IntfIdToPortNo(intfId,portType)
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 portNum := intfId
manikkaraj k17652a72019-05-06 09:06:36 -0400133 if portType == voltha.Port_ETHERNET_NNI {
134 portNum = IntfIdToPortNo(intfId, portType)
135 }
136 // portNum := IntfIdToPortNo(intfId,portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400137 label := GetportLabel(portNum, portType)
138 if len(label) == 0 {
139 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
140 return
141 }
142 // Now create Port
143 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700144 PortNo: portNum,
145 Label: label,
146 Type: portType,
147 OperStatus: operStatus,
148 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400149 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700150 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru0c588b22019-04-23 23:24:56 -0400151 if err := dh.coreProxy.PortCreated(nil, dh.device.Id, port); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": dh.device.Id, "error": err})
153 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530154}
155
156// readIndications to read the indications from the OLT device
157func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400158 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700159 if err != nil {
160 log.Errorw("Failed to read indications", log.Fields{"err": err})
161 return
162 }
163 if indications == nil {
164 log.Errorw("Indications is nil", log.Fields{})
165 return
166 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400167 /* get device state */
168 device, err := dh.coreProxy.GetDevice(nil, dh.device.Id, dh.device.Id)
169 if err != nil || device == nil {
170 /*TODO: needs to handle error scenarios */
171 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
172
173 }
174 // When the device is in DISABLED and Adapter container restarts, we need to
175 // rebuild the locally maintained admin state.
176 if device.AdminState == voltha.AdminState_DISABLED {
177 dh.lockDevice.Lock()
178 dh.adminState = "down"
179 dh.lockDevice.Unlock()
180 }
181
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 for {
183 indication, err := indications.Recv()
184 if err == io.EOF {
185 break
186 }
187 if err != nil {
188 log.Infow("Failed to read from indications", log.Fields{"err": err})
189 continue
190 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400191 // When OLT is admin down, allow only NNI operation status change indications.
192 if dh.adminState == "down" {
193 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
194 if isIntfOperInd {
195 intfOperInd := indication.GetIntfOperInd()
196 if intfOperInd.GetType() == "nni" {
197 log.Infow("olt is admin down, allow nni ind", log.Fields{})
198 }
199 } else {
200 log.Infow("olt is admin down, ignore indication", log.Fields{})
201 continue
202 }
203 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 switch indication.Data.(type) {
205 case *oop.Indication_OltInd:
206 oltInd := indication.GetOltInd()
207 if oltInd.OperState == "up" {
208 dh.transitionMap.Handle(DeviceUpInd)
209 } else if oltInd.OperState == "down" {
210 dh.transitionMap.Handle(DeviceDownInd)
211 }
212 case *oop.Indication_IntfInd:
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530213
cuilin20187b2a8c32019-03-26 19:52:28 -0700214 intfInd := indication.GetIntfInd()
215 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
216 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
217 case *oop.Indication_IntfOperInd:
218 intfOperInd := indication.GetIntfOperInd()
219 if intfOperInd.GetType() == "nni" {
220 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
221 } else if intfOperInd.GetType() == "pon" {
222 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
223 // Handle pon port update
224 }
225 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
226 case *oop.Indication_OnuDiscInd:
227 onuDiscInd := indication.GetOnuDiscInd()
228 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400229 //onuId,err := dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
230 //onuId,err := dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
231 // TODO Get onu ID from the resource manager
cuilin20187b2a8c32019-03-26 19:52:28 -0700232 var onuId uint32 = 1
Girish Gowdru0c588b22019-04-23 23:24:56 -0400233 /*if err != nil{
234 log.Errorw("onu-id-unavailable",log.Fields{"intfId":onuDiscInd.GetIntfId()})
235 return
236 }*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530237
cuilin20187b2a8c32019-03-26 19:52:28 -0700238 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400239 //FIXME: Duplicate child devices being create in go routine
240 dh.onuDiscIndication(onuDiscInd, onuId, sn)
cuilin20187b2a8c32019-03-26 19:52:28 -0700241 case *oop.Indication_OnuInd:
242 onuInd := indication.GetOnuInd()
243 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
244 go dh.onuIndication(onuInd)
245 case *oop.Indication_OmciInd:
246 omciInd := indication.GetOmciInd()
247 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
248 if err := dh.omciIndication(omciInd); err != nil {
249 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
250 }
251 case *oop.Indication_PktInd:
252 pktInd := indication.GetPktInd()
253 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
254 case *oop.Indication_PortStats:
255 portStats := indication.GetPortStats()
256 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
257 case *oop.Indication_FlowStats:
258 flowStats := indication.GetFlowStats()
259 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
260 case *oop.Indication_AlarmInd:
261 alarmInd := indication.GetAlarmInd()
262 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
263 }
264 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530265}
266
267// doStateUp handle the olt up indication and update to voltha core
268func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400269 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400271 voltha.OperStatus_ACTIVE); err != nil {
272 log.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceId": dh.device.Id, "error": err})
273 return err
274 }
275 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530276}
277
278// doStateDown handle the olt down indication
279func (dh *DeviceHandler) doStateDown() error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700280 //TODO Handle oper state down
281 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530282}
283
284// doStateInit dial the grpc before going to init state
285func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400286 var err error
287 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure())
288 if err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceId, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400290 return err
291 }
292 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293}
294
295// postInit create olt client instance to invoke RPC on the olt device
296func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400297 dh.Client = oop.NewOpenoltClient(dh.clientCon)
298 dh.transitionMap.Handle(GrpcConnected)
299 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530300}
301
302// doStateConnected get the device info and update to voltha core
303func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400304 log.Debug("OLT device has been connected")
305 deviceInfo, err := dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700306 if err != nil {
307 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
308 return err
309 }
310 if deviceInfo == nil {
311 log.Errorw("Device info is nil", log.Fields{})
312 return errors.New("Failed to get device info from OLT")
313 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530314
cuilin20187b2a8c32019-03-26 19:52:28 -0700315 dh.device.Root = true
316 dh.device.Vendor = deviceInfo.Vendor
317 dh.device.Model = deviceInfo.Model
318 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
319 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
320 dh.device.HardwareVersion = deviceInfo.HardwareVersion
321 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
322 // TODO : Check whether this MAC address is learnt from SDPON or need to send from device
323 dh.device.MacAddress = "0a:0b:0c:0d:0e:0f"
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530324
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 // Synchronous call to update device - this method is run in its own go routine
326 if err := dh.coreProxy.DeviceUpdate(nil, dh.device); err != nil {
327 log.Errorw("error-updating-device", log.Fields{"deviceId": dh.device.Id, "error": err})
328 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400329 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
330 // Instantiate resource manager
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400331 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceId, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400332 log.Error("Error while instantiating resource manager")
333 return errors.New("Instantiating resource manager failed")
334 }
335 // Instantiate flow manager
336 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
337 log.Error("Error while instantiating flow manager")
338 return errors.New("Instantiating flow manager failed")
339 }
340 /* TODO: Instantiate Alarm , stats , BW managers */
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530341
cuilin20187b2a8c32019-03-26 19:52:28 -0700342 // Start reading indications
343 go dh.readIndications()
344 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530345}
346
347// AdoptDevice adopts the OLT device
348func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400349 dh.transitionMap = NewTransitionMap(dh)
cuilin20187b2a8c32019-03-26 19:52:28 -0700350 log.Infow("AdoptDevice", log.Fields{"deviceId": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400351 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530352}
353
354// GetOfpDeviceInfo Get the Ofp device information
355func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700356 return &ic.SwitchCapability{
357 Desc: &of.OfpDesc{
358 HwDesc: "open_pon",
359 SwDesc: "open_pon",
360 SerialNum: dh.device.SerialNumber,
361 },
362 SwitchFeatures: &of.OfpSwitchFeatures{
363 NBuffers: 256,
364 NTables: 2,
365 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
366 of.OfpCapabilities_OFPC_TABLE_STATS |
367 of.OfpCapabilities_OFPC_PORT_STATS |
368 of.OfpCapabilities_OFPC_GROUP_STATS),
369 },
370 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530371}
372
373// GetOfpPortInfo Get Ofp port information
374func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700375 cap := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
376 return &ic.PortCapability{
377 Port: &voltha.LogicalPort{
378 OfpPort: &of.OfpPort{
379 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
380 Config: 0,
381 State: uint32(of.OfpPortState_OFPPS_LIVE),
382 Curr: cap,
383 Advertised: cap,
384 Peer: cap,
385 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
386 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
387 },
388 DeviceId: dh.device.Id,
389 DevicePortNo: uint32(portNo),
390 },
391 }, nil
392}
393
394func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
395 log.Debugw("omci indication", log.Fields{"intfId": omciInd.IntfId, "onuId": omciInd.OnuId})
396
Girish Gowdru0c588b22019-04-23 23:24:56 -0400397 // ponPort := IntfIdToPortNo(omciInd.GetIntfId(),voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -0700398 kwargs := make(map[string]interface{})
399 kwargs["onu_id"] = omciInd.OnuId
400 kwargs["parent_port_no"] = omciInd.GetIntfId()
401
402 if onuDevice, err := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); err != nil {
403 log.Errorw("onu not found", log.Fields{"intfId": omciInd.IntfId, "onuId": omciInd.OnuId})
404 return err
405 } else {
406 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
manikkaraj kbf256be2019-03-25 00:13:48 +0530407 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
cuilin20187b2a8c32019-03-26 19:52:28 -0700408 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, onuDevice.Type,
409 onuDevice.Id, onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
410 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": onuDevice.Type, "onuId": onuDevice.Id, "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
411 return sendErr
412 }
413 return nil
414 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530415}
416
417// Process_inter_adapter_message process inter adater message
418func (dh *DeviceHandler) Process_inter_adapter_message(msg *ic.InterAdapterMessage) error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700419 // TODO
420 log.Debugw("Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id})
421 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
422 msgId := msg.Header.Id
423 fromTopic := msg.Header.FromTopic
424 toTopic := msg.Header.ToTopic
425 toDeviceId := msg.Header.ToDeviceId
426 proxyDeviceId := msg.Header.ProxyDeviceId
427
428 log.Debugw("omci request message header", log.Fields{"msgId": msgId, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceId": toDeviceId, "proxyDeviceId": proxyDeviceId})
429
430 msgBody := msg.GetBody()
431
432 omciMsg := &ic.InterAdapterOmciMessage{}
433 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
434 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
435 return err
436 }
437
438 if onuDevice, err := dh.coreProxy.GetDevice(nil, dh.device.Id, toDeviceId); err != nil {
439 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceId, "error": err})
440 return err
441 } else {
442 dh.sendProxiedMessage(onuDevice, omciMsg)
443 }
444
445 } else {
446 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
447 }
448 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530449}
450
cuilin20187b2a8c32019-03-26 19:52:28 -0700451func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
452 if onuDevice.ConnectStatus != voltha.ConnectStatus_REACHABLE {
453 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"serialNumber": onuDevice.SerialNumber, "intfId": onuDevice.ProxyAddress.GetChannelId(), "onuId": onuDevice.ProxyAddress.GetOnuId()})
454 return
455 }
456
457 omciMessage := &oop.OmciMsg{IntfId: onuDevice.ProxyAddress.GetChannelId(), OnuId: onuDevice.ProxyAddress.GetOnuId(), Pkt: omciMsg.Message}
458
manikkaraj kbf256be2019-03-25 00:13:48 +0530459 dh.Client.OmciMsgOut(context.Background(), omciMessage)
cuilin20187b2a8c32019-03-26 19:52:28 -0700460 log.Debugw("omci-message-sent", log.Fields{"serialNumber": onuDevice.SerialNumber, "intfId": onuDevice.ProxyAddress.GetChannelId(), "omciMsg": string(omciMsg.Message)})
461}
462
463func (dh *DeviceHandler) activateONU(intfId uint32, onuId int64, serialNum *oop.SerialNumber, serialNumber string) {
464 log.Debugw("activate-onu", log.Fields{"intfId": intfId, "onuId": onuId, "serialNum": serialNum, "serialNumber": serialNumber})
465 // TODO: need resource manager
466 var pir uint32 = 1000000
467 Onu := oop.Onu{IntfId: intfId, OnuId: uint32(onuId), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530468 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700469 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu})
470 } else {
471 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
472 }
473}
474
475func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, onuId uint32, sn string) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400476 //channelId := MkUniPortNum(onuDiscInd.GetIntfId(), onuId, uint32(0))
477 //parentPortNo := IntfIdToPortNo(onuDiscInd.GetIntfId(),voltha.Port_PON_OLT)
478 channelId := onuDiscInd.GetIntfId()
479 parentPortNo := onuDiscInd.GetIntfId()
manikkaraj kbf256be2019-03-25 00:13:48 +0530480 if err := dh.coreProxy.ChildDeviceDetected(nil, dh.device.Id, int(parentPortNo), "brcm_openomci_onu", int(channelId), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuId)); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700481 log.Errorw("Create onu error", log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(), "onuId": onuId, "sn": sn, "error": err})
482 return err
483 }
484
485 kwargs := make(map[string]interface{})
486 kwargs["onu_id"] = onuId
487 kwargs["parent_port_no"] = onuDiscInd.GetIntfId()
488
489 for i := 0; i < 10; i++ {
490 if onuDevice, _ := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); onuDevice != nil {
491 dh.activateONU(onuDiscInd.IntfId, int64(onuId), onuDiscInd.SerialNumber, sn)
492 return nil
493 } else {
494 time.Sleep(1 * time.Second)
495 log.Debugln("Sleep 1 seconds to active onu, retry times ", i+1)
496 }
497 }
498 log.Errorw("Cannot query onu, dont activate it.", log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(), "onuId": onuId, "sn": sn})
499 return errors.New("Failed to activate onu")
500}
501
502func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
503 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
504
505 kwargs := make(map[string]interface{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400506 // ponPort := IntfIdToPortNo(onuInd.GetIntfId(),voltha.Port_PON_OLT)
manikkaraj kbf256be2019-03-25 00:13:48 +0530507
cuilin20187b2a8c32019-03-26 19:52:28 -0700508 if serialNumber != "" {
509 kwargs["serial_number"] = serialNumber
510 } else {
511 kwargs["onu_id"] = onuInd.OnuId
512 kwargs["parent_port_no"] = onuInd.GetIntfId()
513 }
514 if onuDevice, _ := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); onuDevice != nil {
515 //if intfIdFromPortNo(onuDevice.ParentPortNo) != onuInd.GetIntfId() {
516 if onuDevice.ParentPortNo != onuInd.GetIntfId() {
517 //log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": intfIdFromPortNo(onuDevice.ParentPortNo), "currentIntfId": onuInd.GetIntfId()})
518 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": onuInd.GetIntfId()})
519 }
520
521 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
522 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})
523 }
524
525 // adminState
526 if onuInd.AdminState == "down" {
527 if onuInd.OperState != "down" {
528 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
529 // Forcing the oper state change code to execute
530 onuInd.OperState = "down"
531 }
532 // Port and logical port update is taken care of by oper state block
533 } else if onuInd.AdminState == "up" {
534 log.Debugln("received-onu-admin-state up")
535 } else {
536 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
537 }
538 log.Debugln("admin-state-dealt-with")
539
540 // operState
541 if onuInd.OperState == "down" {
542 if onuDevice.ConnectStatus != common.ConnectStatus_UNREACHABLE {
543 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_UNREACHABLE, onuDevice.OperStatus)
544 log.Debugln("onu-oper-state-is-down")
545 }
546 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
547 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_UNREACHABLE, common.OperStatus_DISCOVERED)
548 }
549 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
550
551 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
manikkaraj kbf256be2019-03-25 00:13:48 +0530552 dh.AdapterProxy.SendInterAdapterMessage(nil, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST, "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
cuilin20187b2a8c32019-03-26 19:52:28 -0700553 } else if onuInd.OperState == "up" {
554 if onuDevice.ConnectStatus != common.ConnectStatus_REACHABLE {
555 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_REACHABLE, onuDevice.OperStatus)
556
557 }
558 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
559 log.Warnw("ignore onu indication", log.Fields{"intfId": onuInd.IntfId, "onuId": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
560 return
561 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530562 dh.AdapterProxy.SendInterAdapterMessage(nil, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST, "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
cuilin20187b2a8c32019-03-26 19:52:28 -0700563 } else {
564 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
565 }
566 } else {
567 log.Errorw("onu not found", log.Fields{"intfId": onuInd.IntfId, "onuId": onuInd.OnuId})
568 return
569 }
570
571}
572
573func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
574 if serialNum != nil {
575 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
576 } else {
577 return ""
578 }
579}
580
581func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
582 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
583 fmt.Sprintf("%x", (uint32(vendorSpecific[0]&0x0f))) +
584 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
585 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
586 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
587 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
588 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
589 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
590 return tmp
591}
592
593// flows
594func (dh *DeviceHandler) Update_flows_bulk() error {
595 return errors.New("UnImplemented")
596}
Girish Gowdru0c588b22019-04-23 23:24:56 -0400597func (dh *DeviceHandler) GetChildDevice(parentPort uint32, onuId uint32) *voltha.Device {
598 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuId": onuId})
599 kwargs := make(map[string]interface{})
600 kwargs["onu_id"] = onuId
601 kwargs["parent_port_no"] = parentPort
602 onuDevice, err := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs)
603 if err != nil {
604 log.Errorw("onu not found", log.Fields{"intfId": parentPort, "onuId": onuId})
605 return nil
606 }
607 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
608 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530609}
610
611func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400612 log.Debugw("In UpdateFlowsIncrementally", log.Fields{"deviceId": device.Id, "flows": flows, "groups": groups})
613 if flows != nil {
614 for _, flow := range flows.ToAdd.Items {
615 dh.flowMgr.AddFlow(flow)
616 }
617 }
618 if groups != nil {
619 for _, flow := range flows.ToRemove.Items {
620 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
621 // dh.flowMgr.RemoveFlow(flow)
622 }
623 }
624 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530625}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400626
627func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
628 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
629 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
630 return err
631 }
632 dh.lockDevice.Lock()
633 dh.adminState = "down"
634 dh.lockDevice.Unlock()
635 log.Debug("olt-disabled")
636
637 cloned := proto.Clone(device).(*voltha.Device)
638 // Update the all ports state on that device to disable
639 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
640 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
641 return err
642 }
643
644 //Update the device oper state
645 cloned.OperStatus = voltha.OperStatus_UNKNOWN
646 dh.device = cloned
647
648 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
649 log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
650 return err
651 }
652 log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
653 return nil
654}
655
656func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
657 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
658 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
659 return err
660 }
661
662 dh.lockDevice.Lock()
663 dh.adminState = "up"
664 dh.lockDevice.Unlock()
665 log.Debug("olt-reenabled")
666
667 cloned := proto.Clone(device).(*voltha.Device)
668 // Update the all ports state on that device to enable
669 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
670 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
671 return err
672 }
673
674 //Update the device oper status as ACTIVE
675 cloned.OperStatus = voltha.OperStatus_ACTIVE
676 dh.device = cloned
677
678 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
679 log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
680 return err
681 }
682 log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
683
684 return nil
685}