blob: 6f8b2faad01851a509eeae8daa9d3dc20f141451 [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 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
21 "errors"
npujar1d86a522019-11-14 17:11:16 +053022 "strings"
23 "sync"
24
sbarbari17d7e222019-11-05 10:02:29 -050025 "github.com/opencord/voltha-go/db/model"
Scott Baker807addd2019-10-24 15:16:21 -070026 "github.com/opencord/voltha-lib-go/v2/pkg/kafka"
27 "github.com/opencord/voltha-lib-go/v2/pkg/log"
28 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080029 "github.com/opencord/voltha-protos/v2/go/openflow_13"
30 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040031 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040033)
34
npujar1d86a522019-11-14 17:11:16 +053035// LogicalDeviceManager represent logical device manager attributes
khenaidoob9203542018-09-17 22:56:37 -040036type LogicalDeviceManager struct {
khenaidoo4c9e5592019-09-09 16:20:41 -040037 logicalDeviceAgents sync.Map
38 core *Core
39 deviceMgr *DeviceManager
40 grpcNbiHdlr *APIHandler
khenaidoo4c9e5592019-09-09 16:20:41 -040041 kafkaICProxy *kafka.InterContainerProxy
42 clusterDataProxy *model.Proxy
43 exitChannel chan int
44 defaultTimeout int64
45 logicalDevicesLoadingLock sync.RWMutex
46 logicalDeviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040047}
48
khenaidoo2c6a0992019-04-29 13:46:56 -040049func newLogicalDeviceManager(core *Core, deviceMgr *DeviceManager, kafkaICProxy *kafka.InterContainerProxy, cdProxy *model.Proxy, timeout int64) *LogicalDeviceManager {
khenaidoob9203542018-09-17 22:56:37 -040050 var logicalDeviceMgr LogicalDeviceManager
Richard Jankowski199fd862019-03-18 14:49:51 -040051 logicalDeviceMgr.core = core
khenaidoob9203542018-09-17 22:56:37 -040052 logicalDeviceMgr.exitChannel = make(chan int, 1)
khenaidoob9203542018-09-17 22:56:37 -040053 logicalDeviceMgr.deviceMgr = deviceMgr
khenaidoo43c82122018-11-22 18:38:28 -050054 logicalDeviceMgr.kafkaICProxy = kafkaICProxy
khenaidoo9a468962018-09-19 15:33:13 -040055 logicalDeviceMgr.clusterDataProxy = cdProxy
khenaidoo2c6a0992019-04-29 13:46:56 -040056 logicalDeviceMgr.defaultTimeout = timeout
khenaidoo4c9e5592019-09-09 16:20:41 -040057 logicalDeviceMgr.logicalDevicesLoadingLock = sync.RWMutex{}
58 logicalDeviceMgr.logicalDeviceLoadingInProgress = make(map[string][]chan int)
khenaidoob9203542018-09-17 22:56:37 -040059 return &logicalDeviceMgr
60}
61
Richard Jankowskidbab94a2018-12-06 16:20:25 -050062func (ldMgr *LogicalDeviceManager) setGrpcNbiHandler(grpcNbiHandler *APIHandler) {
63 ldMgr.grpcNbiHdlr = grpcNbiHandler
64}
65
khenaidoo4d4802d2018-10-04 21:59:49 -040066func (ldMgr *LogicalDeviceManager) start(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040067 log.Info("starting-logical-device-manager")
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070068 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusRunning)
khenaidoob9203542018-09-17 22:56:37 -040069 log.Info("logical-device-manager-started")
70}
71
khenaidoo4d4802d2018-10-04 21:59:49 -040072func (ldMgr *LogicalDeviceManager) stop(ctx context.Context) {
khenaidoob9203542018-09-17 22:56:37 -040073 log.Info("stopping-logical-device-manager")
74 ldMgr.exitChannel <- 1
David K. Bainbridgeb4a9ab02019-09-20 15:12:16 -070075 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusStopped)
khenaidoob9203542018-09-17 22:56:37 -040076 log.Info("logical-device-manager-stopped")
77}
78
khenaidoo19d7b632018-10-30 10:49:50 -040079func sendAPIResponse(ctx context.Context, ch chan interface{}, result interface{}) {
80 if ctx.Err() == nil {
81 // Returned response only of the ctx has not been cancelled/timeout/etc
82 // Channel is automatically closed when a context is Done
83 ch <- result
84 log.Debugw("sendResponse", log.Fields{"result": result})
85 } else {
86 // Should the transaction be reverted back?
87 log.Debugw("sendResponse-context-error", log.Fields{"context-error": ctx.Err()})
88 }
89}
90
khenaidoob9203542018-09-17 22:56:37 -040091func (ldMgr *LogicalDeviceManager) addLogicalDeviceAgentToMap(agent *LogicalDeviceAgent) {
npujar1d86a522019-11-14 17:11:16 +053092 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceID); !exist {
93 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040094 }
95}
96
khenaidoo8c3303d2019-02-13 14:59:39 -050097// getLogicalDeviceAgent returns the logical device agent. If the device is not in memory then the device will
98// be loaded from dB and a logical device agent created to managed it.
npujar1d86a522019-11-14 17:11:16 +053099func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceID string) *LogicalDeviceAgent {
100 agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceID)
101 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400102 return agent.(*LogicalDeviceAgent)
npujar1d86a522019-11-14 17:11:16 +0530103 }
104 // Try to load into memory - loading will also create the logical device agent
105 if err := ldMgr.load(logicalDeviceID); err == nil {
106 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceID); ok {
107 return agent.(*LogicalDeviceAgent)
khenaidoo8c3303d2019-02-13 14:59:39 -0500108 }
khenaidoob9203542018-09-17 22:56:37 -0400109 }
110 return nil
111}
112
npujar1d86a522019-11-14 17:11:16 +0530113func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceID string) {
114 ldMgr.logicalDeviceAgents.Delete(logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400115}
116
khenaidoo8c3303d2019-02-13 14:59:39 -0500117// GetLogicalDevice provides a cloned most up to date logical device. If device is not in memory
118// it will be fetched from the dB
khenaidoob9203542018-09-17 22:56:37 -0400119func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400120 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
121 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500122 return agent.GetLogicalDevice(), nil
khenaidoob9203542018-09-17 22:56:37 -0400123 }
124 return nil, status.Errorf(codes.NotFound, "%s", id)
125}
126
khenaidoo43aa6bd2019-05-29 13:35:13 -0400127func (ldMgr *LogicalDeviceManager) listManagedLogicalDevices() (*voltha.LogicalDevices, error) {
128 log.Debug("listManagedLogicalDevices")
129 result := &voltha.LogicalDevices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400130 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
131 agent := value.(*LogicalDeviceAgent)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500132 if ld := agent.GetLogicalDevice(); ld != nil {
khenaidoo43aa6bd2019-05-29 13:35:13 -0400133 result.Items = append(result.Items, ld)
134 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400135 return true
136 })
137
khenaidoo43aa6bd2019-05-29 13:35:13 -0400138 return result, nil
139}
140
khenaidooba6b6c42019-08-02 09:11:56 -0400141//listLogicalDevices returns the list of all logical devices
khenaidoob9203542018-09-17 22:56:37 -0400142func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500143 log.Debug("ListAllLogicalDevices")
khenaidoob9203542018-09-17 22:56:37 -0400144 result := &voltha.LogicalDevices{}
Thomas Lee Se5a44012019-11-07 20:32:24 +0530145 logicalDevices, err := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, true, "")
146 if err != nil {
147 log.Errorw("failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err})
148 return nil, err
149 }
150 if logicalDevices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500151 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500152 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
khenaidoob9203542018-09-17 22:56:37 -0400153 }
154 }
155 return result, nil
156}
157
khenaidoo4d4802d2018-10-04 21:59:49 -0400158func (ldMgr *LogicalDeviceManager) createLogicalDevice(ctx context.Context, device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400159 log.Debugw("creating-logical-device", log.Fields{"deviceId": device.Id})
khenaidoob9203542018-09-17 22:56:37 -0400160 // Sanity check
161 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400162 return nil, errors.New("device-not-root")
khenaidoob9203542018-09-17 22:56:37 -0400163 }
164
165 // Create a logical device agent - the logical device Id is based on the mac address of the device
166 // For now use the serial number - it may contain any combination of alphabetic characters and numbers,
167 // with length varying from eight characters to a maximum of 14 characters. Mac Address is part of oneof
168 // in the Device model. May need to be moved out.
169 macAddress := device.MacAddress
170 id := strings.Replace(macAddress, ":", "", -1)
khenaidoo92e62c52018-10-03 14:02:54 -0400171 if id == "" {
172 log.Errorw("mac-address-not-set", log.Fields{"deviceId": device.Id})
173 return nil, errors.New("mac-address-not-set")
174 }
175 log.Debugw("logical-device-id", log.Fields{"logicaldeviceId": id})
khenaidoob9203542018-09-17 22:56:37 -0400176
khenaidoo2c6a0992019-04-29 13:46:56 -0400177 agent := newLogicalDeviceAgent(id, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy, ldMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400178 ldMgr.addLogicalDeviceAgentToMap(agent)
khenaidooad06fd72019-10-28 12:26:05 -0400179
180 // Update the root device with the logical device Id reference
npujar1d86a522019-11-14 17:11:16 +0530181 if err := ldMgr.deviceMgr.setParentID(device, id); err != nil {
khenaidooad06fd72019-10-28 12:26:05 -0400182 log.Errorw("failed-setting-parent-id", log.Fields{"logicalDeviceId": id, "deviceId": device.Id})
183 return nil, err
184 }
185
npujar1d86a522019-11-14 17:11:16 +0530186 go func() {
187 err := agent.start(ctx, false)
188 if err != nil {
189 log.Errorw("unable-to-create-the-logical-device", log.Fields{"error": err})
190 }
191 }()
khenaidoob9203542018-09-17 22:56:37 -0400192
khenaidoo92e62c52018-10-03 14:02:54 -0400193 log.Debug("creating-logical-device-ends")
khenaidoob9203542018-09-17 22:56:37 -0400194 return &id, nil
195}
196
khenaidoo6d62c002019-05-15 21:57:03 -0400197// stopManagingLogicalDeviceWithDeviceId stops the management of the logical device. This implies removal of any
198// reference of this logical device in cache. The device Id is passed as param because the logical device may already
199// have been removed from the model. This function returns the logical device Id if found
npujar1d86a522019-11-14 17:11:16 +0530200func (ldMgr *LogicalDeviceManager) stopManagingLogicalDeviceWithDeviceID(id string) string {
khenaidoo6d62c002019-05-15 21:57:03 -0400201 log.Infow("stop-managing-logical-device", log.Fields{"deviceId": id})
202 // Go over the list of logical device agents to find the one which has rootDeviceId as id
npujar1d86a522019-11-14 17:11:16 +0530203 var ldID = ""
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400204 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
205 ldAgent := value.(*LogicalDeviceAgent)
npujar1d86a522019-11-14 17:11:16 +0530206 if ldAgent.rootDeviceID == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400207 log.Infow("stopping-logical-device-agent", log.Fields{"lDeviceId": key})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530208 if err := ldAgent.stop(context.TODO()); err != nil {
209 log.Errorw("failed-to-stop-LDAgent", log.Fields{"error": err})
210 return false
211 }
npujar1d86a522019-11-14 17:11:16 +0530212 ldID = key.(string)
213 ldMgr.logicalDeviceAgents.Delete(ldID)
khenaidoo6d62c002019-05-15 21:57:03 -0400214 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400215 return true
216 })
npujar1d86a522019-11-14 17:11:16 +0530217 return ldID
khenaidoo6d62c002019-05-15 21:57:03 -0400218}
219
220//getLogicalDeviceFromModel retrieves the logical device data from the model.
npujar1d86a522019-11-14 17:11:16 +0530221func (ldMgr *LogicalDeviceManager) getLogicalDeviceFromModel(lDeviceID string) (*voltha.LogicalDevice, error) {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530222 logicalDevice, err := ldMgr.clusterDataProxy.Get(context.Background(), "/logical_devices/"+lDeviceID, 0, false, "")
223 if err != nil {
224 log.Errorw("failed-to-get-logical-devices-from-cluster-proxy", log.Fields{"error": err})
225 return nil, err
226 }
227 if logicalDevice != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400228 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
229 return lDevice, nil
230 }
231 }
npujar1d86a522019-11-14 17:11:16 +0530232 return nil, status.Error(codes.NotFound, lDeviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400233}
234
khenaidoo297cd252019-02-07 22:10:23 -0500235// load loads a logical device manager in memory
npujar1d86a522019-11-14 17:11:16 +0530236func (ldMgr *LogicalDeviceManager) load(lDeviceID string) error {
237 if lDeviceID == "" {
khenaidoo4c9e5592019-09-09 16:20:41 -0400238 return nil
khenaidoo297cd252019-02-07 22:10:23 -0500239 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400240 // Add a lock to prevent two concurrent calls from loading the same device twice
241 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530242 if _, exist := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; !exist {
243 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
244 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400245 ldMgr.logicalDevicesLoadingLock.Unlock()
npujar1d86a522019-11-14 17:11:16 +0530246 if _, err := ldMgr.getLogicalDeviceFromModel(lDeviceID); err == nil {
247 log.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceID})
248 agent := newLogicalDeviceAgent(lDeviceID, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy, ldMgr.defaultTimeout)
249 if err := agent.start(context.TODO(), true); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530250 if err := agent.stop(context.TODO()); err != nil {
251 log.Errorw("failed-to-stop-agent", log.Fields{"error": err})
252 return err
253 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400254 } else {
npujar1d86a522019-11-14 17:11:16 +0530255 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoo4c9e5592019-09-09 16:20:41 -0400256 }
257 } else {
npujar1d86a522019-11-14 17:11:16 +0530258 log.Debugw("logicalDevice not in model", log.Fields{"lDeviceId": lDeviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400259 }
260 // announce completion of task to any number of waiting channels
261 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530262 if v, ok := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400263 for _, ch := range v {
264 close(ch)
265 }
npujar1d86a522019-11-14 17:11:16 +0530266 delete(ldMgr.logicalDeviceLoadingInProgress, lDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400267 }
268 ldMgr.logicalDevicesLoadingLock.Unlock()
269 } else {
270 ldMgr.logicalDevicesLoadingLock.Unlock()
271 }
272 } else {
273 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530274 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = append(ldMgr.logicalDeviceLoadingInProgress[lDeviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400275 ldMgr.logicalDevicesLoadingLock.Unlock()
276 // Wait for the channel to be closed, implying the process loading this device is done.
277 <-ch
278 }
npujar1d86a522019-11-14 17:11:16 +0530279 if _, exist := ldMgr.logicalDeviceAgents.Load(lDeviceID); exist {
khenaidoo4c9e5592019-09-09 16:20:41 -0400280 return nil
281 }
npujar1d86a522019-11-14 17:11:16 +0530282 return status.Errorf(codes.Aborted, "Error loading logical device %s", lDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500283}
284
khenaidoo4d4802d2018-10-04 21:59:49 -0400285func (ldMgr *LogicalDeviceManager) deleteLogicalDevice(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400286 log.Debugw("deleting-logical-device", log.Fields{"deviceId": device.Id})
287 // Sanity check
288 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400289 return errors.New("device-not-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400290 }
npujar1d86a522019-11-14 17:11:16 +0530291 logDeviceID := device.ParentId
292 if agent := ldMgr.getLogicalDeviceAgent(logDeviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400293 // Stop the logical device agent
Thomas Lee Se5a44012019-11-07 20:32:24 +0530294 if err := agent.stop(ctx); err != nil {
295 log.Errorw("failed-to-stop-agent", log.Fields{"error": err})
296 return err
297 }
khenaidoo92e62c52018-10-03 14:02:54 -0400298 //Remove the logical device agent from the Map
npujar1d86a522019-11-14 17:11:16 +0530299 ldMgr.deleteLogicalDeviceAgent(logDeviceID)
300 err := ldMgr.core.deviceOwnership.AbandonDevice(logDeviceID)
301 if err != nil {
302 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
303 }
khenaidoo92e62c52018-10-03 14:02:54 -0400304 }
305
306 log.Debug("deleting-logical-device-ends")
307 return nil
308}
309
npujar1d86a522019-11-14 17:11:16 +0530310func (ldMgr *LogicalDeviceManager) getLogicalDeviceID(device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400311 // Device can either be a parent or a child device
312 if device.Root {
313 // Parent device. The ID of a parent device is the logical device ID
314 return &device.ParentId, nil
315 }
316 // Device is child device
317 // retrieve parent device using child device ID
318 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
319 return &parentDevice.ParentId, nil
320 }
321 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
322}
323
npujar1d86a522019-11-14 17:11:16 +0530324func (ldMgr *LogicalDeviceManager) getLogicalDeviceIDFromDeviceID(deviceID string) (*string, error) {
khenaidoo3ab34882019-05-02 21:33:30 -0400325 // Get the device
326 var device *voltha.Device
327 var err error
npujar1d86a522019-11-14 17:11:16 +0530328 if device, err = ldMgr.deviceMgr.GetDevice(deviceID); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400329 return nil, err
330 }
npujar1d86a522019-11-14 17:11:16 +0530331 return ldMgr.getLogicalDeviceID(device)
khenaidoo3ab34882019-05-02 21:33:30 -0400332}
333
npujar1d86a522019-11-14 17:11:16 +0530334func (ldMgr *LogicalDeviceManager) getLogicalPortID(device *voltha.Device) (*voltha.LogicalPortId, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400335 // Get the logical device where this device is attached
npujar1d86a522019-11-14 17:11:16 +0530336 var lDeviceID *string
khenaidoo19d7b632018-10-30 10:49:50 -0400337 var err error
npujar1d86a522019-11-14 17:11:16 +0530338 if lDeviceID, err = ldMgr.getLogicalDeviceID(device); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400339 return nil, err
340 }
341 var lDevice *voltha.LogicalDevice
npujar1d86a522019-11-14 17:11:16 +0530342 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400343 return nil, err
344 }
345 // Go over list of ports
346 for _, port := range lDevice.Ports {
347 if port.DeviceId == device.Id {
npujar1d86a522019-11-14 17:11:16 +0530348 return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400349 }
350 }
351 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
352}
353
npujar1d86a522019-11-14 17:11:16 +0530354// ListLogicalDeviceFlows returns the flows of logical device
khenaidoodd237172019-05-27 16:37:17 -0400355func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*openflow_13.Flows, error) {
356 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
357 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500358 return agent.ListLogicalDeviceFlows(), nil
khenaidoodd237172019-05-27 16:37:17 -0400359 }
360 return nil, status.Errorf(codes.NotFound, "%s", id)
361}
362
npujar1d86a522019-11-14 17:11:16 +0530363// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoodd237172019-05-27 16:37:17 -0400364func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*openflow_13.FlowGroups, error) {
365 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
366 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500367 return agent.ListLogicalDeviceFlowGroups(), nil
khenaidoodd237172019-05-27 16:37:17 -0400368 }
369 return nil, status.Errorf(codes.NotFound, "%s", id)
370}
371
npujar1d86a522019-11-14 17:11:16 +0530372// ListLogicalDevicePorts returns logical device ports
khenaidoo19d7b632018-10-30 10:49:50 -0400373func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
374 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
375 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500376 return agent.ListLogicalDevicePorts(), nil
khenaidoo19d7b632018-10-30 10:49:50 -0400377 }
378 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoo19d7b632018-10-30 10:49:50 -0400379}
380
npujar1d86a522019-11-14 17:11:16 +0530381func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400382 // Get the logical device where this device is attached
383 var err error
384 var lDevice *voltha.LogicalDevice
npujar1d86a522019-11-14 17:11:16 +0530385 if lDevice, err = ldMgr.getLogicalDevice(lPortID.Id); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400386 return nil, err
387 }
388 // Go over list of ports
389 for _, port := range lDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +0530390 if port.Id == lPortID.PortId {
khenaidoo19d7b632018-10-30 10:49:50 -0400391 return port, nil
392 }
393 }
npujar1d86a522019-11-14 17:11:16 +0530394 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400395}
396
khenaidoo2c6a0992019-04-29 13:46:56 -0400397// updateLogicalPort sets up a logical port on the logical device based on the device port
398// information, if needed
399func (ldMgr *LogicalDeviceManager) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
npujar1d86a522019-11-14 17:11:16 +0530400 ldID, err := ldMgr.getLogicalDeviceID(device)
401 if err != nil || *ldID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400402 // This is not an error as the logical device may not have been created at this time. In such a case,
403 // the ports will be created when the logical device is ready.
404 return nil
khenaidoo2c6a0992019-04-29 13:46:56 -0400405 }
npujar1d86a522019-11-14 17:11:16 +0530406 if agent := ldMgr.getLogicalDeviceAgent(*ldID); agent != nil {
407 if err := agent.updateLogicalPort(device, port); err != nil {
408 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400409 }
410 }
411 return nil
412}
413
khenaidoo0a822f92019-05-08 15:15:57 -0400414// deleteLogicalPort removes the logical port associated with a device
npujar1d86a522019-11-14 17:11:16 +0530415func (ldMgr *LogicalDeviceManager) deleteLogicalPort(ctx context.Context, lPortID *voltha.LogicalPortId) error {
416 log.Debugw("deleting-logical-port", log.Fields{"LDeviceId": lPortID.Id})
khenaidoo19d7b632018-10-30 10:49:50 -0400417 // Get logical port
418 var logicalPort *voltha.LogicalPort
419 var err error
npujar1d86a522019-11-14 17:11:16 +0530420 if logicalPort, err = ldMgr.getLogicalPort(lPortID); err != nil {
421 log.Debugw("no-logical-device-port-present", log.Fields{"logicalPortId": lPortID.PortId})
khenaidoo19d7b632018-10-30 10:49:50 -0400422 return err
423 }
khenaidoo92e62c52018-10-03 14:02:54 -0400424 // Sanity check
khenaidoo19d7b632018-10-30 10:49:50 -0400425 if logicalPort.RootPort {
khenaidoo2c6a0992019-04-29 13:46:56 -0400426 return errors.New("device-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400427 }
npujar1d86a522019-11-14 17:11:16 +0530428 if agent := ldMgr.getLogicalDeviceAgent(lPortID.Id); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400429 if err := agent.deleteLogicalPort(logicalPort); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530430 log.Warnw("deleting-logicalport-failed", log.Fields{"LDeviceId": lPortID.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400431 }
khenaidoo92e62c52018-10-03 14:02:54 -0400432 }
433
434 log.Debug("deleting-logical-port-ends")
435 return nil
436}
437
khenaidoo0a822f92019-05-08 15:15:57 -0400438// deleteLogicalPort removes the logical port associated with a child device
npujar1d86a522019-11-14 17:11:16 +0530439func (ldMgr *LogicalDeviceManager) deleteLogicalPorts(deviceID string) error {
440 log.Debugw("deleting-logical-ports", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400441 // Get logical port
npujar1d86a522019-11-14 17:11:16 +0530442 ldID, err := ldMgr.getLogicalDeviceIDFromDeviceID(deviceID)
443 if err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400444 return err
npujar1d86a522019-11-14 17:11:16 +0530445 }
446 if agent := ldMgr.getLogicalDeviceAgent(*ldID); agent != nil {
447 if err = agent.deleteLogicalPorts(deviceID); err != nil {
448 log.Warnw("deleteLogicalPorts-failed", log.Fields{"ldeviceId": *ldID})
449 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400450 }
451 }
452 log.Debug("deleting-logical-port-ends")
453 return nil
454}
455
khenaidoofc1314d2019-03-14 09:34:21 -0400456func (ldMgr *LogicalDeviceManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400457 log.Debugw("setupUNILogicalPorts", log.Fields{"childDeviceId": childDevice.Id, "parentDeviceId": childDevice.ParentId, "current-data": childDevice})
khenaidoob9203542018-09-17 22:56:37 -0400458 // Sanity check
459 if childDevice.Root {
460 return errors.New("Device-root")
461 }
462
463 // Get the logical device id parent device
npujar1d86a522019-11-14 17:11:16 +0530464 parentID := childDevice.ParentId
465 logDeviceID := ldMgr.deviceMgr.GetParentDeviceID(parentID)
khenaidoob9203542018-09-17 22:56:37 -0400466
npujar1d86a522019-11-14 17:11:16 +0530467 log.Debugw("setupUNILogicalPorts", log.Fields{"logDeviceId": logDeviceID, "parentId": parentID})
khenaidoob9203542018-09-17 22:56:37 -0400468
npujar1d86a522019-11-14 17:11:16 +0530469 if parentID == "" || logDeviceID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400470 return errors.New("device-in-invalid-state")
khenaidoo5e677ae2019-02-28 17:26:29 -0500471 }
472
npujar1d86a522019-11-14 17:11:16 +0530473 if agent := ldMgr.getLogicalDeviceAgent(logDeviceID); agent != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400474 if err := agent.setupUNILogicalPorts(ctx, childDevice); err != nil {
khenaidoobcf205b2019-01-25 22:21:14 -0500475 return err
476 }
khenaidoob9203542018-09-17 22:56:37 -0400477 }
khenaidoo21d51152019-02-01 13:48:37 -0500478 return nil
khenaidoob9203542018-09-17 22:56:37 -0400479}
khenaidoo19d7b632018-10-30 10:49:50 -0400480
khenaidoo0a822f92019-05-08 15:15:57 -0400481func (ldMgr *LogicalDeviceManager) deleteAllLogicalPorts(device *voltha.Device) error {
482 log.Debugw("deleteAllLogicalPorts", log.Fields{"deviceId": device.Id})
483
npujar1d86a522019-11-14 17:11:16 +0530484 var ldID *string
khenaidoo0a822f92019-05-08 15:15:57 -0400485 var err error
486 //Get the logical device Id for this device
npujar1d86a522019-11-14 17:11:16 +0530487 if ldID, err = ldMgr.getLogicalDeviceID(device); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400488 log.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
489 return err
490 }
npujar1d86a522019-11-14 17:11:16 +0530491 if agent := ldMgr.getLogicalDeviceAgent(*ldID); agent != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400492 if err := agent.deleteAllLogicalPorts(device); err != nil {
493 return err
494 }
495 }
496 return nil
497}
npujar1d86a522019-11-14 17:11:16 +0530498func (ldMgr *LogicalDeviceManager) updatePortState(deviceID string, portNo uint32, state voltha.OperStatus_OperStatus) error {
499 log.Debugw("updatePortState", log.Fields{"deviceId": deviceID, "state": state, "portNo": portNo})
khenaidoo171b98e2019-10-31 11:48:15 -0400500
npujar1d86a522019-11-14 17:11:16 +0530501 var ldID *string
khenaidoo171b98e2019-10-31 11:48:15 -0400502 var err error
503 //Get the logical device Id for this device
npujar1d86a522019-11-14 17:11:16 +0530504 if ldID, err = ldMgr.getLogicalDeviceIDFromDeviceID(deviceID); err != nil {
505 log.Warnw("no-logical-device-found", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400506 return err
507 }
npujar1d86a522019-11-14 17:11:16 +0530508 if agent := ldMgr.getLogicalDeviceAgent(*ldID); agent != nil {
509 if err := agent.updatePortState(deviceID, portNo, state); err != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400510 return err
511 }
512 }
513 return nil
514}
khenaidoo0a822f92019-05-08 15:15:57 -0400515
khenaidoo3ab34882019-05-02 21:33:30 -0400516func (ldMgr *LogicalDeviceManager) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400517 log.Debugw("updatePortsState", log.Fields{"deviceId": device.Id, "state": state, "current-data": device})
khenaidoo3ab34882019-05-02 21:33:30 -0400518
npujar1d86a522019-11-14 17:11:16 +0530519 var ldID *string
khenaidoo3ab34882019-05-02 21:33:30 -0400520 var err error
521 //Get the logical device Id for this device
npujar1d86a522019-11-14 17:11:16 +0530522 if ldID, err = ldMgr.getLogicalDeviceID(device); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400523 log.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
524 return err
525 }
npujar1d86a522019-11-14 17:11:16 +0530526 if agent := ldMgr.getLogicalDeviceAgent(*ldID); agent != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400527 if err := agent.updatePortsState(device, state); err != nil {
528 return err
529 }
530 }
531 return nil
532}
533
khenaidoo19d7b632018-10-30 10:49:50 -0400534func (ldMgr *LogicalDeviceManager) updateFlowTable(ctx context.Context, id string, flow *openflow_13.OfpFlowMod, ch chan interface{}) {
535 log.Debugw("updateFlowTable", log.Fields{"logicalDeviceId": id})
536 var res interface{}
537 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
538 res = agent.updateFlowTable(ctx, flow)
539 log.Debugw("updateFlowTable-result", log.Fields{"result": res})
540 } else {
541 res = status.Errorf(codes.NotFound, "%s", id)
542 }
543 sendAPIResponse(ctx, ch, res)
544}
545
Manikkaraj kb1a10922019-07-29 12:10:34 -0400546func (ldMgr *LogicalDeviceManager) updateMeterTable(ctx context.Context, id string, meter *openflow_13.OfpMeterMod, ch chan interface{}) {
547 log.Debugw("updateMeterTable", log.Fields{"logicalDeviceId": id})
548 var res interface{}
549 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
550 res = agent.updateMeterTable(ctx, meter)
551 log.Debugw("updateMeterTable-result", log.Fields{"result": res})
552 } else {
553 res = status.Errorf(codes.NotFound, "%s", id)
554 }
555 sendAPIResponse(ctx, ch, res)
556}
557
npujar1d86a522019-11-14 17:11:16 +0530558// ListLogicalDeviceMeters returns logical device meters
Manikkaraj kb1a10922019-07-29 12:10:34 -0400559func (ldMgr *LogicalDeviceManager) ListLogicalDeviceMeters(ctx context.Context, id string) (*openflow_13.Meters, error) {
560 log.Debugw("ListLogicalDeviceMeters", log.Fields{"logicalDeviceId": id})
561 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500562 return agent.ListLogicalDeviceMeters(), nil
Manikkaraj kb1a10922019-07-29 12:10:34 -0400563 }
564 return nil, status.Errorf(codes.NotFound, "%s", id)
565}
khenaidoo19d7b632018-10-30 10:49:50 -0400566func (ldMgr *LogicalDeviceManager) updateGroupTable(ctx context.Context, id string, groupMod *openflow_13.OfpGroupMod, ch chan interface{}) {
567 log.Debugw("updateGroupTable", log.Fields{"logicalDeviceId": id})
568 var res interface{}
569 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
570 res = agent.updateGroupTable(ctx, groupMod)
571 log.Debugw("updateGroupTable-result", log.Fields{"result": res})
572 } else {
573 res = status.Errorf(codes.NotFound, "%s", id)
574 }
575 sendAPIResponse(ctx, ch, res)
576}
577
578func (ldMgr *LogicalDeviceManager) enableLogicalPort(ctx context.Context, id *voltha.LogicalPortId, ch chan interface{}) {
579 log.Debugw("enableLogicalPort", log.Fields{"logicalDeviceId": id})
580 var res interface{}
khenaidoo19d7b632018-10-30 10:49:50 -0400581 if agent := ldMgr.getLogicalDeviceAgent(id.Id); agent != nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +0000582 res = agent.enableLogicalPort(id.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400583 log.Debugw("enableLogicalPort-result", log.Fields{"result": res})
584 } else {
585 res = status.Errorf(codes.NotFound, "%s", id.Id)
586 }
587 sendAPIResponse(ctx, ch, res)
588}
589
590func (ldMgr *LogicalDeviceManager) disableLogicalPort(ctx context.Context, id *voltha.LogicalPortId, ch chan interface{}) {
591 log.Debugw("disableLogicalPort", log.Fields{"logicalDeviceId": id})
592 var res interface{}
khenaidoo19d7b632018-10-30 10:49:50 -0400593 if agent := ldMgr.getLogicalDeviceAgent(id.Id); agent != nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +0000594 res = agent.disableLogicalPort(id.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400595 log.Debugw("disableLogicalPort-result", log.Fields{"result": res})
596 } else {
597 res = status.Errorf(codes.NotFound, "%s", id.Id)
598 }
599 sendAPIResponse(ctx, ch, res)
600}
khenaidoofdbad6e2018-11-06 22:26:38 -0500601
npujar1d86a522019-11-14 17:11:16 +0530602func (ldMgr *LogicalDeviceManager) packetIn(logicalDeviceID string, port uint32, transactionID string, packet []byte) error {
603 log.Debugw("packetIn", log.Fields{"logicalDeviceId": logicalDeviceID, "port": port})
604 if agent := ldMgr.getLogicalDeviceAgent(logicalDeviceID); agent != nil {
605 agent.packetIn(port, transactionID, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500606 } else {
npujar1d86a522019-11-14 17:11:16 +0530607 log.Error("logical-device-not-exist", log.Fields{"logicalDeviceId": logicalDeviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -0500608 }
609 return nil
610}