blob: 185978479fe4cc303e4d58644e048c8ac04021f4 [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"
sbarbari17d7e222019-11-05 10:02:29 -050022 "github.com/opencord/voltha-go/db/model"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080023 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
24 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
26 "github.com/opencord/voltha-protos/v3/go/openflow_13"
27 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040028 "google.golang.org/grpc/codes"
29 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040030 "strings"
31 "sync"
32 "time"
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
npujar467fe752020-01-16 20:17:45 +053041 kafkaICProxy kafka.InterContainerProxy
khenaidoo4c9e5592019-09-09 16:20:41 -040042 clusterDataProxy *model.Proxy
43 exitChannel chan int
khenaidoo442e7c72020-03-10 16:13:48 -040044 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040045 logicalDevicesLoadingLock sync.RWMutex
46 logicalDeviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040047}
48
khenaidoo442e7c72020-03-10 16:13:48 -040049func newLogicalDeviceManager(core *Core, deviceMgr *DeviceManager, kafkaICProxy kafka.InterContainerProxy, cdProxy *model.Proxy, timeout time.Duration) *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.
npujar467fe752020-01-16 20:17:45 +053099func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(ctx context.Context, logicalDeviceID string) *LogicalDeviceAgent {
npujar1d86a522019-11-14 17:11:16 +0530100 agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceID)
101 if ok {
khenaidoo93d5a3d2020-01-15 12:37:05 -0500102 lda := agent.(*LogicalDeviceAgent)
103 if lda.logicalDevice == nil {
104 // This can happen when an agent for the logical device has been created but the logical device
105 // itself is not ready for action as it is waiting for switch and port capabilities from the
106 // relevant adapter. In such a case prevent any request aimed at that logical device.
107 log.Debugf("Logical device %s is not ready to serve requests", logicalDeviceID)
108 return nil
109 }
110 return lda
npujar1d86a522019-11-14 17:11:16 +0530111 }
112 // Try to load into memory - loading will also create the logical device agent
npujar467fe752020-01-16 20:17:45 +0530113 if err := ldMgr.load(ctx, logicalDeviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530114 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceID); ok {
115 return agent.(*LogicalDeviceAgent)
khenaidoo8c3303d2019-02-13 14:59:39 -0500116 }
khenaidoob9203542018-09-17 22:56:37 -0400117 }
118 return nil
119}
120
npujar1d86a522019-11-14 17:11:16 +0530121func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceID string) {
122 ldMgr.logicalDeviceAgents.Delete(logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400123}
124
khenaidoo8c3303d2019-02-13 14:59:39 -0500125// GetLogicalDevice provides a cloned most up to date logical device. If device is not in memory
126// it will be fetched from the dB
npujar467fe752020-01-16 20:17:45 +0530127func (ldMgr *LogicalDeviceManager) getLogicalDevice(ctx context.Context, id string) (*voltha.LogicalDevice, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400128 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
npujar467fe752020-01-16 20:17:45 +0530129 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400130 return agent.GetLogicalDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400131 }
132 return nil, status.Errorf(codes.NotFound, "%s", id)
133}
134
khenaidoo442e7c72020-03-10 16:13:48 -0400135func (ldMgr *LogicalDeviceManager) listManagedLogicalDevices(ctx context.Context) (*voltha.LogicalDevices, error) {
khenaidoo43aa6bd2019-05-29 13:35:13 -0400136 log.Debug("listManagedLogicalDevices")
137 result := &voltha.LogicalDevices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400138 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
139 agent := value.(*LogicalDeviceAgent)
khenaidoo442e7c72020-03-10 16:13:48 -0400140 if ld, _ := agent.GetLogicalDevice(ctx); ld != nil {
khenaidoo43aa6bd2019-05-29 13:35:13 -0400141 result.Items = append(result.Items, ld)
142 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400143 return true
144 })
145
khenaidoo43aa6bd2019-05-29 13:35:13 -0400146 return result, nil
147}
148
khenaidooba6b6c42019-08-02 09:11:56 -0400149//listLogicalDevices returns the list of all logical devices
npujar467fe752020-01-16 20:17:45 +0530150func (ldMgr *LogicalDeviceManager) listLogicalDevices(ctx context.Context) (*voltha.LogicalDevices, error) {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500151 log.Debug("ListAllLogicalDevices")
khenaidoob9203542018-09-17 22:56:37 -0400152 result := &voltha.LogicalDevices{}
npujar467fe752020-01-16 20:17:45 +0530153 logicalDevices, err := ldMgr.clusterDataProxy.List(ctx, "/logical_devices", 0, true, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530154 if err != nil {
155 log.Errorw("failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err})
156 return nil, err
157 }
158 if logicalDevices != nil {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500159 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500160 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
khenaidoob9203542018-09-17 22:56:37 -0400161 }
162 }
163 return result, nil
164}
165
khenaidoo4d4802d2018-10-04 21:59:49 -0400166func (ldMgr *LogicalDeviceManager) createLogicalDevice(ctx context.Context, device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400167 log.Debugw("creating-logical-device", log.Fields{"deviceId": device.Id})
khenaidoob9203542018-09-17 22:56:37 -0400168 // Sanity check
169 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400170 return nil, errors.New("device-not-root")
khenaidoob9203542018-09-17 22:56:37 -0400171 }
172
173 // Create a logical device agent - the logical device Id is based on the mac address of the device
174 // For now use the serial number - it may contain any combination of alphabetic characters and numbers,
175 // with length varying from eight characters to a maximum of 14 characters. Mac Address is part of oneof
176 // in the Device model. May need to be moved out.
177 macAddress := device.MacAddress
178 id := strings.Replace(macAddress, ":", "", -1)
khenaidoo92e62c52018-10-03 14:02:54 -0400179 if id == "" {
180 log.Errorw("mac-address-not-set", log.Fields{"deviceId": device.Id})
181 return nil, errors.New("mac-address-not-set")
182 }
183 log.Debugw("logical-device-id", log.Fields{"logicaldeviceId": id})
khenaidoob9203542018-09-17 22:56:37 -0400184
khenaidoo2c6a0992019-04-29 13:46:56 -0400185 agent := newLogicalDeviceAgent(id, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy, ldMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400186 ldMgr.addLogicalDeviceAgentToMap(agent)
khenaidooad06fd72019-10-28 12:26:05 -0400187
188 // Update the root device with the logical device Id reference
npujar467fe752020-01-16 20:17:45 +0530189 if err := ldMgr.deviceMgr.setParentID(ctx, device, id); err != nil {
khenaidooad06fd72019-10-28 12:26:05 -0400190 log.Errorw("failed-setting-parent-id", log.Fields{"logicalDeviceId": id, "deviceId": device.Id})
191 return nil, err
192 }
193
npujar1d86a522019-11-14 17:11:16 +0530194 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400195 //agent := newLogicalDeviceAgent(id, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy, ldMgr.defaultTimeout)
196 err := agent.start(context.Background(), false)
npujar1d86a522019-11-14 17:11:16 +0530197 if err != nil {
198 log.Errorw("unable-to-create-the-logical-device", log.Fields{"error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400199 ldMgr.deleteLogicalDeviceAgent(id)
npujar1d86a522019-11-14 17:11:16 +0530200 }
201 }()
khenaidoob9203542018-09-17 22:56:37 -0400202
khenaidoo92e62c52018-10-03 14:02:54 -0400203 log.Debug("creating-logical-device-ends")
khenaidoob9203542018-09-17 22:56:37 -0400204 return &id, nil
205}
206
khenaidoo6d62c002019-05-15 21:57:03 -0400207// stopManagingLogicalDeviceWithDeviceId stops the management of the logical device. This implies removal of any
208// reference of this logical device in cache. The device Id is passed as param because the logical device may already
209// have been removed from the model. This function returns the logical device Id if found
npujar467fe752020-01-16 20:17:45 +0530210func (ldMgr *LogicalDeviceManager) stopManagingLogicalDeviceWithDeviceID(ctx context.Context, id string) string {
khenaidoo6d62c002019-05-15 21:57:03 -0400211 log.Infow("stop-managing-logical-device", log.Fields{"deviceId": id})
212 // Go over the list of logical device agents to find the one which has rootDeviceId as id
npujar1d86a522019-11-14 17:11:16 +0530213 var ldID = ""
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400214 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
215 ldAgent := value.(*LogicalDeviceAgent)
npujar1d86a522019-11-14 17:11:16 +0530216 if ldAgent.rootDeviceID == id {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400217 log.Infow("stopping-logical-device-agent", log.Fields{"lDeviceId": key})
npujar467fe752020-01-16 20:17:45 +0530218 if err := ldAgent.stop(ctx); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530219 log.Errorw("failed-to-stop-LDAgent", log.Fields{"error": err})
220 return false
221 }
npujar1d86a522019-11-14 17:11:16 +0530222 ldID = key.(string)
223 ldMgr.logicalDeviceAgents.Delete(ldID)
khenaidoo6d62c002019-05-15 21:57:03 -0400224 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400225 return true
226 })
npujar1d86a522019-11-14 17:11:16 +0530227 return ldID
khenaidoo6d62c002019-05-15 21:57:03 -0400228}
229
230//getLogicalDeviceFromModel retrieves the logical device data from the model.
npujar467fe752020-01-16 20:17:45 +0530231func (ldMgr *LogicalDeviceManager) getLogicalDeviceFromModel(ctx context.Context, lDeviceID string) (*voltha.LogicalDevice, error) {
232 logicalDevice, err := ldMgr.clusterDataProxy.Get(ctx, "/logical_devices/"+lDeviceID, 0, false, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530233 if err != nil {
234 log.Errorw("failed-to-get-logical-devices-from-cluster-proxy", log.Fields{"error": err})
235 return nil, err
236 }
237 if logicalDevice != nil {
khenaidoo6d62c002019-05-15 21:57:03 -0400238 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
239 return lDevice, nil
240 }
241 }
npujar1d86a522019-11-14 17:11:16 +0530242 return nil, status.Error(codes.NotFound, lDeviceID)
khenaidoo6d62c002019-05-15 21:57:03 -0400243}
244
khenaidoo297cd252019-02-07 22:10:23 -0500245// load loads a logical device manager in memory
npujar467fe752020-01-16 20:17:45 +0530246func (ldMgr *LogicalDeviceManager) load(ctx context.Context, lDeviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530247 if lDeviceID == "" {
khenaidoo4c9e5592019-09-09 16:20:41 -0400248 return nil
khenaidoo297cd252019-02-07 22:10:23 -0500249 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400250 // Add a lock to prevent two concurrent calls from loading the same device twice
251 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530252 if _, exist := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; !exist {
253 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
254 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400255 ldMgr.logicalDevicesLoadingLock.Unlock()
npujar467fe752020-01-16 20:17:45 +0530256 if _, err := ldMgr.getLogicalDeviceFromModel(ctx, lDeviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +0530257 log.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceID})
258 agent := newLogicalDeviceAgent(lDeviceID, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy, ldMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530259 if err := agent.start(ctx, true); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400260 return err
khenaidoo4c9e5592019-09-09 16:20:41 -0400261 }
khenaidoo442e7c72020-03-10 16:13:48 -0400262 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoo4c9e5592019-09-09 16:20:41 -0400263 } else {
npujar1d86a522019-11-14 17:11:16 +0530264 log.Debugw("logicalDevice not in model", log.Fields{"lDeviceId": lDeviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400265 }
266 // announce completion of task to any number of waiting channels
267 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530268 if v, ok := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400269 for _, ch := range v {
270 close(ch)
271 }
npujar1d86a522019-11-14 17:11:16 +0530272 delete(ldMgr.logicalDeviceLoadingInProgress, lDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400273 }
274 ldMgr.logicalDevicesLoadingLock.Unlock()
275 } else {
276 ldMgr.logicalDevicesLoadingLock.Unlock()
277 }
278 } else {
279 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530280 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = append(ldMgr.logicalDeviceLoadingInProgress[lDeviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400281 ldMgr.logicalDevicesLoadingLock.Unlock()
282 // Wait for the channel to be closed, implying the process loading this device is done.
283 <-ch
284 }
npujar1d86a522019-11-14 17:11:16 +0530285 if _, exist := ldMgr.logicalDeviceAgents.Load(lDeviceID); exist {
khenaidoo4c9e5592019-09-09 16:20:41 -0400286 return nil
287 }
npujar1d86a522019-11-14 17:11:16 +0530288 return status.Errorf(codes.Aborted, "Error loading logical device %s", lDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500289}
290
khenaidoo4d4802d2018-10-04 21:59:49 -0400291func (ldMgr *LogicalDeviceManager) deleteLogicalDevice(ctx context.Context, device *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400292 log.Debugw("deleting-logical-device", log.Fields{"deviceId": device.Id})
293 // Sanity check
294 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400295 return errors.New("device-not-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400296 }
npujar1d86a522019-11-14 17:11:16 +0530297 logDeviceID := device.ParentId
npujar467fe752020-01-16 20:17:45 +0530298 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400299 // Stop the logical device agent
Thomas Lee Se5a44012019-11-07 20:32:24 +0530300 if err := agent.stop(ctx); err != nil {
301 log.Errorw("failed-to-stop-agent", log.Fields{"error": err})
302 return err
303 }
khenaidoo92e62c52018-10-03 14:02:54 -0400304 //Remove the logical device agent from the Map
npujar1d86a522019-11-14 17:11:16 +0530305 ldMgr.deleteLogicalDeviceAgent(logDeviceID)
306 err := ldMgr.core.deviceOwnership.AbandonDevice(logDeviceID)
307 if err != nil {
308 log.Errorw("unable-to-abandon-the-device", log.Fields{"error": err})
309 }
khenaidoo92e62c52018-10-03 14:02:54 -0400310 }
311
312 log.Debug("deleting-logical-device-ends")
313 return nil
314}
315
npujar467fe752020-01-16 20:17:45 +0530316func (ldMgr *LogicalDeviceManager) getLogicalDeviceID(ctx context.Context, device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400317 // Device can either be a parent or a child device
318 if device.Root {
319 // Parent device. The ID of a parent device is the logical device ID
320 return &device.ParentId, nil
321 }
322 // Device is child device
323 // retrieve parent device using child device ID
npujar467fe752020-01-16 20:17:45 +0530324 if parentDevice := ldMgr.deviceMgr.getParentDevice(ctx, device); parentDevice != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400325 return &parentDevice.ParentId, nil
326 }
327 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
328}
329
npujar467fe752020-01-16 20:17:45 +0530330func (ldMgr *LogicalDeviceManager) getLogicalDeviceIDFromDeviceID(ctx context.Context, deviceID string) (*string, error) {
khenaidoo3ab34882019-05-02 21:33:30 -0400331 // Get the device
332 var device *voltha.Device
333 var err error
npujar467fe752020-01-16 20:17:45 +0530334 if device, err = ldMgr.deviceMgr.GetDevice(ctx, deviceID); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400335 return nil, err
336 }
npujar467fe752020-01-16 20:17:45 +0530337 return ldMgr.getLogicalDeviceID(ctx, device)
khenaidoo3ab34882019-05-02 21:33:30 -0400338}
339
npujar467fe752020-01-16 20:17:45 +0530340func (ldMgr *LogicalDeviceManager) getLogicalPortID(ctx context.Context, device *voltha.Device) (*voltha.LogicalPortId, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400341 // Get the logical device where this device is attached
npujar1d86a522019-11-14 17:11:16 +0530342 var lDeviceID *string
khenaidoo19d7b632018-10-30 10:49:50 -0400343 var err error
npujar467fe752020-01-16 20:17:45 +0530344 if lDeviceID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400345 return nil, err
346 }
347 var lDevice *voltha.LogicalDevice
npujar467fe752020-01-16 20:17:45 +0530348 if lDevice, err = ldMgr.getLogicalDevice(ctx, *lDeviceID); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400349 return nil, err
350 }
351 // Go over list of ports
352 for _, port := range lDevice.Ports {
353 if port.DeviceId == device.Id {
npujar1d86a522019-11-14 17:11:16 +0530354 return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400355 }
356 }
357 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
358}
359
npujar1d86a522019-11-14 17:11:16 +0530360// ListLogicalDeviceFlows returns the flows of logical device
khenaidoodd237172019-05-27 16:37:17 -0400361func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*openflow_13.Flows, error) {
362 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
npujar467fe752020-01-16 20:17:45 +0530363 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400364 return agent.ListLogicalDeviceFlows(ctx)
khenaidoodd237172019-05-27 16:37:17 -0400365 }
366 return nil, status.Errorf(codes.NotFound, "%s", id)
367}
368
npujar1d86a522019-11-14 17:11:16 +0530369// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoodd237172019-05-27 16:37:17 -0400370func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*openflow_13.FlowGroups, error) {
371 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
npujar467fe752020-01-16 20:17:45 +0530372 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400373 return agent.ListLogicalDeviceFlowGroups(ctx)
khenaidoodd237172019-05-27 16:37:17 -0400374 }
375 return nil, status.Errorf(codes.NotFound, "%s", id)
376}
377
npujar1d86a522019-11-14 17:11:16 +0530378// ListLogicalDevicePorts returns logical device ports
khenaidoo19d7b632018-10-30 10:49:50 -0400379func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
380 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
npujar467fe752020-01-16 20:17:45 +0530381 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400382 return agent.ListLogicalDevicePorts(ctx)
khenaidoo19d7b632018-10-30 10:49:50 -0400383 }
384 return nil, status.Errorf(codes.NotFound, "%s", id)
khenaidoo19d7b632018-10-30 10:49:50 -0400385}
386
npujar467fe752020-01-16 20:17:45 +0530387func (ldMgr *LogicalDeviceManager) getLogicalPort(ctx context.Context, lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400388 // Get the logical device where this device is attached
389 var err error
390 var lDevice *voltha.LogicalDevice
npujar467fe752020-01-16 20:17:45 +0530391 if lDevice, err = ldMgr.getLogicalDevice(ctx, lPortID.Id); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400392 return nil, err
393 }
394 // Go over list of ports
395 for _, port := range lDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +0530396 if port.Id == lPortID.PortId {
khenaidoo19d7b632018-10-30 10:49:50 -0400397 return port, nil
398 }
399 }
npujar1d86a522019-11-14 17:11:16 +0530400 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400401}
402
khenaidoo2c6a0992019-04-29 13:46:56 -0400403// updateLogicalPort sets up a logical port on the logical device based on the device port
404// information, if needed
npujar467fe752020-01-16 20:17:45 +0530405func (ldMgr *LogicalDeviceManager) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
406 ldID, err := ldMgr.getLogicalDeviceID(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530407 if err != nil || *ldID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400408 // This is not an error as the logical device may not have been created at this time. In such a case,
409 // the ports will be created when the logical device is ready.
410 return nil
khenaidoo2c6a0992019-04-29 13:46:56 -0400411 }
npujar467fe752020-01-16 20:17:45 +0530412 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
413 if err := agent.updateLogicalPort(ctx, device, port); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530414 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400415 }
416 }
417 return nil
418}
419
khenaidoo0a822f92019-05-08 15:15:57 -0400420// deleteLogicalPort removes the logical port associated with a device
npujar1d86a522019-11-14 17:11:16 +0530421func (ldMgr *LogicalDeviceManager) deleteLogicalPort(ctx context.Context, lPortID *voltha.LogicalPortId) error {
422 log.Debugw("deleting-logical-port", log.Fields{"LDeviceId": lPortID.Id})
khenaidoo19d7b632018-10-30 10:49:50 -0400423 // Get logical port
424 var logicalPort *voltha.LogicalPort
425 var err error
npujar467fe752020-01-16 20:17:45 +0530426 if logicalPort, err = ldMgr.getLogicalPort(ctx, lPortID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530427 log.Debugw("no-logical-device-port-present", log.Fields{"logicalPortId": lPortID.PortId})
khenaidoo19d7b632018-10-30 10:49:50 -0400428 return err
429 }
khenaidoo92e62c52018-10-03 14:02:54 -0400430 // Sanity check
khenaidoo19d7b632018-10-30 10:49:50 -0400431 if logicalPort.RootPort {
khenaidoo2c6a0992019-04-29 13:46:56 -0400432 return errors.New("device-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400433 }
npujar467fe752020-01-16 20:17:45 +0530434 if agent := ldMgr.getLogicalDeviceAgent(ctx, lPortID.Id); agent != nil {
435 if err := agent.deleteLogicalPort(ctx, logicalPort); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530436 log.Warnw("deleting-logicalport-failed", log.Fields{"LDeviceId": lPortID.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400437 }
khenaidoo92e62c52018-10-03 14:02:54 -0400438 }
439
440 log.Debug("deleting-logical-port-ends")
441 return nil
442}
443
khenaidoo0a822f92019-05-08 15:15:57 -0400444// deleteLogicalPort removes the logical port associated with a child device
npujar467fe752020-01-16 20:17:45 +0530445func (ldMgr *LogicalDeviceManager) deleteLogicalPorts(ctx context.Context, deviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530446 log.Debugw("deleting-logical-ports", log.Fields{"deviceId": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400447 // Get logical port
npujar467fe752020-01-16 20:17:45 +0530448 ldID, err := ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530449 if err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400450 return err
npujar1d86a522019-11-14 17:11:16 +0530451 }
npujar467fe752020-01-16 20:17:45 +0530452 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
453 if err = agent.deleteLogicalPorts(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530454 log.Warnw("deleteLogicalPorts-failed", log.Fields{"ldeviceId": *ldID})
455 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400456 }
457 }
458 log.Debug("deleting-logical-port-ends")
459 return nil
460}
461
khenaidoofc1314d2019-03-14 09:34:21 -0400462func (ldMgr *LogicalDeviceManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400463 log.Debugw("setupUNILogicalPorts", log.Fields{"childDeviceId": childDevice.Id, "parentDeviceId": childDevice.ParentId, "current-data": childDevice})
khenaidoob9203542018-09-17 22:56:37 -0400464 // Sanity check
465 if childDevice.Root {
466 return errors.New("Device-root")
467 }
468
469 // Get the logical device id parent device
npujar1d86a522019-11-14 17:11:16 +0530470 parentID := childDevice.ParentId
npujar467fe752020-01-16 20:17:45 +0530471 logDeviceID := ldMgr.deviceMgr.GetParentDeviceID(ctx, parentID)
khenaidoob9203542018-09-17 22:56:37 -0400472
npujar1d86a522019-11-14 17:11:16 +0530473 log.Debugw("setupUNILogicalPorts", log.Fields{"logDeviceId": logDeviceID, "parentId": parentID})
khenaidoob9203542018-09-17 22:56:37 -0400474
npujar1d86a522019-11-14 17:11:16 +0530475 if parentID == "" || logDeviceID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400476 return errors.New("device-in-invalid-state")
khenaidoo5e677ae2019-02-28 17:26:29 -0500477 }
478
npujar467fe752020-01-16 20:17:45 +0530479 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400480 if err := agent.setupUNILogicalPorts(ctx, childDevice); err != nil {
khenaidoobcf205b2019-01-25 22:21:14 -0500481 return err
482 }
khenaidoob9203542018-09-17 22:56:37 -0400483 }
khenaidoo21d51152019-02-01 13:48:37 -0500484 return nil
khenaidoob9203542018-09-17 22:56:37 -0400485}
khenaidoo19d7b632018-10-30 10:49:50 -0400486
npujar467fe752020-01-16 20:17:45 +0530487func (ldMgr *LogicalDeviceManager) deleteAllLogicalPorts(ctx context.Context, device *voltha.Device) error {
khenaidoo0a822f92019-05-08 15:15:57 -0400488 log.Debugw("deleteAllLogicalPorts", log.Fields{"deviceId": device.Id})
489
npujar1d86a522019-11-14 17:11:16 +0530490 var ldID *string
khenaidoo0a822f92019-05-08 15:15:57 -0400491 var err error
492 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530493 if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400494 log.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
495 return err
496 }
npujar467fe752020-01-16 20:17:45 +0530497 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
Girish Gowdra408cd962020-03-11 14:31:31 -0700498 if err := agent.deleteAllLogicalPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400499 return err
500 }
501 }
502 return nil
503}
Hardik Windlassc704def2020-02-26 18:23:19 +0000504
505func (ldMgr *LogicalDeviceManager) deleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
506 log.Debugw("delete-all-uni-logical-ports", log.Fields{"parent-device-id": parentDevice.Id})
507
508 var ldID *string
509 var err error
510 //Get the logical device Id for this device
511 if ldID, err = ldMgr.getLogicalDeviceID(ctx, parentDevice); err != nil {
512 return err
513 }
514 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
515 if err := agent.deleteAllUNILogicalPorts(ctx, parentDevice); err != nil {
516 return err
517 }
518 }
519 return nil
520}
521
npujar467fe752020-01-16 20:17:45 +0530522func (ldMgr *LogicalDeviceManager) updatePortState(ctx context.Context, deviceID string, portNo uint32, state voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530523 log.Debugw("updatePortState", log.Fields{"deviceId": deviceID, "state": state, "portNo": portNo})
khenaidoo171b98e2019-10-31 11:48:15 -0400524
npujar1d86a522019-11-14 17:11:16 +0530525 var ldID *string
khenaidoo171b98e2019-10-31 11:48:15 -0400526 var err error
527 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530528 if ldID, err = ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530529 log.Warnw("no-logical-device-found", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400530 return err
531 }
npujar467fe752020-01-16 20:17:45 +0530532 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
533 if err := agent.updatePortState(ctx, deviceID, portNo, state); err != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400534 return err
535 }
536 }
537 return nil
538}
khenaidoo0a822f92019-05-08 15:15:57 -0400539
kesavandbc2d1622020-01-21 00:42:01 -0500540func (ldMgr *LogicalDeviceManager) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400541 log.Debugw("updatePortsState", log.Fields{"deviceId": device.Id, "state": state, "current-data": device})
khenaidoo3ab34882019-05-02 21:33:30 -0400542
npujar1d86a522019-11-14 17:11:16 +0530543 var ldID *string
khenaidoo3ab34882019-05-02 21:33:30 -0400544 var err error
545 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530546 if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400547 log.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
548 return err
549 }
npujar467fe752020-01-16 20:17:45 +0530550 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
551 if err := agent.updatePortsState(ctx, device, state); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400552 return err
553 }
554 }
555 return nil
556}
557
khenaidoo19d7b632018-10-30 10:49:50 -0400558func (ldMgr *LogicalDeviceManager) updateFlowTable(ctx context.Context, id string, flow *openflow_13.OfpFlowMod, ch chan interface{}) {
559 log.Debugw("updateFlowTable", log.Fields{"logicalDeviceId": id})
560 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530561 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400562 res = agent.updateFlowTable(ctx, flow)
563 log.Debugw("updateFlowTable-result", log.Fields{"result": res})
564 } else {
565 res = status.Errorf(codes.NotFound, "%s", id)
566 }
567 sendAPIResponse(ctx, ch, res)
568}
569
Manikkaraj kb1a10922019-07-29 12:10:34 -0400570func (ldMgr *LogicalDeviceManager) updateMeterTable(ctx context.Context, id string, meter *openflow_13.OfpMeterMod, ch chan interface{}) {
571 log.Debugw("updateMeterTable", log.Fields{"logicalDeviceId": id})
572 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530573 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400574 res = agent.updateMeterTable(ctx, meter)
575 log.Debugw("updateMeterTable-result", log.Fields{"result": res})
576 } else {
577 res = status.Errorf(codes.NotFound, "%s", id)
578 }
579 sendAPIResponse(ctx, ch, res)
580}
581
npujar1d86a522019-11-14 17:11:16 +0530582// ListLogicalDeviceMeters returns logical device meters
Manikkaraj kb1a10922019-07-29 12:10:34 -0400583func (ldMgr *LogicalDeviceManager) ListLogicalDeviceMeters(ctx context.Context, id string) (*openflow_13.Meters, error) {
584 log.Debugw("ListLogicalDeviceMeters", log.Fields{"logicalDeviceId": id})
npujar467fe752020-01-16 20:17:45 +0530585 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400586 return agent.ListLogicalDeviceMeters(ctx)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400587 }
588 return nil, status.Errorf(codes.NotFound, "%s", id)
589}
khenaidoo19d7b632018-10-30 10:49:50 -0400590func (ldMgr *LogicalDeviceManager) updateGroupTable(ctx context.Context, id string, groupMod *openflow_13.OfpGroupMod, ch chan interface{}) {
591 log.Debugw("updateGroupTable", log.Fields{"logicalDeviceId": id})
592 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530593 if agent := ldMgr.getLogicalDeviceAgent(ctx, id); agent != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400594 res = agent.updateGroupTable(ctx, groupMod)
595 log.Debugw("updateGroupTable-result", log.Fields{"result": res})
596 } else {
597 res = status.Errorf(codes.NotFound, "%s", id)
598 }
599 sendAPIResponse(ctx, ch, res)
600}
601
602func (ldMgr *LogicalDeviceManager) enableLogicalPort(ctx context.Context, id *voltha.LogicalPortId, ch chan interface{}) {
603 log.Debugw("enableLogicalPort", log.Fields{"logicalDeviceId": id})
604 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530605 if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
606 res = agent.enableLogicalPort(ctx, id.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400607 log.Debugw("enableLogicalPort-result", log.Fields{"result": res})
608 } else {
609 res = status.Errorf(codes.NotFound, "%s", id.Id)
610 }
611 sendAPIResponse(ctx, ch, res)
612}
613
614func (ldMgr *LogicalDeviceManager) disableLogicalPort(ctx context.Context, id *voltha.LogicalPortId, ch chan interface{}) {
615 log.Debugw("disableLogicalPort", log.Fields{"logicalDeviceId": id})
616 var res interface{}
npujar467fe752020-01-16 20:17:45 +0530617 if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
618 res = agent.disableLogicalPort(ctx, id.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400619 log.Debugw("disableLogicalPort-result", log.Fields{"result": res})
620 } else {
621 res = status.Errorf(codes.NotFound, "%s", id.Id)
622 }
623 sendAPIResponse(ctx, ch, res)
624}
khenaidoofdbad6e2018-11-06 22:26:38 -0500625
npujar467fe752020-01-16 20:17:45 +0530626func (ldMgr *LogicalDeviceManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, transactionID string, packet []byte) error {
npujar1d86a522019-11-14 17:11:16 +0530627 log.Debugw("packetIn", log.Fields{"logicalDeviceId": logicalDeviceID, "port": port})
npujar467fe752020-01-16 20:17:45 +0530628 if agent := ldMgr.getLogicalDeviceAgent(ctx, logicalDeviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +0530629 agent.packetIn(port, transactionID, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500630 } else {
npujar1d86a522019-11-14 17:11:16 +0530631 log.Error("logical-device-not-exist", log.Fields{"logicalDeviceId": logicalDeviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -0500632 }
633 return nil
634}