blob: d6ca4ce9d0cd58a64ac14ef160529785444c27e7 [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
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoob9203542018-09-17 22:56:37 -040018
19import (
20 "context"
21 "errors"
Kent Hagerman45a13e42020-04-13 12:23:50 -040022 "io"
David Bainbridged1afd662020-03-26 18:27:41 -070023 "strings"
24 "sync"
25 "time"
26
Kent Hagerman433a31a2020-05-20 19:04:48 -040027 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050028 "github.com/opencord/voltha-go/db/model"
Kent Hagerman433a31a2020-05-20 19:04:48 -040029 "github.com/opencord/voltha-go/rw_core/core/device/event"
30 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080031 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040035 "google.golang.org/grpc/codes"
36 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040037)
38
Kent Hagerman2b216042020-04-03 18:28:56 -040039// LogicalManager represent logical device manager attributes
40type LogicalManager struct {
Kent Hagerman45a13e42020-04-13 12:23:50 -040041 *event.Manager
khenaidoo4c9e5592019-09-09 16:20:41 -040042 logicalDeviceAgents sync.Map
Kent Hagerman2b216042020-04-03 18:28:56 -040043 deviceMgr *Manager
npujar467fe752020-01-16 20:17:45 +053044 kafkaICProxy kafka.InterContainerProxy
Mahir Gunyel03de0d32020-06-03 01:36:59 -070045 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040046 ldProxy *model.Proxy
khenaidoo442e7c72020-03-10 16:13:48 -040047 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040048 logicalDevicesLoadingLock sync.RWMutex
49 logicalDeviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040050}
51
Kent Hagerman2b216042020-04-03 18:28:56 -040052func (ldMgr *LogicalManager) addLogicalDeviceAgentToMap(agent *LogicalAgent) {
npujar1d86a522019-11-14 17:11:16 +053053 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceID); !exist {
54 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040055 }
56}
57
khenaidoo8c3303d2019-02-13 14:59:39 -050058// getLogicalDeviceAgent returns the logical device agent. If the device is not in memory then the device will
59// be loaded from dB and a logical device agent created to managed it.
Kent Hagerman2b216042020-04-03 18:28:56 -040060func (ldMgr *LogicalManager) getLogicalDeviceAgent(ctx context.Context, logicalDeviceID string) *LogicalAgent {
Andrea Campanella09400bd2020-04-02 11:58:04 +020061 logger.Debugw("get-logical-device-agent", log.Fields{"logical-device-id": logicalDeviceID})
npujar1d86a522019-11-14 17:11:16 +053062 agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceID)
63 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -040064 lda := agent.(*LogicalAgent)
khenaidoo93d5a3d2020-01-15 12:37:05 -050065 if lda.logicalDevice == nil {
66 // This can happen when an agent for the logical device has been created but the logical device
67 // itself is not ready for action as it is waiting for switch and port capabilities from the
68 // relevant adapter. In such a case prevent any request aimed at that logical device.
Girish Kumarf56a4682020-03-20 20:07:46 +000069 logger.Debugf("Logical device %s is not ready to serve requests", logicalDeviceID)
khenaidoo93d5a3d2020-01-15 12:37:05 -050070 return nil
71 }
72 return lda
npujar1d86a522019-11-14 17:11:16 +053073 }
74 // Try to load into memory - loading will also create the logical device agent
npujar467fe752020-01-16 20:17:45 +053075 if err := ldMgr.load(ctx, logicalDeviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +053076 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -040077 return agent.(*LogicalAgent)
khenaidoo8c3303d2019-02-13 14:59:39 -050078 }
khenaidoob9203542018-09-17 22:56:37 -040079 }
80 return nil
81}
82
Kent Hagerman2b216042020-04-03 18:28:56 -040083func (ldMgr *LogicalManager) deleteLogicalDeviceAgent(logicalDeviceID string) {
npujar1d86a522019-11-14 17:11:16 +053084 ldMgr.logicalDeviceAgents.Delete(logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -040085}
86
khenaidoo8c3303d2019-02-13 14:59:39 -050087// GetLogicalDevice provides a cloned most up to date logical device. If device is not in memory
88// it will be fetched from the dB
Kent Hagerman45a13e42020-04-13 12:23:50 -040089func (ldMgr *LogicalManager) GetLogicalDevice(ctx context.Context, id *voltha.ID) (*voltha.LogicalDevice, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +000090 logger.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
Kent Hagerman45a13e42020-04-13 12:23:50 -040091 if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -040092 return agent.GetLogicalDevice(ctx)
khenaidoob9203542018-09-17 22:56:37 -040093 }
94 return nil, status.Errorf(codes.NotFound, "%s", id)
95}
96
Kent Hagerman2b216042020-04-03 18:28:56 -040097//ListLogicalDevices returns the list of all logical devices
Kent Hagerman45a13e42020-04-13 12:23:50 -040098func (ldMgr *LogicalManager) ListLogicalDevices(ctx context.Context, _ *empty.Empty) (*voltha.LogicalDevices, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +000099 logger.Debug("ListAllLogicalDevices")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400100
101 var logicalDevices []*voltha.LogicalDevice
Kent Hagermanf5a67352020-04-30 15:15:26 -0400102 if err := ldMgr.ldProxy.List(ctx, &logicalDevices); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000103 logger.Errorw("failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530104 return nil, err
105 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400106 return &voltha.LogicalDevices{Items: logicalDevices}, nil
khenaidoob9203542018-09-17 22:56:37 -0400107}
108
Kent Hagerman2b216042020-04-03 18:28:56 -0400109func (ldMgr *LogicalManager) createLogicalDevice(ctx context.Context, device *voltha.Device) (*string, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000110 logger.Debugw("creating-logical-device", log.Fields{"deviceId": device.Id})
khenaidoob9203542018-09-17 22:56:37 -0400111 // Sanity check
112 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400113 return nil, errors.New("device-not-root")
khenaidoob9203542018-09-17 22:56:37 -0400114 }
115
116 // Create a logical device agent - the logical device Id is based on the mac address of the device
117 // For now use the serial number - it may contain any combination of alphabetic characters and numbers,
118 // with length varying from eight characters to a maximum of 14 characters. Mac Address is part of oneof
119 // in the Device model. May need to be moved out.
Kent Hagerman2b216042020-04-03 18:28:56 -0400120 id := utils.CreateLogicalDeviceID()
David Bainbridged1afd662020-03-26 18:27:41 -0700121 sn := strings.Replace(device.MacAddress, ":", "", -1)
khenaidoo92e62c52018-10-03 14:02:54 -0400122 if id == "" {
David Bainbridged1afd662020-03-26 18:27:41 -0700123 logger.Errorw("mac-address-not-set", log.Fields{"deviceId": device.Id, "serial-number": sn})
khenaidoo92e62c52018-10-03 14:02:54 -0400124 return nil, errors.New("mac-address-not-set")
125 }
David Bainbridged1afd662020-03-26 18:27:41 -0700126
Girish Kumarf56a4682020-03-20 20:07:46 +0000127 logger.Debugw("logical-device-id", log.Fields{"logicaldeviceId": id})
khenaidoob9203542018-09-17 22:56:37 -0400128
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700129 agent := newLogicalAgent(id, sn, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400130 ldMgr.addLogicalDeviceAgentToMap(agent)
khenaidooad06fd72019-10-28 12:26:05 -0400131
132 // Update the root device with the logical device Id reference
npujar467fe752020-01-16 20:17:45 +0530133 if err := ldMgr.deviceMgr.setParentID(ctx, device, id); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000134 logger.Errorw("failed-setting-parent-id", log.Fields{"logicalDeviceId": id, "deviceId": device.Id})
khenaidooad06fd72019-10-28 12:26:05 -0400135 return nil, err
136 }
137
npujar1d86a522019-11-14 17:11:16 +0530138 go func() {
Kent Hagermanf5a67352020-04-30 15:15:26 -0400139 //TODO: either wait for the agent to be started before returning, or
140 // implement locks in the agent to ensure request are not processed before start() is complete
khenaidoo442e7c72020-03-10 16:13:48 -0400141 err := agent.start(context.Background(), false)
npujar1d86a522019-11-14 17:11:16 +0530142 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000143 logger.Errorw("unable-to-create-the-logical-device", log.Fields{"error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400144 ldMgr.deleteLogicalDeviceAgent(id)
npujar1d86a522019-11-14 17:11:16 +0530145 }
146 }()
khenaidoob9203542018-09-17 22:56:37 -0400147
Girish Kumarf56a4682020-03-20 20:07:46 +0000148 logger.Debug("creating-logical-device-ends")
khenaidoob9203542018-09-17 22:56:37 -0400149 return &id, nil
150}
151
khenaidoo6d62c002019-05-15 21:57:03 -0400152// stopManagingLogicalDeviceWithDeviceId stops the management of the logical device. This implies removal of any
153// reference of this logical device in cache. The device Id is passed as param because the logical device may already
154// have been removed from the model. This function returns the logical device Id if found
Kent Hagerman2b216042020-04-03 18:28:56 -0400155func (ldMgr *LogicalManager) stopManagingLogicalDeviceWithDeviceID(ctx context.Context, id string) string {
Girish Kumarf56a4682020-03-20 20:07:46 +0000156 logger.Infow("stop-managing-logical-device", log.Fields{"deviceId": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400157 // Go over the list of logical device agents to find the one which has rootDeviceId as id
npujar1d86a522019-11-14 17:11:16 +0530158 var ldID = ""
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400159 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
Kent Hagerman2b216042020-04-03 18:28:56 -0400160 ldAgent := value.(*LogicalAgent)
npujar1d86a522019-11-14 17:11:16 +0530161 if ldAgent.rootDeviceID == id {
Girish Kumarf56a4682020-03-20 20:07:46 +0000162 logger.Infow("stopping-logical-device-agent", log.Fields{"lDeviceId": key})
npujar467fe752020-01-16 20:17:45 +0530163 if err := ldAgent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000164 logger.Errorw("failed-to-stop-LDAgent", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530165 return false
166 }
npujar1d86a522019-11-14 17:11:16 +0530167 ldID = key.(string)
168 ldMgr.logicalDeviceAgents.Delete(ldID)
khenaidoo6d62c002019-05-15 21:57:03 -0400169 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400170 return true
171 })
npujar1d86a522019-11-14 17:11:16 +0530172 return ldID
khenaidoo6d62c002019-05-15 21:57:03 -0400173}
174
175//getLogicalDeviceFromModel retrieves the logical device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400176func (ldMgr *LogicalManager) getLogicalDeviceFromModel(ctx context.Context, lDeviceID string) (*voltha.LogicalDevice, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400177 logicalDevice := &voltha.LogicalDevice{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400178 if have, err := ldMgr.ldProxy.Get(ctx, lDeviceID, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000179 logger.Errorw("failed-to-get-logical-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530180 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400181 } else if !have {
182 return nil, status.Error(codes.NotFound, lDeviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530183 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400184
185 return logicalDevice, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400186}
187
khenaidoo297cd252019-02-07 22:10:23 -0500188// load loads a logical device manager in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400189func (ldMgr *LogicalManager) load(ctx context.Context, lDeviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530190 if lDeviceID == "" {
khenaidoo4c9e5592019-09-09 16:20:41 -0400191 return nil
khenaidoo297cd252019-02-07 22:10:23 -0500192 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400193 // Add a lock to prevent two concurrent calls from loading the same device twice
194 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530195 if _, exist := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; !exist {
196 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
197 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400198 ldMgr.logicalDevicesLoadingLock.Unlock()
npujar467fe752020-01-16 20:17:45 +0530199 if _, err := ldMgr.getLogicalDeviceFromModel(ctx, lDeviceID); err == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000200 logger.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceID})
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700201 agent := newLogicalAgent(lDeviceID, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530202 if err := agent.start(ctx, true); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400203 return err
khenaidoo4c9e5592019-09-09 16:20:41 -0400204 }
khenaidoo442e7c72020-03-10 16:13:48 -0400205 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoo4c9e5592019-09-09 16:20:41 -0400206 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000207 logger.Debugw("logicalDevice not in model", log.Fields{"lDeviceId": lDeviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400208 }
209 // announce completion of task to any number of waiting channels
210 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530211 if v, ok := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400212 for _, ch := range v {
213 close(ch)
214 }
npujar1d86a522019-11-14 17:11:16 +0530215 delete(ldMgr.logicalDeviceLoadingInProgress, lDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400216 }
217 ldMgr.logicalDevicesLoadingLock.Unlock()
218 } else {
219 ldMgr.logicalDevicesLoadingLock.Unlock()
220 }
221 } else {
222 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530223 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = append(ldMgr.logicalDeviceLoadingInProgress[lDeviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400224 ldMgr.logicalDevicesLoadingLock.Unlock()
225 // Wait for the channel to be closed, implying the process loading this device is done.
226 <-ch
227 }
npujar1d86a522019-11-14 17:11:16 +0530228 if _, exist := ldMgr.logicalDeviceAgents.Load(lDeviceID); exist {
khenaidoo4c9e5592019-09-09 16:20:41 -0400229 return nil
230 }
npujar1d86a522019-11-14 17:11:16 +0530231 return status.Errorf(codes.Aborted, "Error loading logical device %s", lDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500232}
233
Kent Hagerman2b216042020-04-03 18:28:56 -0400234func (ldMgr *LogicalManager) deleteLogicalDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000235 logger.Debugw("deleting-logical-device", log.Fields{"deviceId": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400236 // Sanity check
237 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400238 return errors.New("device-not-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400239 }
npujar1d86a522019-11-14 17:11:16 +0530240 logDeviceID := device.ParentId
npujar467fe752020-01-16 20:17:45 +0530241 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400242 // Stop the logical device agent
Thomas Lee Se5a44012019-11-07 20:32:24 +0530243 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Errorw("failed-to-stop-agent", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530245 return err
246 }
khenaidoo92e62c52018-10-03 14:02:54 -0400247 //Remove the logical device agent from the Map
npujar1d86a522019-11-14 17:11:16 +0530248 ldMgr.deleteLogicalDeviceAgent(logDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400249 }
250
Girish Kumarf56a4682020-03-20 20:07:46 +0000251 logger.Debug("deleting-logical-device-ends")
khenaidoo92e62c52018-10-03 14:02:54 -0400252 return nil
253}
254
Kent Hagerman2b216042020-04-03 18:28:56 -0400255func (ldMgr *LogicalManager) getLogicalDeviceID(ctx context.Context, device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400256 // Device can either be a parent or a child device
257 if device.Root {
258 // Parent device. The ID of a parent device is the logical device ID
259 return &device.ParentId, nil
260 }
261 // Device is child device
262 // retrieve parent device using child device ID
npujar467fe752020-01-16 20:17:45 +0530263 if parentDevice := ldMgr.deviceMgr.getParentDevice(ctx, device); parentDevice != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400264 return &parentDevice.ParentId, nil
265 }
266 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
267}
268
Kent Hagerman2b216042020-04-03 18:28:56 -0400269func (ldMgr *LogicalManager) getLogicalDeviceIDFromDeviceID(ctx context.Context, deviceID string) (*string, error) {
khenaidoo3ab34882019-05-02 21:33:30 -0400270 // Get the device
271 var device *voltha.Device
272 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400273 if device, err = ldMgr.deviceMgr.getDevice(ctx, deviceID); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400274 return nil, err
275 }
npujar467fe752020-01-16 20:17:45 +0530276 return ldMgr.getLogicalDeviceID(ctx, device)
khenaidoo3ab34882019-05-02 21:33:30 -0400277}
278
Kent Hagerman2b216042020-04-03 18:28:56 -0400279func (ldMgr *LogicalManager) getLogicalPortID(ctx context.Context, device *voltha.Device) (*voltha.LogicalPortId, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400280 // Get the logical device where this device is attached
npujar1d86a522019-11-14 17:11:16 +0530281 var lDeviceID *string
khenaidoo19d7b632018-10-30 10:49:50 -0400282 var err error
npujar467fe752020-01-16 20:17:45 +0530283 if lDeviceID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400284 return nil, err
285 }
286 var lDevice *voltha.LogicalDevice
Kent Hagerman45a13e42020-04-13 12:23:50 -0400287 if lDevice, err = ldMgr.GetLogicalDevice(ctx, &voltha.ID{Id: *lDeviceID}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400288 return nil, err
289 }
290 // Go over list of ports
291 for _, port := range lDevice.Ports {
292 if port.DeviceId == device.Id {
npujar1d86a522019-11-14 17:11:16 +0530293 return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400294 }
295 }
296 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
297}
298
npujar1d86a522019-11-14 17:11:16 +0530299// ListLogicalDeviceFlows returns the flows of logical device
Kent Hagerman45a13e42020-04-13 12:23:50 -0400300func (ldMgr *LogicalManager) ListLogicalDeviceFlows(ctx context.Context, id *voltha.ID) (*openflow_13.Flows, error) {
301 logger.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id.Id})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400302 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
303 if agent == nil {
304 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoodd237172019-05-27 16:37:17 -0400305 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400306
307 flows := agent.listLogicalDeviceFlows()
308 ctr, ret := 0, make([]*openflow_13.OfpFlowStats, len(flows))
309 for _, flow := range flows {
310 ret[ctr] = flow
311 ctr++
312 }
313 return &openflow_13.Flows{Items: ret}, nil
khenaidoodd237172019-05-27 16:37:17 -0400314}
315
npujar1d86a522019-11-14 17:11:16 +0530316// ListLogicalDeviceFlowGroups returns logical device flow groups
Kent Hagerman45a13e42020-04-13 12:23:50 -0400317func (ldMgr *LogicalManager) ListLogicalDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*openflow_13.FlowGroups, error) {
318 logger.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id.Id})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400319 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
320 if agent == nil {
321 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoodd237172019-05-27 16:37:17 -0400322 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400323
324 groups := agent.listLogicalDeviceGroups()
325 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
326 for _, group := range groups {
327 ret[ctr] = group
328 ctr++
329 }
330 return &openflow_13.FlowGroups{Items: ret}, nil
khenaidoodd237172019-05-27 16:37:17 -0400331}
332
npujar1d86a522019-11-14 17:11:16 +0530333// ListLogicalDevicePorts returns logical device ports
Kent Hagerman45a13e42020-04-13 12:23:50 -0400334func (ldMgr *LogicalManager) ListLogicalDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.LogicalPorts, error) {
335 logger.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id.Id})
336 if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400337 return agent.ListLogicalDevicePorts(ctx)
khenaidoo19d7b632018-10-30 10:49:50 -0400338 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400339 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400340}
341
Kent Hagerman45a13e42020-04-13 12:23:50 -0400342// GetLogicalDevicePort returns logical device port details
343func (ldMgr *LogicalManager) GetLogicalDevicePort(ctx context.Context, lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
khenaidoo19d7b632018-10-30 10:49:50 -0400344 // Get the logical device where this device is attached
345 var err error
346 var lDevice *voltha.LogicalDevice
Kent Hagerman45a13e42020-04-13 12:23:50 -0400347 if lDevice, err = ldMgr.GetLogicalDevice(ctx, &voltha.ID{Id: lPortID.Id}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400348 return nil, err
349 }
350 // Go over list of ports
351 for _, port := range lDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +0530352 if port.Id == lPortID.PortId {
khenaidoo19d7b632018-10-30 10:49:50 -0400353 return port, nil
354 }
355 }
npujar1d86a522019-11-14 17:11:16 +0530356 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400357}
358
khenaidoo2c6a0992019-04-29 13:46:56 -0400359// updateLogicalPort sets up a logical port on the logical device based on the device port
360// information, if needed
Kent Hagerman2b216042020-04-03 18:28:56 -0400361func (ldMgr *LogicalManager) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530362 ldID, err := ldMgr.getLogicalDeviceID(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530363 if err != nil || *ldID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400364 // This is not an error as the logical device may not have been created at this time. In such a case,
365 // the ports will be created when the logical device is ready.
366 return nil
khenaidoo2c6a0992019-04-29 13:46:56 -0400367 }
npujar467fe752020-01-16 20:17:45 +0530368 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
369 if err := agent.updateLogicalPort(ctx, device, port); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530370 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400371 }
372 }
373 return nil
374}
375
khenaidoo0a822f92019-05-08 15:15:57 -0400376// deleteLogicalPort removes the logical port associated with a device
Kent Hagerman2b216042020-04-03 18:28:56 -0400377func (ldMgr *LogicalManager) deleteLogicalPort(ctx context.Context, lPortID *voltha.LogicalPortId) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000378 logger.Debugw("deleting-logical-port", log.Fields{"LDeviceId": lPortID.Id})
khenaidoo19d7b632018-10-30 10:49:50 -0400379 // Get logical port
380 var logicalPort *voltha.LogicalPort
381 var err error
Kent Hagerman45a13e42020-04-13 12:23:50 -0400382 if logicalPort, err = ldMgr.GetLogicalDevicePort(ctx, lPortID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000383 logger.Debugw("no-logical-device-port-present", log.Fields{"logicalPortId": lPortID.PortId})
khenaidoo19d7b632018-10-30 10:49:50 -0400384 return err
385 }
khenaidoo92e62c52018-10-03 14:02:54 -0400386 // Sanity check
khenaidoo19d7b632018-10-30 10:49:50 -0400387 if logicalPort.RootPort {
khenaidoo2c6a0992019-04-29 13:46:56 -0400388 return errors.New("device-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400389 }
npujar467fe752020-01-16 20:17:45 +0530390 if agent := ldMgr.getLogicalDeviceAgent(ctx, lPortID.Id); agent != nil {
391 if err := agent.deleteLogicalPort(ctx, logicalPort); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000392 logger.Warnw("deleting-logicalport-failed", log.Fields{"LDeviceId": lPortID.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400393 }
khenaidoo92e62c52018-10-03 14:02:54 -0400394 }
395
Girish Kumarf56a4682020-03-20 20:07:46 +0000396 logger.Debug("deleting-logical-port-ends")
khenaidoo92e62c52018-10-03 14:02:54 -0400397 return nil
398}
399
khenaidoo0a822f92019-05-08 15:15:57 -0400400// deleteLogicalPort removes the logical port associated with a child device
Kent Hagerman2b216042020-04-03 18:28:56 -0400401func (ldMgr *LogicalManager) deleteLogicalPorts(ctx context.Context, deviceID string) error {
Andrea Campanella09400bd2020-04-02 11:58:04 +0200402 logger.Debugw("deleting-logical-ports", log.Fields{"device-id": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400403 // Get logical port
npujar467fe752020-01-16 20:17:45 +0530404 ldID, err := ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530405 if err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400406 return err
npujar1d86a522019-11-14 17:11:16 +0530407 }
npujar467fe752020-01-16 20:17:45 +0530408 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
409 if err = agent.deleteLogicalPorts(ctx, deviceID); err != nil {
Andrea Campanella09400bd2020-04-02 11:58:04 +0200410 logger.Warnw("delete-logical-ports-failed", log.Fields{"logical-device-id": *ldID})
npujar1d86a522019-11-14 17:11:16 +0530411 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400412 }
413 }
Andrea Campanella09400bd2020-04-02 11:58:04 +0200414 logger.Debug("deleting-logical-ports-ends")
khenaidoo0a822f92019-05-08 15:15:57 -0400415 return nil
416}
417
Kent Hagerman2b216042020-04-03 18:28:56 -0400418func (ldMgr *LogicalManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000419 logger.Debugw("setupUNILogicalPorts", log.Fields{"childDeviceId": childDevice.Id, "parentDeviceId": childDevice.ParentId, "current-data": childDevice})
khenaidoob9203542018-09-17 22:56:37 -0400420 // Sanity check
421 if childDevice.Root {
422 return errors.New("Device-root")
423 }
424
425 // Get the logical device id parent device
npujar1d86a522019-11-14 17:11:16 +0530426 parentID := childDevice.ParentId
npujar467fe752020-01-16 20:17:45 +0530427 logDeviceID := ldMgr.deviceMgr.GetParentDeviceID(ctx, parentID)
khenaidoob9203542018-09-17 22:56:37 -0400428
Girish Kumarf56a4682020-03-20 20:07:46 +0000429 logger.Debugw("setupUNILogicalPorts", log.Fields{"logDeviceId": logDeviceID, "parentId": parentID})
khenaidoob9203542018-09-17 22:56:37 -0400430
npujar1d86a522019-11-14 17:11:16 +0530431 if parentID == "" || logDeviceID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400432 return errors.New("device-in-invalid-state")
khenaidoo5e677ae2019-02-28 17:26:29 -0500433 }
434
npujar467fe752020-01-16 20:17:45 +0530435 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400436 if err := agent.setupUNILogicalPorts(ctx, childDevice); err != nil {
khenaidoobcf205b2019-01-25 22:21:14 -0500437 return err
438 }
khenaidoob9203542018-09-17 22:56:37 -0400439 }
khenaidoo21d51152019-02-01 13:48:37 -0500440 return nil
khenaidoob9203542018-09-17 22:56:37 -0400441}
khenaidoo19d7b632018-10-30 10:49:50 -0400442
Kent Hagerman2b216042020-04-03 18:28:56 -0400443func (ldMgr *LogicalManager) deleteAllLogicalPorts(ctx context.Context, device *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000444 logger.Debugw("deleteAllLogicalPorts", log.Fields{"deviceId": device.Id})
khenaidoo0a822f92019-05-08 15:15:57 -0400445
npujar1d86a522019-11-14 17:11:16 +0530446 var ldID *string
khenaidoo0a822f92019-05-08 15:15:57 -0400447 var err error
448 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530449 if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000450 logger.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400451 return err
452 }
npujar467fe752020-01-16 20:17:45 +0530453 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
Girish Gowdra408cd962020-03-11 14:31:31 -0700454 if err := agent.deleteAllLogicalPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400455 return err
456 }
457 }
458 return nil
459}
Hardik Windlassc704def2020-02-26 18:23:19 +0000460
Kent Hagerman2b216042020-04-03 18:28:56 -0400461func (ldMgr *LogicalManager) updatePortState(ctx context.Context, deviceID string, portNo uint32, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000462 logger.Debugw("updatePortState", log.Fields{"deviceId": deviceID, "state": state, "portNo": portNo})
khenaidoo171b98e2019-10-31 11:48:15 -0400463
npujar1d86a522019-11-14 17:11:16 +0530464 var ldID *string
khenaidoo171b98e2019-10-31 11:48:15 -0400465 var err error
466 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530467 if ldID, err = ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000468 logger.Warnw("no-logical-device-found", log.Fields{"deviceId": deviceID, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400469 return err
470 }
npujar467fe752020-01-16 20:17:45 +0530471 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
472 if err := agent.updatePortState(ctx, deviceID, portNo, state); err != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400473 return err
474 }
475 }
476 return nil
477}
khenaidoo0a822f92019-05-08 15:15:57 -0400478
Kent Hagerman2b216042020-04-03 18:28:56 -0400479func (ldMgr *LogicalManager) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000480 logger.Debugw("updatePortsState", log.Fields{"deviceId": device.Id, "state": state, "current-data": device})
khenaidoo3ab34882019-05-02 21:33:30 -0400481
npujar1d86a522019-11-14 17:11:16 +0530482 var ldID *string
khenaidoo3ab34882019-05-02 21:33:30 -0400483 var err error
484 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530485 if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000486 logger.Warnw("no-logical-device-found", log.Fields{"deviceId": device.Id, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400487 return err
488 }
npujar467fe752020-01-16 20:17:45 +0530489 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
490 if err := agent.updatePortsState(ctx, device, state); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400491 return err
492 }
493 }
494 return nil
495}
496
Kent Hagerman45a13e42020-04-13 12:23:50 -0400497// UpdateLogicalDeviceFlowTable updates logical device flow table
498func (ldMgr *LogicalManager) UpdateLogicalDeviceFlowTable(ctx context.Context, flow *openflow_13.FlowTableUpdate) (*empty.Empty, error) {
499 logger.Debugw("UpdateLogicalDeviceFlowTable", log.Fields{"logicalDeviceId": flow.Id})
500 agent := ldMgr.getLogicalDeviceAgent(ctx, flow.Id)
501 if agent == nil {
502 return nil, status.Errorf(codes.NotFound, "%s", flow.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400503 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400504 return &empty.Empty{}, agent.updateFlowTable(ctx, flow.FlowMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400505}
506
Kent Hagerman45a13e42020-04-13 12:23:50 -0400507// UpdateLogicalDeviceMeterTable - This function sends meter mod request to logical device manager and waits for response
508func (ldMgr *LogicalManager) UpdateLogicalDeviceMeterTable(ctx context.Context, meter *openflow_13.MeterModUpdate) (*empty.Empty, error) {
509 logger.Debugw("UpdateLogicalDeviceMeterTable", log.Fields{"logicalDeviceId": meter.Id})
510 agent := ldMgr.getLogicalDeviceAgent(ctx, meter.Id)
511 if agent == nil {
512 return nil, status.Errorf(codes.NotFound, "%s", meter.Id)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400513 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400514 return &empty.Empty{}, agent.updateMeterTable(ctx, meter.MeterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400515}
516
npujar1d86a522019-11-14 17:11:16 +0530517// ListLogicalDeviceMeters returns logical device meters
Kent Hagerman45a13e42020-04-13 12:23:50 -0400518func (ldMgr *LogicalManager) ListLogicalDeviceMeters(ctx context.Context, id *voltha.ID) (*openflow_13.Meters, error) {
519 logger.Debugw("ListLogicalDeviceMeters", log.Fields{"logicalDeviceId": id.Id})
520 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
521 if agent == nil {
522 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400523 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400524 meters := agent.listLogicalDeviceMeters()
525 ctr, ret := 0, make([]*openflow_13.OfpMeterEntry, len(meters))
526 for _, meter := range meters {
527 ret[ctr] = meter
528 ctr++
529 }
530 return &openflow_13.Meters{Items: ret}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400531}
532
Kent Hagerman45a13e42020-04-13 12:23:50 -0400533// UpdateLogicalDeviceFlowGroupTable updates logical device flow group table
534func (ldMgr *LogicalManager) UpdateLogicalDeviceFlowGroupTable(ctx context.Context, flow *openflow_13.FlowGroupTableUpdate) (*empty.Empty, error) {
535 logger.Debugw("UpdateGroupTable", log.Fields{"logicalDeviceId": flow.Id})
536 agent := ldMgr.getLogicalDeviceAgent(ctx, flow.Id)
537 if agent == nil {
538 return nil, status.Errorf(codes.NotFound, "%s", flow.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400539 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400540 return &empty.Empty{}, agent.updateGroupTable(ctx, flow.GroupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400541}
542
Kent Hagerman45a13e42020-04-13 12:23:50 -0400543// EnableLogicalDevicePort enables logical device port
544func (ldMgr *LogicalManager) EnableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
545 logger.Debugw("EnableLogicalDevicePort", log.Fields{"logicalDeviceId": id})
546 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
547 if agent == nil {
548 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400549 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400550 return &empty.Empty{}, agent.enableLogicalPort(ctx, id.PortId)
551}
552
553// DisableLogicalDevicePort disables logical device port
554func (ldMgr *LogicalManager) DisableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
555 logger.Debugw("DisableLogicalDevicePort", log.Fields{"logicalDeviceId": id})
556 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
557 if agent == nil {
558 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
559 }
560 return &empty.Empty{}, agent.disableLogicalPort(ctx, id.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400561}
khenaidoofdbad6e2018-11-06 22:26:38 -0500562
Kent Hagerman2b216042020-04-03 18:28:56 -0400563func (ldMgr *LogicalManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, transactionID string, packet []byte) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000564 logger.Debugw("packetIn", log.Fields{"logicalDeviceId": logicalDeviceID, "port": port})
npujar467fe752020-01-16 20:17:45 +0530565 if agent := ldMgr.getLogicalDeviceAgent(ctx, logicalDeviceID); agent != nil {
npujar1d86a522019-11-14 17:11:16 +0530566 agent.packetIn(port, transactionID, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500567 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000568 logger.Error("logical-device-not-exist", log.Fields{"logicalDeviceId": logicalDeviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -0500569 }
570 return nil
571}
Kent Hagerman2b216042020-04-03 18:28:56 -0400572
Kent Hagerman45a13e42020-04-13 12:23:50 -0400573// StreamPacketsOut sends packets to adapter
574func (ldMgr *LogicalManager) StreamPacketsOut(packets voltha.VolthaService_StreamPacketsOutServer) error {
575 logger.Debugw("StreamPacketsOut-request", log.Fields{"packets": packets})
576loop:
577 for {
578 select {
579 case <-packets.Context().Done():
580 logger.Infow("StreamPacketsOut-context-done", log.Fields{"packets": packets, "error": packets.Context().Err()})
581 break loop
582 default:
583 }
584
585 packet, err := packets.Recv()
586
587 if err == io.EOF {
588 logger.Debugw("Received-EOF", log.Fields{"packets": packets})
589 break loop
590 }
591
592 if err != nil {
593 logger.Errorw("Failed to receive packet out", log.Fields{"error": err})
594 continue
595 }
596
597 if agent := ldMgr.getLogicalDeviceAgent(packets.Context(), packet.Id); agent != nil {
598 agent.packetOut(packets.Context(), packet.PacketOut)
599 } else {
600 logger.Errorf("No logical device agent present", log.Fields{"logicalDeviceID": packet.Id})
601 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400602 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400603
604 logger.Debugw("StreamPacketsOut-request-done", log.Fields{"packets": packets})
605 return nil
Kent Hagerman2b216042020-04-03 18:28:56 -0400606}