blob: e50c035041a5efbaa4ed2624729413531b407cd5 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
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 core
17
18import (
19 "context"
20 "errors"
21 "github.com/opencord/voltha-go/common/log"
22 "github.com/opencord/voltha-go/db/model"
23 "github.com/opencord/voltha-go/kafka"
khenaidoo79232702018-12-04 11:00:41 -050024 ic "github.com/opencord/voltha-go/protos/inter_container"
khenaidoo19d7b632018-10-30 10:49:50 -040025 ofp "github.com/opencord/voltha-go/protos/openflow_13"
khenaidoob9203542018-09-17 22:56:37 -040026 "github.com/opencord/voltha-go/protos/voltha"
27 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29 "reflect"
30 "runtime"
31 "sync"
32)
33
34type DeviceManager struct {
35 deviceAgents map[string]*DeviceAgent
36 adapterProxy *AdapterProxy
37 logicalDeviceMgr *LogicalDeviceManager
khenaidoo43c82122018-11-22 18:38:28 -050038 kafkaICProxy *kafka.InterContainerProxy
khenaidoob9203542018-09-17 22:56:37 -040039 stateTransitions *TransitionMap
khenaidoo9a468962018-09-19 15:33:13 -040040 clusterDataProxy *model.Proxy
khenaidood2b6df92018-12-13 16:37:20 -050041 coreInstanceId string
khenaidoob9203542018-09-17 22:56:37 -040042 exitChannel chan int
43 lockDeviceAgentsMap sync.RWMutex
44}
45
khenaidoo19374072018-12-11 11:05:15 -050046func newDeviceManager(kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy, coreInstanceId string) *DeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040047 var deviceMgr DeviceManager
48 deviceMgr.exitChannel = make(chan int, 1)
49 deviceMgr.deviceAgents = make(map[string]*DeviceAgent)
khenaidoo43c82122018-11-22 18:38:28 -050050 deviceMgr.adapterProxy = NewAdapterProxy(kafkaICProxy)
51 deviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo19374072018-12-11 11:05:15 -050052 deviceMgr.coreInstanceId = coreInstanceId
khenaidoo9a468962018-09-19 15:33:13 -040053 deviceMgr.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040054 deviceMgr.lockDeviceAgentsMap = sync.RWMutex{}
55 return &deviceMgr
56}
57
khenaidoo4d4802d2018-10-04 21:59:49 -040058func (dMgr *DeviceManager) start(ctx context.Context, logicalDeviceMgr *LogicalDeviceManager) {
khenaidoob9203542018-09-17 22:56:37 -040059 log.Info("starting-device-manager")
60 dMgr.logicalDeviceMgr = logicalDeviceMgr
61 dMgr.stateTransitions = NewTransitionMap(dMgr)
62 log.Info("device-manager-started")
63}
64
khenaidoo4d4802d2018-10-04 21:59:49 -040065func (dMgr *DeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040066 log.Info("stopping-device-manager")
67 dMgr.exitChannel <- 1
68 log.Info("device-manager-stopped")
69}
70
71func sendResponse(ctx context.Context, ch chan interface{}, result interface{}) {
72 if ctx.Err() == nil {
73 // Returned response only of the ctx has not been cancelled/timeout/etc
74 // Channel is automatically closed when a context is Done
75 ch <- result
76 log.Debugw("sendResponse", log.Fields{"result": result})
77 } else {
78 // Should the transaction be reverted back?
79 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
80 }
81}
82
83func (dMgr *DeviceManager) addDeviceAgentToMap(agent *DeviceAgent) {
84 dMgr.lockDeviceAgentsMap.Lock()
85 defer dMgr.lockDeviceAgentsMap.Unlock()
86 if _, exist := dMgr.deviceAgents[agent.deviceId]; !exist {
87 dMgr.deviceAgents[agent.deviceId] = agent
88 }
89}
90
khenaidoo4d4802d2018-10-04 21:59:49 -040091func (dMgr *DeviceManager) deleteDeviceAgentToMap(agent *DeviceAgent) {
92 dMgr.lockDeviceAgentsMap.Lock()
93 defer dMgr.lockDeviceAgentsMap.Unlock()
94 delete(dMgr.deviceAgents, agent.deviceId)
95}
96
khenaidoob9203542018-09-17 22:56:37 -040097func (dMgr *DeviceManager) getDeviceAgent(deviceId string) *DeviceAgent {
khenaidoo4d4802d2018-10-04 21:59:49 -040098 // TODO If the device is not in memory it needs to be loaded first
khenaidoob9203542018-09-17 22:56:37 -040099 dMgr.lockDeviceAgentsMap.Lock()
100 defer dMgr.lockDeviceAgentsMap.Unlock()
101 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
102 return agent
103 }
104 return nil
105}
106
107func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400108 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400109
110 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400111 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400112 dMgr.addDeviceAgentToMap(agent)
113 agent.start(ctx)
114
khenaidoo92e62c52018-10-03 14:02:54 -0400115 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400116}
117
118func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400119 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400120 var res interface{}
121 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
122 res = agent.enableDevice(ctx)
123 log.Debugw("EnableDevice-result", log.Fields{"result": res})
124 } else {
125 res = status.Errorf(codes.NotFound, "%s", id.Id)
126 }
127
128 sendResponse(ctx, ch, res)
129}
130
khenaidoo92e62c52018-10-03 14:02:54 -0400131func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
132 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400133 var res interface{}
134 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
135 res = agent.disableDevice(ctx)
136 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400137 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400138 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400139 }
khenaidoo92e62c52018-10-03 14:02:54 -0400140
141 sendResponse(ctx, ch, res)
142}
143
khenaidoo4d4802d2018-10-04 21:59:49 -0400144func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
145 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
146 var res interface{}
147 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
148 res = agent.rebootDevice(ctx)
149 log.Debugw("rebootDevice-result", log.Fields{"result": res})
150 } else {
151 res = status.Errorf(codes.NotFound, "%s", id.Id)
152 }
153 sendResponse(ctx, ch, res)
154}
155
156func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
157 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
158 var res interface{}
159 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
160 res = agent.deleteDevice(ctx)
161 if res == nil { //Success
162 agent.stop(ctx)
163 dMgr.deleteDeviceAgentToMap(agent)
164 }
165 log.Debugw("deleteDevice-result", log.Fields{"result": res})
166 } else {
167 res = status.Errorf(codes.NotFound, "%s", id.Id)
168 }
169 sendResponse(ctx, ch, res)
170}
171
khenaidoo19d7b632018-10-30 10:49:50 -0400172func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
173 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400174 if agent := dMgr.getDeviceAgent(id); agent != nil {
175 return agent.getDevice()
176 }
177 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400178}
179
khenaidoo19d7b632018-10-30 10:49:50 -0400180func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
181 device, err := dMgr.GetDevice(id)
182 if err != nil {
183 return false, err
184 }
185 return device.Root, nil
186}
187
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500188// GetDevice retrieves the latest device information from the data model
khenaidoob9203542018-09-17 22:56:37 -0400189func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400190 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400191 result := &voltha.Devices{}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500192 if devices := dMgr.clusterDataProxy.Get("/devices", 0, false, ""); devices != nil {
193 for _, device := range devices.([]interface{}) {
194 if agent := dMgr.getDeviceAgent(device.(*voltha.Device).Id); agent == nil {
195 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
196 dMgr.addDeviceAgentToMap(agent)
197 agent.start(nil)
198 }
199 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400200 }
201 }
202 return result, nil
203}
204
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500205//func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
206// log.Debug("ListDevices")
207// result := &voltha.Devices{}
208// dMgr.lockDeviceAgentsMap.Lock()
209// defer dMgr.lockDeviceAgentsMap.Unlock()
210// for _, agent := range dMgr.deviceAgents {
211// if device, err := agent.getDevice(); err == nil {
212// //cloned := proto.Clone(device).(*voltha.Device)
213// result.Items = append(result.Items, device)
214// }
215// }
216// return result, nil
217//}
218
khenaidoob9203542018-09-17 22:56:37 -0400219func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400220 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400221 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
222 return agent.updateDevice(device)
223 }
224 return status.Errorf(codes.NotFound, "%s", device.Id)
225}
226
227func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
228 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400229 if err := agent.addPort(port); err != nil {
230 return err
231 }
232 // Setup peer ports
233 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
234 for _, peerPort := range port.Peers {
235 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
236 if err := agent.addPeerPort(meAsPeer); err != nil {
237 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
238 return err
239 }
240 }
241 }
242 return nil
243 } else {
244 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400245 }
khenaidoob9203542018-09-17 22:56:37 -0400246}
247
khenaidoo19d7b632018-10-30 10:49:50 -0400248func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
249 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
250 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
251 return agent.updateFlows(flows)
252 }
253 return status.Errorf(codes.NotFound, "%s", deviceId)
254}
255
256func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
257 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
258 return agent.updateGroups(groups)
259 }
260 return status.Errorf(codes.NotFound, "%s", deviceId)
261}
262
khenaidoob9203542018-09-17 22:56:37 -0400263func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
264 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
265 return agent.updatePmConfigs(pmConfigs)
266 }
267 return status.Errorf(codes.NotFound, "%s", deviceId)
268}
269
khenaidoo79232702018-12-04 11:00:41 -0500270func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400271 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400272 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
273 return agent.getSwitchCapability(ctx)
274 }
275 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
276}
277
khenaidoo92e62c52018-10-03 14:02:54 -0400278func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
279 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400280 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400281 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400282 }
283 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400284
khenaidoob9203542018-09-17 22:56:37 -0400285}
286
khenaidoo79232702018-12-04 11:00:41 -0500287func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400288 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400289 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
290 return agent.getPortCapability(ctx, portNo)
291 }
292 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
293}
294
khenaidoo92e62c52018-10-03 14:02:54 -0400295func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
296 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400297 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400298 return agent.updateDeviceStatus(operStatus, connStatus)
299 }
300 return status.Errorf(codes.NotFound, "%s", deviceId)
301}
302
khenaidoo4d4802d2018-10-04 21:59:49 -0400303func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
304 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
305 var parentDevice *voltha.Device
306 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400307 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400308 return status.Errorf(codes.Aborted, "%s", err.Error())
309 }
310 var childDeviceIds []string
311 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
312 return status.Errorf(codes.Aborted, "%s", err.Error())
313 }
314 if len(childDeviceIds) == 0 {
315 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
316 }
317 for _, childDeviceId := range childDeviceIds {
318 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
319 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
320 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
321 }
322 }
323 }
324 return nil
325}
326
khenaidoo92e62c52018-10-03 14:02:54 -0400327func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
328 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
329 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
330 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400331 }
332 return status.Errorf(codes.NotFound, "%s", deviceId)
333}
334
335func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400336 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400337
338 // Create the ONU device
339 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400340 childDevice.Type = deviceType
341 childDevice.ParentId = parentDeviceId
342 childDevice.ParentPortNo = uint32(parentPortNo)
343 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400344
345 //Get parent device type
346 parent, err := dMgr.GetDevice(parentDeviceId)
347 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500348 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400349 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
350 }
351
352 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400353
354 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400355 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400356 dMgr.addDeviceAgentToMap(agent)
357 agent.start(nil)
358
359 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400360 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500361 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400362 }
363
khenaidoo79232702018-12-04 11:00:41 -0500364 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500365 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500366
khenaidoob9203542018-09-17 22:56:37 -0400367 return nil
368}
369
370func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
371 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400372 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
373 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500374 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400375 return nil
khenaidoob9203542018-09-17 22:56:37 -0400376 }
khenaidoo92e62c52018-10-03 14:02:54 -0400377 for _, handler := range handlers {
378 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
379 if err := handler(current); err != nil {
380 return err
381 }
382 }
khenaidoob9203542018-09-17 22:56:37 -0400383 return nil
384}
385
khenaidoofdbad6e2018-11-06 22:26:38 -0500386func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
387 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
388 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
389 return agent.packetOut(outPort, packet)
390 }
391 return status.Errorf(codes.NotFound, "%s", deviceId)
392}
393
394func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
395 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
396 // Get the logical device Id based on the deviceId
397 var device *voltha.Device
398 var err error
399 if device, err = dMgr.GetDevice(deviceId); err != nil {
400 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
401 return err
402 }
khenaidoo43c82122018-11-22 18:38:28 -0500403 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500404 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
405 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
406 }
407
408 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
409 return err
410 }
411 return nil
412}
413
khenaidoo92e62c52018-10-03 14:02:54 -0400414func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400415 log.Info("createLogicalDevice")
416 var logicalId *string
417 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400418 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400419 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
420 return err
421 }
422 // Update the parent device with the logical id
423 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
424 return nil
425}
426
khenaidoo92e62c52018-10-03 14:02:54 -0400427func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
428 log.Info("deleteLogicalDevice")
429 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400430 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400431 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
432 return err
433 }
434 // Remove the logical device Id from the parent device
435 logicalId := ""
436 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
437 return nil
438}
439
khenaidoo19d7b632018-10-30 10:49:50 -0400440func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400441 log.Info("deleteLogicalPort")
442 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400443 // Get the logical port associated with this device
444 var lPortId *voltha.LogicalPortId
445 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400446 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400447 return err
448 }
449 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
450 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400451 return err
452 }
khenaidoo92e62c52018-10-03 14:02:54 -0400453 return nil
454}
455
456func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
457 // Sanity check
458 if childDevice.Root {
459 // childDevice is the parent device
460 return childDevice
461 }
khenaidoo19d7b632018-10-30 10:49:50 -0400462 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400463 return parentDevice
464}
465
khenaidoo4d4802d2018-10-04 21:59:49 -0400466/*
467All the functions below are callback functions where they are invoked with the latest and previous data. We can
468therefore use the data as is without trying to get the latest from the model.
469*/
470
471//disableAllChildDevices is invoked as a callback when the parent device is disabled
472func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400473 log.Debug("disableAllChildDevices")
474 var childDeviceIds []string
475 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400476 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
477 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400478 }
479 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400480 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400481 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400482 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400483 for _, childDeviceId := range childDeviceIds {
484 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
485 if err = agent.disableDevice(nil); err != nil {
486 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400487 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400488 }
489 }
490 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400491 if !allChildDisable {
492 return err
493 }
khenaidoo92e62c52018-10-03 14:02:54 -0400494 return nil
495}
496
khenaidoo4d4802d2018-10-04 21:59:49 -0400497//deleteAllChildDevices is invoked as a callback when the parent device is deleted
498func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
499 log.Debug("deleteAllChildDevices")
500 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400501 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400502 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
503 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400504 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400505 if len(childDeviceIds) == 0 {
506 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
507 }
508 allChildDeleted := true
509 for _, childDeviceId := range childDeviceIds {
510 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
511 if err = agent.deleteDevice(nil); err != nil {
512 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
513 allChildDeleted = false
514 } else {
515 agent.stop(nil)
516 dMgr.deleteDeviceAgentToMap(agent)
517 }
518 }
519 }
520 if !allChildDeleted {
521 return err
522 }
523 return nil
524}
525
526//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
527func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
528 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400529 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400530 if parentDevice != nil {
531 for _, port := range parentDevice.Ports {
532 for _, peer := range port.Peers {
533 childDeviceIds = append(childDeviceIds, peer.DeviceId)
534 }
khenaidoo92e62c52018-10-03 14:02:54 -0400535 }
536 }
537 return childDeviceIds, nil
538}
539
540func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400541 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400542 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400543 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
544 return err
545 }
546 return nil
547}
548
khenaidoo92e62c52018-10-03 14:02:54 -0400549func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400550 log.Info("activateDevice")
551 return nil
552}
553
khenaidoo92e62c52018-10-03 14:02:54 -0400554func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
555 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400556 return nil
557}
558
khenaidoo92e62c52018-10-03 14:02:54 -0400559func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400560 log.Info("abandonDevice")
561 return nil
562}
563
khenaidoo92e62c52018-10-03 14:02:54 -0400564func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400565 log.Info("reEnableDevice")
566 return nil
567}
568
khenaidoo92e62c52018-10-03 14:02:54 -0400569func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400570 log.Info("noOp")
571 return nil
572}
573
khenaidoo92e62c52018-10-03 14:02:54 -0400574func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400575 log.Info("notAllowed")
576 return errors.New("Transition-not-allowed")
577}
578
579func funcName(f interface{}) string {
580 p := reflect.ValueOf(f).Pointer()
581 rf := runtime.FuncForPC(p)
582 return rf.Name()
583}
584
585func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
586 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
587 agent.updateDeviceAttribute(attribute, value)
588 }
589}
590
591func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400592 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400593 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400594 return &device.ParentId
595 }
596 return nil
597}