blob: f077eef625a643f15ca5e51cf6adb02d34e8657d [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
Girish Gowdru0c588b22019-04-23 23:24:56 -0400133 label := GetportLabel(portNum, portType)
134 if len(label) == 0 {
135 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
136 return
137 }
138 // Now create Port
139 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700140 PortNo: portNum,
141 Label: label,
142 Type: portType,
143 OperStatus: operStatus,
144 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400145 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700146 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru0c588b22019-04-23 23:24:56 -0400147 if err := dh.coreProxy.PortCreated(nil, dh.device.Id, port); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": dh.device.Id, "error": err})
149 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530150}
151
152// readIndications to read the indications from the OLT device
153func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400154 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 if err != nil {
156 log.Errorw("Failed to read indications", log.Fields{"err": err})
157 return
158 }
159 if indications == nil {
160 log.Errorw("Indications is nil", log.Fields{})
161 return
162 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400163 /* get device state */
164 device, err := dh.coreProxy.GetDevice(nil, dh.device.Id, dh.device.Id)
165 if err != nil || device == nil {
166 /*TODO: needs to handle error scenarios */
167 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
168
169 }
170 // When the device is in DISABLED and Adapter container restarts, we need to
171 // rebuild the locally maintained admin state.
172 if device.AdminState == voltha.AdminState_DISABLED {
173 dh.lockDevice.Lock()
174 dh.adminState = "down"
175 dh.lockDevice.Unlock()
176 }
177
cuilin20187b2a8c32019-03-26 19:52:28 -0700178 for {
179 indication, err := indications.Recv()
180 if err == io.EOF {
181 break
182 }
183 if err != nil {
184 log.Infow("Failed to read from indications", log.Fields{"err": err})
185 continue
186 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400187 // When OLT is admin down, allow only NNI operation status change indications.
188 if dh.adminState == "down" {
189 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
190 if isIntfOperInd {
191 intfOperInd := indication.GetIntfOperInd()
192 if intfOperInd.GetType() == "nni" {
193 log.Infow("olt is admin down, allow nni ind", log.Fields{})
194 }
195 } else {
196 log.Infow("olt is admin down, ignore indication", log.Fields{})
197 continue
198 }
199 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700200 switch indication.Data.(type) {
201 case *oop.Indication_OltInd:
202 oltInd := indication.GetOltInd()
203 if oltInd.OperState == "up" {
204 dh.transitionMap.Handle(DeviceUpInd)
205 } else if oltInd.OperState == "down" {
206 dh.transitionMap.Handle(DeviceDownInd)
207 }
208 case *oop.Indication_IntfInd:
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530209
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 intfInd := indication.GetIntfInd()
211 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
212 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
213 case *oop.Indication_IntfOperInd:
214 intfOperInd := indication.GetIntfOperInd()
215 if intfOperInd.GetType() == "nni" {
216 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
217 } else if intfOperInd.GetType() == "pon" {
218 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
219 // Handle pon port update
220 }
221 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
222 case *oop.Indication_OnuDiscInd:
223 onuDiscInd := indication.GetOnuDiscInd()
224 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400225 //onuId,err := dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
226 //onuId,err := dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
227 // TODO Get onu ID from the resource manager
cuilin20187b2a8c32019-03-26 19:52:28 -0700228 var onuId uint32 = 1
Girish Gowdru0c588b22019-04-23 23:24:56 -0400229 /*if err != nil{
230 log.Errorw("onu-id-unavailable",log.Fields{"intfId":onuDiscInd.GetIntfId()})
231 return
232 }*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530233
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400235 //FIXME: Duplicate child devices being create in go routine
236 dh.onuDiscIndication(onuDiscInd, onuId, sn)
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 case *oop.Indication_OnuInd:
238 onuInd := indication.GetOnuInd()
239 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
240 go dh.onuIndication(onuInd)
241 case *oop.Indication_OmciInd:
242 omciInd := indication.GetOmciInd()
243 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
244 if err := dh.omciIndication(omciInd); err != nil {
245 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
246 }
247 case *oop.Indication_PktInd:
248 pktInd := indication.GetPktInd()
249 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
250 case *oop.Indication_PortStats:
251 portStats := indication.GetPortStats()
252 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
253 case *oop.Indication_FlowStats:
254 flowStats := indication.GetFlowStats()
255 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
256 case *oop.Indication_AlarmInd:
257 alarmInd := indication.GetAlarmInd()
258 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
259 }
260 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530261}
262
263// doStateUp handle the olt up indication and update to voltha core
264func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400265 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400267 voltha.OperStatus_ACTIVE); err != nil {
268 log.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceId": dh.device.Id, "error": err})
269 return err
270 }
271 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530272}
273
274// doStateDown handle the olt down indication
275func (dh *DeviceHandler) doStateDown() error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700276 //TODO Handle oper state down
277 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530278}
279
280// doStateInit dial the grpc before going to init state
281func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400282 var err error
283 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure())
284 if err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700285 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceId, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400286 return err
287 }
288 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530289}
290
291// postInit create olt client instance to invoke RPC on the olt device
292func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400293 dh.Client = oop.NewOpenoltClient(dh.clientCon)
294 dh.transitionMap.Handle(GrpcConnected)
295 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530296}
297
298// doStateConnected get the device info and update to voltha core
299func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400300 log.Debug("OLT device has been connected")
301 deviceInfo, err := dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700302 if err != nil {
303 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
304 return err
305 }
306 if deviceInfo == nil {
307 log.Errorw("Device info is nil", log.Fields{})
308 return errors.New("Failed to get device info from OLT")
309 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530310
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 dh.device.Root = true
312 dh.device.Vendor = deviceInfo.Vendor
313 dh.device.Model = deviceInfo.Model
314 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
315 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
316 dh.device.HardwareVersion = deviceInfo.HardwareVersion
317 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
318 // TODO : Check whether this MAC address is learnt from SDPON or need to send from device
319 dh.device.MacAddress = "0a:0b:0c:0d:0e:0f"
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 // Synchronous call to update device - this method is run in its own go routine
322 if err := dh.coreProxy.DeviceUpdate(nil, dh.device); err != nil {
323 log.Errorw("error-updating-device", log.Fields{"deviceId": dh.device.Id, "error": err})
324 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400325 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
326 // Instantiate resource manager
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400327 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceId, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400328 log.Error("Error while instantiating resource manager")
329 return errors.New("Instantiating resource manager failed")
330 }
331 // Instantiate flow manager
332 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
333 log.Error("Error while instantiating flow manager")
334 return errors.New("Instantiating flow manager failed")
335 }
336 /* TODO: Instantiate Alarm , stats , BW managers */
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530337
cuilin20187b2a8c32019-03-26 19:52:28 -0700338 // Start reading indications
339 go dh.readIndications()
340 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530341}
342
343// AdoptDevice adopts the OLT device
344func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400345 dh.transitionMap = NewTransitionMap(dh)
cuilin20187b2a8c32019-03-26 19:52:28 -0700346 log.Infow("AdoptDevice", log.Fields{"deviceId": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400347 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530348}
349
350// GetOfpDeviceInfo Get the Ofp device information
351func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700352 return &ic.SwitchCapability{
353 Desc: &of.OfpDesc{
354 HwDesc: "open_pon",
355 SwDesc: "open_pon",
356 SerialNum: dh.device.SerialNumber,
357 },
358 SwitchFeatures: &of.OfpSwitchFeatures{
359 NBuffers: 256,
360 NTables: 2,
361 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
362 of.OfpCapabilities_OFPC_TABLE_STATS |
363 of.OfpCapabilities_OFPC_PORT_STATS |
364 of.OfpCapabilities_OFPC_GROUP_STATS),
365 },
366 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530367}
368
369// GetOfpPortInfo Get Ofp port information
370func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 cap := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
372 return &ic.PortCapability{
373 Port: &voltha.LogicalPort{
374 OfpPort: &of.OfpPort{
375 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
376 Config: 0,
377 State: uint32(of.OfpPortState_OFPPS_LIVE),
378 Curr: cap,
379 Advertised: cap,
380 Peer: cap,
381 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
382 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
383 },
384 DeviceId: dh.device.Id,
385 DevicePortNo: uint32(portNo),
386 },
387 }, nil
388}
389
390func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
391 log.Debugw("omci indication", log.Fields{"intfId": omciInd.IntfId, "onuId": omciInd.OnuId})
392
Girish Gowdru0c588b22019-04-23 23:24:56 -0400393 // ponPort := IntfIdToPortNo(omciInd.GetIntfId(),voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -0700394 kwargs := make(map[string]interface{})
395 kwargs["onu_id"] = omciInd.OnuId
396 kwargs["parent_port_no"] = omciInd.GetIntfId()
397
398 if onuDevice, err := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); err != nil {
399 log.Errorw("onu not found", log.Fields{"intfId": omciInd.IntfId, "onuId": omciInd.OnuId})
400 return err
401 } else {
402 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
manikkaraj kbf256be2019-03-25 00:13:48 +0530403 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
cuilin20187b2a8c32019-03-26 19:52:28 -0700404 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, onuDevice.Type,
405 onuDevice.Id, onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
406 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": onuDevice.Type, "onuId": onuDevice.Id, "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
407 return sendErr
408 }
409 return nil
410 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530411}
412
413// Process_inter_adapter_message process inter adater message
414func (dh *DeviceHandler) Process_inter_adapter_message(msg *ic.InterAdapterMessage) error {
cuilin20187b2a8c32019-03-26 19:52:28 -0700415 // TODO
416 log.Debugw("Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id})
417 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
418 msgId := msg.Header.Id
419 fromTopic := msg.Header.FromTopic
420 toTopic := msg.Header.ToTopic
421 toDeviceId := msg.Header.ToDeviceId
422 proxyDeviceId := msg.Header.ProxyDeviceId
423
424 log.Debugw("omci request message header", log.Fields{"msgId": msgId, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceId": toDeviceId, "proxyDeviceId": proxyDeviceId})
425
426 msgBody := msg.GetBody()
427
428 omciMsg := &ic.InterAdapterOmciMessage{}
429 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
430 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
431 return err
432 }
433
434 if onuDevice, err := dh.coreProxy.GetDevice(nil, dh.device.Id, toDeviceId); err != nil {
435 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceId, "error": err})
436 return err
437 } else {
438 dh.sendProxiedMessage(onuDevice, omciMsg)
439 }
440
441 } else {
442 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
443 }
444 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530445}
446
cuilin20187b2a8c32019-03-26 19:52:28 -0700447func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
448 if onuDevice.ConnectStatus != voltha.ConnectStatus_REACHABLE {
449 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"serialNumber": onuDevice.SerialNumber, "intfId": onuDevice.ProxyAddress.GetChannelId(), "onuId": onuDevice.ProxyAddress.GetOnuId()})
450 return
451 }
452
453 omciMessage := &oop.OmciMsg{IntfId: onuDevice.ProxyAddress.GetChannelId(), OnuId: onuDevice.ProxyAddress.GetOnuId(), Pkt: omciMsg.Message}
454
manikkaraj kbf256be2019-03-25 00:13:48 +0530455 dh.Client.OmciMsgOut(context.Background(), omciMessage)
cuilin20187b2a8c32019-03-26 19:52:28 -0700456 log.Debugw("omci-message-sent", log.Fields{"serialNumber": onuDevice.SerialNumber, "intfId": onuDevice.ProxyAddress.GetChannelId(), "omciMsg": string(omciMsg.Message)})
457}
458
459func (dh *DeviceHandler) activateONU(intfId uint32, onuId int64, serialNum *oop.SerialNumber, serialNumber string) {
460 log.Debugw("activate-onu", log.Fields{"intfId": intfId, "onuId": onuId, "serialNum": serialNum, "serialNumber": serialNumber})
461 // TODO: need resource manager
462 var pir uint32 = 1000000
463 Onu := oop.Onu{IntfId: intfId, OnuId: uint32(onuId), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530464 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700465 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu})
466 } else {
467 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
468 }
469}
470
471func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, onuId uint32, sn string) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400472 //channelId := MkUniPortNum(onuDiscInd.GetIntfId(), onuId, uint32(0))
473 //parentPortNo := IntfIdToPortNo(onuDiscInd.GetIntfId(),voltha.Port_PON_OLT)
474 channelId := onuDiscInd.GetIntfId()
475 parentPortNo := onuDiscInd.GetIntfId()
manikkaraj kbf256be2019-03-25 00:13:48 +0530476 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 -0700477 log.Errorw("Create onu error", log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(), "onuId": onuId, "sn": sn, "error": err})
478 return err
479 }
480
481 kwargs := make(map[string]interface{})
482 kwargs["onu_id"] = onuId
483 kwargs["parent_port_no"] = onuDiscInd.GetIntfId()
484
485 for i := 0; i < 10; i++ {
486 if onuDevice, _ := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); onuDevice != nil {
487 dh.activateONU(onuDiscInd.IntfId, int64(onuId), onuDiscInd.SerialNumber, sn)
488 return nil
489 } else {
490 time.Sleep(1 * time.Second)
491 log.Debugln("Sleep 1 seconds to active onu, retry times ", i+1)
492 }
493 }
494 log.Errorw("Cannot query onu, dont activate it.", log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(), "onuId": onuId, "sn": sn})
495 return errors.New("Failed to activate onu")
496}
497
498func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
499 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
500
501 kwargs := make(map[string]interface{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400502 // ponPort := IntfIdToPortNo(onuInd.GetIntfId(),voltha.Port_PON_OLT)
manikkaraj kbf256be2019-03-25 00:13:48 +0530503
cuilin20187b2a8c32019-03-26 19:52:28 -0700504 if serialNumber != "" {
505 kwargs["serial_number"] = serialNumber
506 } else {
507 kwargs["onu_id"] = onuInd.OnuId
508 kwargs["parent_port_no"] = onuInd.GetIntfId()
509 }
510 if onuDevice, _ := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs); onuDevice != nil {
511 //if intfIdFromPortNo(onuDevice.ParentPortNo) != onuInd.GetIntfId() {
512 if onuDevice.ParentPortNo != onuInd.GetIntfId() {
513 //log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": intfIdFromPortNo(onuDevice.ParentPortNo), "currentIntfId": onuInd.GetIntfId()})
514 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": onuInd.GetIntfId()})
515 }
516
517 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
518 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})
519 }
520
521 // adminState
522 if onuInd.AdminState == "down" {
523 if onuInd.OperState != "down" {
524 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
525 // Forcing the oper state change code to execute
526 onuInd.OperState = "down"
527 }
528 // Port and logical port update is taken care of by oper state block
529 } else if onuInd.AdminState == "up" {
530 log.Debugln("received-onu-admin-state up")
531 } else {
532 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
533 }
534 log.Debugln("admin-state-dealt-with")
535
536 // operState
537 if onuInd.OperState == "down" {
538 if onuDevice.ConnectStatus != common.ConnectStatus_UNREACHABLE {
539 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_UNREACHABLE, onuDevice.OperStatus)
540 log.Debugln("onu-oper-state-is-down")
541 }
542 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
543 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_UNREACHABLE, common.OperStatus_DISCOVERED)
544 }
545 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
546
547 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
manikkaraj kbf256be2019-03-25 00:13:48 +0530548 dh.AdapterProxy.SendInterAdapterMessage(nil, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST, "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
cuilin20187b2a8c32019-03-26 19:52:28 -0700549 } else if onuInd.OperState == "up" {
550 if onuDevice.ConnectStatus != common.ConnectStatus_REACHABLE {
551 dh.coreProxy.DeviceStateUpdate(nil, onuDevice.Id, common.ConnectStatus_REACHABLE, onuDevice.OperStatus)
552
553 }
554 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
555 log.Warnw("ignore onu indication", log.Fields{"intfId": onuInd.IntfId, "onuId": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
556 return
557 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530558 dh.AdapterProxy.SendInterAdapterMessage(nil, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST, "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
cuilin20187b2a8c32019-03-26 19:52:28 -0700559 } else {
560 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
561 }
562 } else {
563 log.Errorw("onu not found", log.Fields{"intfId": onuInd.IntfId, "onuId": onuInd.OnuId})
564 return
565 }
566
567}
568
569func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
570 if serialNum != nil {
571 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
572 } else {
573 return ""
574 }
575}
576
577func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
578 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
579 fmt.Sprintf("%x", (uint32(vendorSpecific[0]&0x0f))) +
580 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
581 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
582 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
583 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
584 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
585 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
586 return tmp
587}
588
589// flows
590func (dh *DeviceHandler) Update_flows_bulk() error {
591 return errors.New("UnImplemented")
592}
Girish Gowdru0c588b22019-04-23 23:24:56 -0400593func (dh *DeviceHandler) GetChildDevice(parentPort uint32, onuId uint32) *voltha.Device {
594 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuId": onuId})
595 kwargs := make(map[string]interface{})
596 kwargs["onu_id"] = onuId
597 kwargs["parent_port_no"] = parentPort
598 onuDevice, err := dh.coreProxy.GetChildDevice(nil, dh.device.Id, kwargs)
599 if err != nil {
600 log.Errorw("onu not found", log.Fields{"intfId": parentPort, "onuId": onuId})
601 return nil
602 }
603 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
604 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530605}
606
607func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400608 log.Debugw("In UpdateFlowsIncrementally", log.Fields{"deviceId": device.Id, "flows": flows, "groups": groups})
609 if flows != nil {
610 for _, flow := range flows.ToAdd.Items {
611 dh.flowMgr.AddFlow(flow)
612 }
613 }
614 if groups != nil {
615 for _, flow := range flows.ToRemove.Items {
616 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
617 // dh.flowMgr.RemoveFlow(flow)
618 }
619 }
620 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530621}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400622
623func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
624 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
625 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
626 return err
627 }
628 dh.lockDevice.Lock()
629 dh.adminState = "down"
630 dh.lockDevice.Unlock()
631 log.Debug("olt-disabled")
632
633 cloned := proto.Clone(device).(*voltha.Device)
634 // Update the all ports state on that device to disable
635 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
636 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
637 return err
638 }
639
640 //Update the device oper state
641 cloned.OperStatus = voltha.OperStatus_UNKNOWN
642 dh.device = cloned
643
644 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
645 log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
646 return err
647 }
648 log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
649 return nil
650}
651
652func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
653 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
654 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
655 return err
656 }
657
658 dh.lockDevice.Lock()
659 dh.adminState = "up"
660 dh.lockDevice.Unlock()
661 log.Debug("olt-reenabled")
662
663 cloned := proto.Clone(device).(*voltha.Device)
664 // Update the all ports state on that device to enable
665 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
666 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
667 return err
668 }
669
670 //Update the device oper status as ACTIVE
671 cloned.OperStatus = voltha.OperStatus_ACTIVE
672 dh.device = cloned
673
674 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
675 log.Errorw("error-updating-device-state", log.Fields{"deviceId": device.Id, "error": err})
676 return err
677 }
678 log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
679
680 return nil
681}