blob: 3f27e101b015943f5a7cd2c3178c61ab5fe42eee [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
khenaidoo7ccedd52018-12-14 16:48:54 -0500107func (dMgr *DeviceManager) listDeviceIdsFromMap() *voltha.IDs {
108 dMgr.lockDeviceAgentsMap.Lock()
109 defer dMgr.lockDeviceAgentsMap.Unlock()
110 result := &voltha.IDs{Items: make([]*voltha.ID, 0)}
111 for key, _ := range dMgr.deviceAgents {
112 result.Items = append(result.Items, &voltha.ID{Id: key})
113 }
114 return result
115}
116
khenaidoob9203542018-09-17 22:56:37 -0400117func (dMgr *DeviceManager) createDevice(ctx context.Context, device *voltha.Device, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400118 log.Debugw("createDevice", log.Fields{"device": device, "aproxy": dMgr.adapterProxy})
khenaidoob9203542018-09-17 22:56:37 -0400119
120 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400121 agent := newDeviceAgent(dMgr.adapterProxy, device, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400122 dMgr.addDeviceAgentToMap(agent)
123 agent.start(ctx)
124
khenaidoo92e62c52018-10-03 14:02:54 -0400125 sendResponse(ctx, ch, agent.lastData)
khenaidoob9203542018-09-17 22:56:37 -0400126}
127
128func (dMgr *DeviceManager) enableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
khenaidoo92e62c52018-10-03 14:02:54 -0400129 log.Debugw("enableDevice", log.Fields{"deviceid": id})
khenaidoob9203542018-09-17 22:56:37 -0400130 var res interface{}
131 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
132 res = agent.enableDevice(ctx)
133 log.Debugw("EnableDevice-result", log.Fields{"result": res})
134 } else {
135 res = status.Errorf(codes.NotFound, "%s", id.Id)
136 }
137
138 sendResponse(ctx, ch, res)
139}
140
khenaidoo92e62c52018-10-03 14:02:54 -0400141func (dMgr *DeviceManager) disableDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
142 log.Debugw("disableDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400143 var res interface{}
144 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
145 res = agent.disableDevice(ctx)
146 log.Debugw("disableDevice-result", log.Fields{"result": res})
khenaidoob9203542018-09-17 22:56:37 -0400147 } else {
khenaidoo92e62c52018-10-03 14:02:54 -0400148 res = status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400149 }
khenaidoo92e62c52018-10-03 14:02:54 -0400150
151 sendResponse(ctx, ch, res)
152}
153
khenaidoo4d4802d2018-10-04 21:59:49 -0400154func (dMgr *DeviceManager) rebootDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
155 log.Debugw("rebootDevice", log.Fields{"deviceid": id})
156 var res interface{}
157 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
158 res = agent.rebootDevice(ctx)
159 log.Debugw("rebootDevice-result", log.Fields{"result": res})
160 } else {
161 res = status.Errorf(codes.NotFound, "%s", id.Id)
162 }
163 sendResponse(ctx, ch, res)
164}
165
166func (dMgr *DeviceManager) deleteDevice(ctx context.Context, id *voltha.ID, ch chan interface{}) {
167 log.Debugw("deleteDevice", log.Fields{"deviceid": id})
168 var res interface{}
169 if agent := dMgr.getDeviceAgent(id.Id); agent != nil {
170 res = agent.deleteDevice(ctx)
171 if res == nil { //Success
172 agent.stop(ctx)
173 dMgr.deleteDeviceAgentToMap(agent)
174 }
175 log.Debugw("deleteDevice-result", log.Fields{"result": res})
176 } else {
177 res = status.Errorf(codes.NotFound, "%s", id.Id)
178 }
179 sendResponse(ctx, ch, res)
180}
181
khenaidoo19d7b632018-10-30 10:49:50 -0400182func (dMgr *DeviceManager) GetDevice(id string) (*voltha.Device, error) {
183 log.Debugw("GetDevice", log.Fields{"deviceid": id})
khenaidoo92e62c52018-10-03 14:02:54 -0400184 if agent := dMgr.getDeviceAgent(id); agent != nil {
185 return agent.getDevice()
186 }
187 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoob9203542018-09-17 22:56:37 -0400188}
189
khenaidoo19d7b632018-10-30 10:49:50 -0400190func (dMgr *DeviceManager) IsRootDevice(id string) (bool, error) {
191 device, err := dMgr.GetDevice(id)
192 if err != nil {
193 return false, err
194 }
195 return device.Root, nil
196}
197
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500198// GetDevice retrieves the latest device information from the data model
khenaidoob9203542018-09-17 22:56:37 -0400199func (dMgr *DeviceManager) ListDevices() (*voltha.Devices, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400200 log.Debug("ListDevices")
khenaidoob9203542018-09-17 22:56:37 -0400201 result := &voltha.Devices{}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500202 if devices := dMgr.clusterDataProxy.Get("/devices", 0, false, ""); devices != nil {
203 for _, device := range devices.([]interface{}) {
204 if agent := dMgr.getDeviceAgent(device.(*voltha.Device).Id); agent == nil {
205 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
206 dMgr.addDeviceAgentToMap(agent)
207 agent.start(nil)
208 }
209 result.Items = append(result.Items, device.(*voltha.Device))
khenaidoob9203542018-09-17 22:56:37 -0400210 }
211 }
212 return result, nil
213}
214
khenaidoo7ccedd52018-12-14 16:48:54 -0500215// ListDeviceIds retrieves the latest device IDs information from the data model (memory data only)
216func (dMgr *DeviceManager) ListDeviceIds() (*voltha.IDs, error) {
217 log.Debug("ListDeviceIDs")
218 // Report only device IDs that are in the device agent map
219 return dMgr.listDeviceIdsFromMap(), nil
220}
221
222//ReconcileDevices is a request to a voltha core to managed a list of devices based on their IDs
223func (dMgr *DeviceManager) ReconcileDevices(ctx context.Context, ids *voltha.IDs, ch chan interface{}) {
224 log.Debug("ReconcileDevices")
225 var res interface{}
226 if ids != nil {
227 toReconcile := len(ids.Items)
228 reconciled := 0
229 for _, id := range ids.Items {
230 // Act on the device only if its not present in the agent map
231 if agent := dMgr.getDeviceAgent(id.Id); agent == nil {
232 // Device Id not in memory
233 log.Debugw("reconciling-device", log.Fields{"id": id.Id})
234 // Load device from model
235 if device := dMgr.clusterDataProxy.Get("/devices/"+id.Id, 0, false, ""); device != nil {
236 agent = newDeviceAgent(dMgr.adapterProxy, device.(*voltha.Device), dMgr, dMgr.clusterDataProxy)
237 dMgr.addDeviceAgentToMap(agent)
238 agent.start(nil)
239 reconciled += 1
240 } else {
241 log.Warnw("device-inexistent", log.Fields{"id": id.Id})
242 }
243 } else {
244 reconciled += 1
245 }
246 }
247 if toReconcile != reconciled {
248 res = status.Errorf(codes.DataLoss, "less-device-reconciled:%d/%d", reconciled, toReconcile)
249 }
250 } else {
251 res = status.Errorf(codes.InvalidArgument, "empty-list-of-ids")
252 }
253 sendResponse(ctx, ch, res)
254}
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500255
khenaidoob9203542018-09-17 22:56:37 -0400256func (dMgr *DeviceManager) updateDevice(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400257 log.Debugw("updateDevice", log.Fields{"deviceid": device.Id, "device": device})
khenaidoob9203542018-09-17 22:56:37 -0400258 if agent := dMgr.getDeviceAgent(device.Id); agent != nil {
259 return agent.updateDevice(device)
260 }
261 return status.Errorf(codes.NotFound, "%s", device.Id)
262}
263
264func (dMgr *DeviceManager) addPort(deviceId string, port *voltha.Port) error {
265 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400266 if err := agent.addPort(port); err != nil {
267 return err
268 }
269 // Setup peer ports
270 meAsPeer := &voltha.Port_PeerPort{DeviceId: deviceId, PortNo: port.PortNo}
271 for _, peerPort := range port.Peers {
272 if agent := dMgr.getDeviceAgent(peerPort.DeviceId); agent != nil {
273 if err := agent.addPeerPort(meAsPeer); err != nil {
274 log.Errorw("failed-to-add-peer", log.Fields{"peer-device-id": peerPort.DeviceId})
275 return err
276 }
277 }
278 }
279 return nil
280 } else {
281 return status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoob9203542018-09-17 22:56:37 -0400282 }
khenaidoob9203542018-09-17 22:56:37 -0400283}
284
khenaidoo19d7b632018-10-30 10:49:50 -0400285func (dMgr *DeviceManager) updateFlows(deviceId string, flows []*ofp.OfpFlowStats) error {
286 log.Debugw("updateFlows", log.Fields{"deviceid": deviceId})
287 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
288 return agent.updateFlows(flows)
289 }
290 return status.Errorf(codes.NotFound, "%s", deviceId)
291}
292
293func (dMgr *DeviceManager) updateGroups(deviceId string, groups []*ofp.OfpGroupEntry) error {
294 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
295 return agent.updateGroups(groups)
296 }
297 return status.Errorf(codes.NotFound, "%s", deviceId)
298}
299
khenaidoob9203542018-09-17 22:56:37 -0400300func (dMgr *DeviceManager) updatePmConfigs(deviceId string, pmConfigs *voltha.PmConfigs) error {
301 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
302 return agent.updatePmConfigs(pmConfigs)
303 }
304 return status.Errorf(codes.NotFound, "%s", deviceId)
305}
306
khenaidoo79232702018-12-04 11:00:41 -0500307func (dMgr *DeviceManager) getSwitchCapability(ctx context.Context, deviceId string) (*ic.SwitchCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400308 log.Debugw("getSwitchCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400309 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
310 return agent.getSwitchCapability(ctx)
311 }
312 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
313}
314
khenaidoo92e62c52018-10-03 14:02:54 -0400315func (dMgr *DeviceManager) getPorts(ctx context.Context, deviceId string, portType voltha.Port_PortType) (*voltha.Ports, error) {
316 log.Debugw("getPorts", log.Fields{"deviceid": deviceId, "portType": portType})
khenaidoob9203542018-09-17 22:56:37 -0400317 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400318 return agent.getPorts(ctx, portType), nil
khenaidoob9203542018-09-17 22:56:37 -0400319 }
320 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
khenaidoo92e62c52018-10-03 14:02:54 -0400321
khenaidoob9203542018-09-17 22:56:37 -0400322}
323
khenaidoo79232702018-12-04 11:00:41 -0500324func (dMgr *DeviceManager) getPortCapability(ctx context.Context, deviceId string, portNo uint32) (*ic.PortCapability, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400325 log.Debugw("getPortCapability", log.Fields{"deviceid": deviceId})
khenaidoob9203542018-09-17 22:56:37 -0400326 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
327 return agent.getPortCapability(ctx, portNo)
328 }
329 return nil, status.Errorf(codes.NotFound, "%s", deviceId)
330}
331
khenaidoo92e62c52018-10-03 14:02:54 -0400332func (dMgr *DeviceManager) updateDeviceStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
333 log.Debugw("updateDeviceStatus", log.Fields{"deviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
khenaidoob9203542018-09-17 22:56:37 -0400334 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400335 return agent.updateDeviceStatus(operStatus, connStatus)
336 }
337 return status.Errorf(codes.NotFound, "%s", deviceId)
338}
339
khenaidoo4d4802d2018-10-04 21:59:49 -0400340func (dMgr *DeviceManager) updateChildrenStatus(deviceId string, operStatus voltha.OperStatus_OperStatus, connStatus voltha.ConnectStatus_ConnectStatus) error {
341 log.Debugw("updateChildrenStatus", log.Fields{"parentDeviceid": deviceId, "operStatus": operStatus, "connStatus": connStatus})
342 var parentDevice *voltha.Device
343 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400344 if parentDevice, err = dMgr.GetDevice(deviceId); err != nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400345 return status.Errorf(codes.Aborted, "%s", err.Error())
346 }
347 var childDeviceIds []string
348 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
349 return status.Errorf(codes.Aborted, "%s", err.Error())
350 }
351 if len(childDeviceIds) == 0 {
352 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
353 }
354 for _, childDeviceId := range childDeviceIds {
355 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
356 if err = agent.updateDeviceStatus(operStatus, connStatus); err != nil {
357 return status.Errorf(codes.Aborted, "childDevice:%s, error:%s", childDeviceId, err.Error())
358 }
359 }
360 }
361 return nil
362}
363
khenaidoo92e62c52018-10-03 14:02:54 -0400364func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
365 log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
366 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
367 return agent.updatePortState(portType, portNo, operStatus)
khenaidoob9203542018-09-17 22:56:37 -0400368 }
369 return status.Errorf(codes.NotFound, "%s", deviceId)
370}
371
372func (dMgr *DeviceManager) childDeviceDetected(parentDeviceId string, parentPortNo int64, deviceType string, channelId int64) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400373 log.Debugw("childDeviceDetected", log.Fields{"parentDeviceId": parentDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400374
375 // Create the ONU device
376 childDevice := &voltha.Device{}
khenaidoob9203542018-09-17 22:56:37 -0400377 childDevice.Type = deviceType
378 childDevice.ParentId = parentDeviceId
379 childDevice.ParentPortNo = uint32(parentPortNo)
380 childDevice.Root = false
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400381
382 //Get parent device type
383 parent, err := dMgr.GetDevice(parentDeviceId)
384 if err != nil {
khenaidoo43c82122018-11-22 18:38:28 -0500385 log.Error("no-parent-found", log.Fields{"parentId": parentDeviceId})
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400386 return status.Errorf(codes.NotFound, "%s", parentDeviceId)
387 }
388
389 childDevice.ProxyAddress = &voltha.Device_ProxyAddress{DeviceId: parentDeviceId, DeviceType: parent.Type, ChannelId: uint32(channelId)}
khenaidoob9203542018-09-17 22:56:37 -0400390
391 // Create and start a device agent for that device
khenaidoo9a468962018-09-19 15:33:13 -0400392 agent := newDeviceAgent(dMgr.adapterProxy, childDevice, dMgr, dMgr.clusterDataProxy)
khenaidoob9203542018-09-17 22:56:37 -0400393 dMgr.addDeviceAgentToMap(agent)
394 agent.start(nil)
395
396 // Activate the child device
khenaidoo92e62c52018-10-03 14:02:54 -0400397 if agent := dMgr.getDeviceAgent(agent.deviceId); agent != nil {
khenaidoo79232702018-12-04 11:00:41 -0500398 go agent.enableDevice(nil)
khenaidoob9203542018-09-17 22:56:37 -0400399 }
400
khenaidoo79232702018-12-04 11:00:41 -0500401 // Publish on the messaging bus that we have discovered new devices
khenaidoo19374072018-12-11 11:05:15 -0500402 go dMgr.kafkaICProxy.DeviceDiscovered(agent.deviceId, deviceType, parentDeviceId, dMgr.coreInstanceId)
khenaidoo79232702018-12-04 11:00:41 -0500403
khenaidoob9203542018-09-17 22:56:37 -0400404 return nil
405}
406
407func (dMgr *DeviceManager) processTransition(previous *voltha.Device, current *voltha.Device) error {
408 // This will be triggered on every update to the device.
khenaidoo92e62c52018-10-03 14:02:54 -0400409 handlers := dMgr.stateTransitions.GetTransitionHandler(previous, current)
410 if handlers == nil {
khenaidoo43c82122018-11-22 18:38:28 -0500411 log.Debugw("no-op-transition", log.Fields{"deviceId": current.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400412 return nil
khenaidoob9203542018-09-17 22:56:37 -0400413 }
khenaidoo92e62c52018-10-03 14:02:54 -0400414 for _, handler := range handlers {
415 log.Debugw("running-handler", log.Fields{"handler": funcName(handler)})
416 if err := handler(current); err != nil {
417 return err
418 }
419 }
khenaidoob9203542018-09-17 22:56:37 -0400420 return nil
421}
422
khenaidoofdbad6e2018-11-06 22:26:38 -0500423func (dMgr *DeviceManager) packetOut(deviceId string, outPort uint32, packet *ofp.OfpPacketOut) error {
424 log.Debugw("packetOut", log.Fields{"deviceId": deviceId, "outPort": outPort})
425 if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
426 return agent.packetOut(outPort, packet)
427 }
428 return status.Errorf(codes.NotFound, "%s", deviceId)
429}
430
431func (dMgr *DeviceManager) PacketIn(deviceId string, port uint32, packet []byte) error {
432 log.Debugw("PacketIn", log.Fields{"deviceId": deviceId, "port": port})
433 // Get the logical device Id based on the deviceId
434 var device *voltha.Device
435 var err error
436 if device, err = dMgr.GetDevice(deviceId); err != nil {
437 log.Errorw("device-not-found", log.Fields{"deviceId": deviceId})
438 return err
439 }
khenaidoo43c82122018-11-22 18:38:28 -0500440 if !device.Root {
khenaidoofdbad6e2018-11-06 22:26:38 -0500441 log.Errorw("device-not-root", log.Fields{"deviceId": deviceId})
442 return status.Errorf(codes.FailedPrecondition, "%s", deviceId)
443 }
444
445 if err := dMgr.logicalDeviceMgr.packetIn(device.ParentId, port, packet); err != nil {
446 return err
447 }
448 return nil
449}
450
khenaidoo92e62c52018-10-03 14:02:54 -0400451func (dMgr *DeviceManager) createLogicalDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400452 log.Info("createLogicalDevice")
453 var logicalId *string
454 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400455 if logicalId, err = dMgr.logicalDeviceMgr.createLogicalDevice(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400456 log.Warnw("createlogical-device-error", log.Fields{"device": cDevice})
457 return err
458 }
459 // Update the parent device with the logical id
460 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", *logicalId)
461 return nil
462}
463
khenaidoo92e62c52018-10-03 14:02:54 -0400464func (dMgr *DeviceManager) deleteLogicalDevice(cDevice *voltha.Device) error {
465 log.Info("deleteLogicalDevice")
466 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400467 if err = dMgr.logicalDeviceMgr.deleteLogicalDevice(nil, cDevice); err != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400468 log.Warnw("deleteLogical-device-error", log.Fields{"deviceId": cDevice.Id})
469 return err
470 }
471 // Remove the logical device Id from the parent device
472 logicalId := ""
473 dMgr.UpdateDeviceAttribute(cDevice.Id, "ParentId", logicalId)
474 return nil
475}
476
khenaidoo19d7b632018-10-30 10:49:50 -0400477func (dMgr *DeviceManager) deleteLogicalPort(device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400478 log.Info("deleteLogicalPort")
479 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400480 // Get the logical port associated with this device
481 var lPortId *voltha.LogicalPortId
482 if lPortId, err = dMgr.logicalDeviceMgr.getLogicalPortId(device); err != nil {
khenaidoo6fdf0ba2018-11-02 14:38:33 -0400483 log.Warnw("getLogical-port-error", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo19d7b632018-10-30 10:49:50 -0400484 return err
485 }
486 if err = dMgr.logicalDeviceMgr.deleteLogicalPort(nil, lPortId); err != nil {
487 log.Warnw("deleteLogical-port-error", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400488 return err
489 }
khenaidoo92e62c52018-10-03 14:02:54 -0400490 return nil
491}
492
493func (dMgr *DeviceManager) getParentDevice(childDevice *voltha.Device) *voltha.Device {
494 // Sanity check
495 if childDevice.Root {
496 // childDevice is the parent device
497 return childDevice
498 }
khenaidoo19d7b632018-10-30 10:49:50 -0400499 parentDevice, _ := dMgr.GetDevice(childDevice.ParentId)
khenaidoo92e62c52018-10-03 14:02:54 -0400500 return parentDevice
501}
502
khenaidoo4d4802d2018-10-04 21:59:49 -0400503/*
504All the functions below are callback functions where they are invoked with the latest and previous data. We can
505therefore use the data as is without trying to get the latest from the model.
506*/
507
508//disableAllChildDevices is invoked as a callback when the parent device is disabled
509func (dMgr *DeviceManager) disableAllChildDevices(parentDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400510 log.Debug("disableAllChildDevices")
511 var childDeviceIds []string
512 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400513 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
514 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400515 }
516 if len(childDeviceIds) == 0 {
khenaidoo4d4802d2018-10-04 21:59:49 -0400517 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400518 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400519 allChildDisable := true
khenaidoo92e62c52018-10-03 14:02:54 -0400520 for _, childDeviceId := range childDeviceIds {
521 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
522 if err = agent.disableDevice(nil); err != nil {
523 log.Errorw("failure-disable-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
khenaidoo4d4802d2018-10-04 21:59:49 -0400524 allChildDisable = false
khenaidoo92e62c52018-10-03 14:02:54 -0400525 }
526 }
527 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400528 if !allChildDisable {
529 return err
530 }
khenaidoo92e62c52018-10-03 14:02:54 -0400531 return nil
532}
533
khenaidoo4d4802d2018-10-04 21:59:49 -0400534//deleteAllChildDevices is invoked as a callback when the parent device is deleted
535func (dMgr *DeviceManager) deleteAllChildDevices(parentDevice *voltha.Device) error {
536 log.Debug("deleteAllChildDevices")
537 var childDeviceIds []string
khenaidoo92e62c52018-10-03 14:02:54 -0400538 var err error
khenaidoo4d4802d2018-10-04 21:59:49 -0400539 if childDeviceIds, err = dMgr.getAllChildDeviceIds(parentDevice); err != nil {
540 return status.Errorf(codes.NotFound, "%s", parentDevice.Id)
khenaidoo92e62c52018-10-03 14:02:54 -0400541 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400542 if len(childDeviceIds) == 0 {
543 log.Debugw("no-child-device", log.Fields{"parentDeviceId": parentDevice.Id})
544 }
545 allChildDeleted := true
546 for _, childDeviceId := range childDeviceIds {
547 if agent := dMgr.getDeviceAgent(childDeviceId); agent != nil {
548 if err = agent.deleteDevice(nil); err != nil {
549 log.Errorw("failure-delete-device", log.Fields{"deviceId": childDeviceId, "error": err.Error()})
550 allChildDeleted = false
551 } else {
552 agent.stop(nil)
553 dMgr.deleteDeviceAgentToMap(agent)
554 }
555 }
556 }
557 if !allChildDeleted {
558 return err
559 }
560 return nil
561}
562
563//getAllChildDeviceIds is a helper method to get all the child device IDs from the device passed as parameter
564func (dMgr *DeviceManager) getAllChildDeviceIds(parentDevice *voltha.Device) ([]string, error) {
565 log.Debugw("getAllChildDeviceIds", log.Fields{"parentDeviceId": parentDevice.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400566 childDeviceIds := make([]string, 0)
khenaidoo4d4802d2018-10-04 21:59:49 -0400567 if parentDevice != nil {
568 for _, port := range parentDevice.Ports {
569 for _, peer := range port.Peers {
570 childDeviceIds = append(childDeviceIds, peer.DeviceId)
571 }
khenaidoo92e62c52018-10-03 14:02:54 -0400572 }
573 }
574 return childDeviceIds, nil
575}
576
577func (dMgr *DeviceManager) addUNILogicalPort(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400578 log.Info("addUNILogicalPort")
khenaidoo4d4802d2018-10-04 21:59:49 -0400579 if err := dMgr.logicalDeviceMgr.addUNILogicalPort(nil, cDevice); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400580 log.Warnw("addUNILogicalPort-error", log.Fields{"device": cDevice, "err": err})
581 return err
582 }
583 return nil
584}
585
khenaidoo92e62c52018-10-03 14:02:54 -0400586func (dMgr *DeviceManager) activateDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400587 log.Info("activateDevice")
588 return nil
589}
590
khenaidoo92e62c52018-10-03 14:02:54 -0400591func (dMgr *DeviceManager) disableDeviceHandler(cDevice *voltha.Device) error {
592 log.Info("disableDevice-donothing")
khenaidoob9203542018-09-17 22:56:37 -0400593 return nil
594}
595
khenaidoo92e62c52018-10-03 14:02:54 -0400596func (dMgr *DeviceManager) abandonDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400597 log.Info("abandonDevice")
598 return nil
599}
600
khenaidoo92e62c52018-10-03 14:02:54 -0400601func (dMgr *DeviceManager) reEnableDevice(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400602 log.Info("reEnableDevice")
603 return nil
604}
605
khenaidoo92e62c52018-10-03 14:02:54 -0400606func (dMgr *DeviceManager) noOp(cDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400607 log.Info("noOp")
608 return nil
609}
610
khenaidoo92e62c52018-10-03 14:02:54 -0400611func (dMgr *DeviceManager) notAllowed(pcDevice *voltha.Device) error {
khenaidoob9203542018-09-17 22:56:37 -0400612 log.Info("notAllowed")
613 return errors.New("Transition-not-allowed")
614}
615
616func funcName(f interface{}) string {
617 p := reflect.ValueOf(f).Pointer()
618 rf := runtime.FuncForPC(p)
619 return rf.Name()
620}
621
622func (dMgr *DeviceManager) UpdateDeviceAttribute(deviceId string, attribute string, value interface{}) {
623 if agent, ok := dMgr.deviceAgents[deviceId]; ok {
624 agent.updateDeviceAttribute(attribute, value)
625 }
626}
627
628func (dMgr *DeviceManager) GetParentDeviceId(deviceId string) *string {
khenaidoo19d7b632018-10-30 10:49:50 -0400629 if device, _ := dMgr.GetDevice(deviceId); device != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400630 log.Infow("GetParentDeviceId", log.Fields{"deviceId": device.Id, "parentId": device.ParentId})
khenaidoob9203542018-09-17 22:56:37 -0400631 return &device.ParentId
632 }
633 return nil
634}