blob: 5661fdde59f3623250043b8fb749dda1cea89934 [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"
Kent Hagermanfa9d6d42020-05-25 11:49:40 -040023 "strconv"
David Bainbridged1afd662020-03-26 18:27:41 -070024 "strings"
25 "sync"
26 "time"
27
Kent Hagerman433a31a2020-05-20 19:04:48 -040028 "github.com/golang/protobuf/ptypes/empty"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
Kent Hagerman433a31a2020-05-20 19:04:48 -040030 "github.com/opencord/voltha-go/rw_core/core/device/event"
31 "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080032 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080034 "github.com/opencord/voltha-protos/v3/go/openflow_13"
35 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040036 "google.golang.org/grpc/codes"
37 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040038)
39
Kent Hagerman2b216042020-04-03 18:28:56 -040040// LogicalManager represent logical device manager attributes
41type LogicalManager struct {
Kent Hagerman45a13e42020-04-13 12:23:50 -040042 *event.Manager
khenaidoo4c9e5592019-09-09 16:20:41 -040043 logicalDeviceAgents sync.Map
Kent Hagerman2b216042020-04-03 18:28:56 -040044 deviceMgr *Manager
npujar467fe752020-01-16 20:17:45 +053045 kafkaICProxy kafka.InterContainerProxy
Mahir Gunyel03de0d32020-06-03 01:36:59 -070046 dbPath *model.Path
Kent Hagermanf5a67352020-04-30 15:15:26 -040047 ldProxy *model.Proxy
khenaidoo442e7c72020-03-10 16:13:48 -040048 defaultTimeout time.Duration
khenaidoo4c9e5592019-09-09 16:20:41 -040049 logicalDevicesLoadingLock sync.RWMutex
50 logicalDeviceLoadingInProgress map[string][]chan int
khenaidoob9203542018-09-17 22:56:37 -040051}
52
Kent Hagerman2b216042020-04-03 18:28:56 -040053func (ldMgr *LogicalManager) addLogicalDeviceAgentToMap(agent *LogicalAgent) {
npujar1d86a522019-11-14 17:11:16 +053054 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceID); !exist {
55 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoob9203542018-09-17 22:56:37 -040056 }
57}
58
khenaidoo8c3303d2019-02-13 14:59:39 -050059// getLogicalDeviceAgent returns the logical device agent. If the device is not in memory then the device will
60// be loaded from dB and a logical device agent created to managed it.
Kent Hagerman2b216042020-04-03 18:28:56 -040061func (ldMgr *LogicalManager) getLogicalDeviceAgent(ctx context.Context, logicalDeviceID string) *LogicalAgent {
Rohan Agrawal31f21802020-06-12 05:38:46 +000062 logger.Debugw(ctx, "get-logical-device-agent", log.Fields{"logical-device-id": logicalDeviceID})
npujar1d86a522019-11-14 17:11:16 +053063 agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceID)
64 if ok {
Kent Hagerman2b216042020-04-03 18:28:56 -040065 lda := agent.(*LogicalAgent)
khenaidoo93d5a3d2020-01-15 12:37:05 -050066 if lda.logicalDevice == nil {
67 // This can happen when an agent for the logical device has been created but the logical device
68 // itself is not ready for action as it is waiting for switch and port capabilities from the
69 // relevant adapter. In such a case prevent any request aimed at that logical device.
Rohan Agrawal31f21802020-06-12 05:38:46 +000070 logger.Debugf(ctx, "Logical device %s is not ready to serve requests", logicalDeviceID)
khenaidoo93d5a3d2020-01-15 12:37:05 -050071 return nil
72 }
73 return lda
npujar1d86a522019-11-14 17:11:16 +053074 }
75 // Try to load into memory - loading will also create the logical device agent
npujar467fe752020-01-16 20:17:45 +053076 if err := ldMgr.load(ctx, logicalDeviceID); err == nil {
npujar1d86a522019-11-14 17:11:16 +053077 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceID); ok {
Kent Hagerman2b216042020-04-03 18:28:56 -040078 return agent.(*LogicalAgent)
khenaidoo8c3303d2019-02-13 14:59:39 -050079 }
khenaidoob9203542018-09-17 22:56:37 -040080 }
81 return nil
82}
83
Kent Hagerman2b216042020-04-03 18:28:56 -040084func (ldMgr *LogicalManager) deleteLogicalDeviceAgent(logicalDeviceID string) {
npujar1d86a522019-11-14 17:11:16 +053085 ldMgr.logicalDeviceAgents.Delete(logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -040086}
87
khenaidoo8c3303d2019-02-13 14:59:39 -050088// GetLogicalDevice provides a cloned most up to date logical device. If device is not in memory
89// it will be fetched from the dB
Kent Hagerman45a13e42020-04-13 12:23:50 -040090func (ldMgr *LogicalManager) GetLogicalDevice(ctx context.Context, id *voltha.ID) (*voltha.LogicalDevice, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +000091 logger.Debugw(ctx, "getlogicalDevice", log.Fields{"logical-device-id": id})
Kent Hagerman45a13e42020-04-13 12:23:50 -040092 if agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id); agent != nil {
Kent Hagermancba2f302020-07-28 13:37:36 -040093 return agent.GetLogicalDeviceReadOnly(ctx)
khenaidoob9203542018-09-17 22:56:37 -040094 }
95 return nil, status.Errorf(codes.NotFound, "%s", id)
96}
97
Kent Hagerman2b216042020-04-03 18:28:56 -040098//ListLogicalDevices returns the list of all logical devices
Kent Hagerman45a13e42020-04-13 12:23:50 -040099func (ldMgr *LogicalManager) ListLogicalDevices(ctx context.Context, _ *empty.Empty) (*voltha.LogicalDevices, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000100 logger.Debug(ctx, "ListAllLogicalDevices")
Kent Hagerman4f355f52020-03-30 16:01:33 -0400101
102 var logicalDevices []*voltha.LogicalDevice
Kent Hagermanf5a67352020-04-30 15:15:26 -0400103 if err := ldMgr.ldProxy.List(ctx, &logicalDevices); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000104 logger.Errorw(ctx, "failed-to-list-logical-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530105 return nil, err
106 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400107 return &voltha.LogicalDevices{Items: logicalDevices}, nil
khenaidoob9203542018-09-17 22:56:37 -0400108}
109
Kent Hagerman2b216042020-04-03 18:28:56 -0400110func (ldMgr *LogicalManager) createLogicalDevice(ctx context.Context, device *voltha.Device) (*string, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000111 logger.Debugw(ctx, "creating-logical-device", log.Fields{"device-id": device.Id})
khenaidoob9203542018-09-17 22:56:37 -0400112 // Sanity check
113 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400114 return nil, errors.New("device-not-root")
khenaidoob9203542018-09-17 22:56:37 -0400115 }
116
117 // Create a logical device agent - the logical device Id is based on the mac address of the device
118 // For now use the serial number - it may contain any combination of alphabetic characters and numbers,
119 // with length varying from eight characters to a maximum of 14 characters. Mac Address is part of oneof
120 // in the Device model. May need to be moved out.
Kent Hagerman2b216042020-04-03 18:28:56 -0400121 id := utils.CreateLogicalDeviceID()
David Bainbridged1afd662020-03-26 18:27:41 -0700122 sn := strings.Replace(device.MacAddress, ":", "", -1)
khenaidoo92e62c52018-10-03 14:02:54 -0400123 if id == "" {
divyadesaicb8b59d2020-08-18 09:55:47 +0000124 logger.Errorw(ctx, "mac-address-not-set", log.Fields{"device-id": device.Id, "serial-number": sn})
khenaidoo92e62c52018-10-03 14:02:54 -0400125 return nil, errors.New("mac-address-not-set")
126 }
David Bainbridged1afd662020-03-26 18:27:41 -0700127
divyadesaicb8b59d2020-08-18 09:55:47 +0000128 logger.Debugw(ctx, "logical-device-id", log.Fields{"logical-device-id": id})
khenaidoob9203542018-09-17 22:56:37 -0400129
Rohan Agrawal31f21802020-06-12 05:38:46 +0000130 agent := newLogicalAgent(ctx, id, sn, device.Id, ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
khenaidoob9203542018-09-17 22:56:37 -0400131 ldMgr.addLogicalDeviceAgentToMap(agent)
khenaidooad06fd72019-10-28 12:26:05 -0400132
133 // Update the root device with the logical device Id reference
npujar467fe752020-01-16 20:17:45 +0530134 if err := ldMgr.deviceMgr.setParentID(ctx, device, id); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000135 logger.Errorw(ctx, "failed-setting-parent-id", log.Fields{"logical-device-id": id, "device-id": device.Id})
khenaidooad06fd72019-10-28 12:26:05 -0400136 return nil, err
137 }
138
npujar1d86a522019-11-14 17:11:16 +0530139 go func() {
Kent Hagermanf5a67352020-04-30 15:15:26 -0400140 //TODO: either wait for the agent to be started before returning, or
141 // implement locks in the agent to ensure request are not processed before start() is complete
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000142 err := agent.start(log.WithSpanFromContext(context.Background(), ctx), false)
npujar1d86a522019-11-14 17:11:16 +0530143 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000144 logger.Errorw(ctx, "unable-to-create-the-logical-device", log.Fields{"error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400145 ldMgr.deleteLogicalDeviceAgent(id)
npujar1d86a522019-11-14 17:11:16 +0530146 }
147 }()
khenaidoob9203542018-09-17 22:56:37 -0400148
Rohan Agrawal31f21802020-06-12 05:38:46 +0000149 logger.Debug(ctx, "creating-logical-device-ends")
khenaidoob9203542018-09-17 22:56:37 -0400150 return &id, nil
151}
152
khenaidoo6d62c002019-05-15 21:57:03 -0400153// stopManagingLogicalDeviceWithDeviceId stops the management of the logical device. This implies removal of any
154// reference of this logical device in cache. The device Id is passed as param because the logical device may already
155// have been removed from the model. This function returns the logical device Id if found
Kent Hagerman2b216042020-04-03 18:28:56 -0400156func (ldMgr *LogicalManager) stopManagingLogicalDeviceWithDeviceID(ctx context.Context, id string) string {
divyadesaicb8b59d2020-08-18 09:55:47 +0000157 logger.Infow(ctx, "stop-managing-logical-device", log.Fields{"device-id": id})
khenaidoo6d62c002019-05-15 21:57:03 -0400158 // Go over the list of logical device agents to find the one which has rootDeviceId as id
npujar1d86a522019-11-14 17:11:16 +0530159 var ldID = ""
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400160 ldMgr.logicalDeviceAgents.Range(func(key, value interface{}) bool {
Kent Hagerman2b216042020-04-03 18:28:56 -0400161 ldAgent := value.(*LogicalAgent)
npujar1d86a522019-11-14 17:11:16 +0530162 if ldAgent.rootDeviceID == id {
divyadesaicb8b59d2020-08-18 09:55:47 +0000163 logger.Infow(ctx, "stopping-logical-device-agent", log.Fields{"logical-device-id": key})
npujar467fe752020-01-16 20:17:45 +0530164 if err := ldAgent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000165 logger.Errorw(ctx, "failed-to-stop-LDAgent", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530166 return false
167 }
npujar1d86a522019-11-14 17:11:16 +0530168 ldID = key.(string)
169 ldMgr.logicalDeviceAgents.Delete(ldID)
khenaidoo6d62c002019-05-15 21:57:03 -0400170 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400171 return true
172 })
npujar1d86a522019-11-14 17:11:16 +0530173 return ldID
khenaidoo6d62c002019-05-15 21:57:03 -0400174}
175
176//getLogicalDeviceFromModel retrieves the logical device data from the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400177func (ldMgr *LogicalManager) getLogicalDeviceFromModel(ctx context.Context, lDeviceID string) (*voltha.LogicalDevice, error) {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400178 logicalDevice := &voltha.LogicalDevice{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400179 if have, err := ldMgr.ldProxy.Get(ctx, lDeviceID, logicalDevice); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000180 logger.Errorw(ctx, "failed-to-get-logical-devices-from-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530181 return nil, err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400182 } else if !have {
183 return nil, status.Error(codes.NotFound, lDeviceID)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530184 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400185
186 return logicalDevice, nil
khenaidoo6d62c002019-05-15 21:57:03 -0400187}
188
khenaidoo297cd252019-02-07 22:10:23 -0500189// load loads a logical device manager in memory
Kent Hagerman2b216042020-04-03 18:28:56 -0400190func (ldMgr *LogicalManager) load(ctx context.Context, lDeviceID string) error {
npujar1d86a522019-11-14 17:11:16 +0530191 if lDeviceID == "" {
khenaidoo4c9e5592019-09-09 16:20:41 -0400192 return nil
khenaidoo297cd252019-02-07 22:10:23 -0500193 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400194 // Add a lock to prevent two concurrent calls from loading the same device twice
195 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530196 if _, exist := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; !exist {
197 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
198 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = []chan int{make(chan int, 1)}
khenaidoo4c9e5592019-09-09 16:20:41 -0400199 ldMgr.logicalDevicesLoadingLock.Unlock()
npujar467fe752020-01-16 20:17:45 +0530200 if _, err := ldMgr.getLogicalDeviceFromModel(ctx, lDeviceID); err == nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000201 logger.Debugw(ctx, "loading-logical-device", log.Fields{"lDeviceId": lDeviceID})
202 agent := newLogicalAgent(ctx, lDeviceID, "", "", ldMgr, ldMgr.deviceMgr, ldMgr.dbPath, ldMgr.ldProxy, ldMgr.defaultTimeout)
npujar467fe752020-01-16 20:17:45 +0530203 if err := agent.start(ctx, true); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400204 return err
khenaidoo4c9e5592019-09-09 16:20:41 -0400205 }
khenaidoo442e7c72020-03-10 16:13:48 -0400206 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
khenaidoo4c9e5592019-09-09 16:20:41 -0400207 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000208 logger.Debugw(ctx, "logicalDevice not in model", log.Fields{"lDeviceId": lDeviceID})
khenaidoo4c9e5592019-09-09 16:20:41 -0400209 }
210 // announce completion of task to any number of waiting channels
211 ldMgr.logicalDevicesLoadingLock.Lock()
npujar1d86a522019-11-14 17:11:16 +0530212 if v, ok := ldMgr.logicalDeviceLoadingInProgress[lDeviceID]; ok {
khenaidoo4c9e5592019-09-09 16:20:41 -0400213 for _, ch := range v {
214 close(ch)
215 }
npujar1d86a522019-11-14 17:11:16 +0530216 delete(ldMgr.logicalDeviceLoadingInProgress, lDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400217 }
218 ldMgr.logicalDevicesLoadingLock.Unlock()
219 } else {
220 ldMgr.logicalDevicesLoadingLock.Unlock()
221 }
222 } else {
223 ch := make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +0530224 ldMgr.logicalDeviceLoadingInProgress[lDeviceID] = append(ldMgr.logicalDeviceLoadingInProgress[lDeviceID], ch)
khenaidoo4c9e5592019-09-09 16:20:41 -0400225 ldMgr.logicalDevicesLoadingLock.Unlock()
226 // Wait for the channel to be closed, implying the process loading this device is done.
227 <-ch
228 }
npujar1d86a522019-11-14 17:11:16 +0530229 if _, exist := ldMgr.logicalDeviceAgents.Load(lDeviceID); exist {
khenaidoo4c9e5592019-09-09 16:20:41 -0400230 return nil
231 }
npujar1d86a522019-11-14 17:11:16 +0530232 return status.Errorf(codes.Aborted, "Error loading logical device %s", lDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500233}
234
Kent Hagerman2b216042020-04-03 18:28:56 -0400235func (ldMgr *LogicalManager) deleteLogicalDevice(ctx context.Context, device *voltha.Device) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000236 logger.Debugw(ctx, "deleting-logical-device", log.Fields{"device-id": device.Id})
khenaidoo92e62c52018-10-03 14:02:54 -0400237 // Sanity check
238 if !device.Root {
khenaidoo2c6a0992019-04-29 13:46:56 -0400239 return errors.New("device-not-root")
khenaidoo92e62c52018-10-03 14:02:54 -0400240 }
npujar1d86a522019-11-14 17:11:16 +0530241 logDeviceID := device.ParentId
npujar467fe752020-01-16 20:17:45 +0530242 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400243 // Stop the logical device agent
Thomas Lee Se5a44012019-11-07 20:32:24 +0530244 if err := agent.stop(ctx); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000245 logger.Errorw(ctx, "failed-to-stop-agent", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530246 return err
247 }
khenaidoo92e62c52018-10-03 14:02:54 -0400248 //Remove the logical device agent from the Map
npujar1d86a522019-11-14 17:11:16 +0530249 ldMgr.deleteLogicalDeviceAgent(logDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400250 }
251
Rohan Agrawal31f21802020-06-12 05:38:46 +0000252 logger.Debug(ctx, "deleting-logical-device-ends")
khenaidoo92e62c52018-10-03 14:02:54 -0400253 return nil
254}
255
Kent Hagerman2b216042020-04-03 18:28:56 -0400256func (ldMgr *LogicalManager) getLogicalDeviceID(ctx context.Context, device *voltha.Device) (*string, error) {
khenaidoo92e62c52018-10-03 14:02:54 -0400257 // Device can either be a parent or a child device
258 if device.Root {
259 // Parent device. The ID of a parent device is the logical device ID
260 return &device.ParentId, nil
261 }
262 // Device is child device
263 // retrieve parent device using child device ID
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400264 // TODO: return (string, have) instead of *string
265 // also: If not root device, just return device.parentID instead of loading the parent device.
npujar467fe752020-01-16 20:17:45 +0530266 if parentDevice := ldMgr.deviceMgr.getParentDevice(ctx, device); parentDevice != nil {
khenaidoo92e62c52018-10-03 14:02:54 -0400267 return &parentDevice.ParentId, nil
268 }
269 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
270}
271
Kent Hagerman2b216042020-04-03 18:28:56 -0400272func (ldMgr *LogicalManager) getLogicalDeviceIDFromDeviceID(ctx context.Context, deviceID string) (*string, error) {
khenaidoo3ab34882019-05-02 21:33:30 -0400273 // Get the device
274 var device *voltha.Device
275 var err error
Kent Hagermancba2f302020-07-28 13:37:36 -0400276 if device, err = ldMgr.deviceMgr.getDeviceReadOnly(ctx, deviceID); err != nil {
khenaidoo3ab34882019-05-02 21:33:30 -0400277 return nil, err
278 }
npujar467fe752020-01-16 20:17:45 +0530279 return ldMgr.getLogicalDeviceID(ctx, device)
khenaidoo3ab34882019-05-02 21:33:30 -0400280}
281
npujar1d86a522019-11-14 17:11:16 +0530282// ListLogicalDeviceFlows returns the flows of logical device
Kent Hagerman45a13e42020-04-13 12:23:50 -0400283func (ldMgr *LogicalManager) ListLogicalDeviceFlows(ctx context.Context, id *voltha.ID) (*openflow_13.Flows, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000284 logger.Debugw(ctx, "ListLogicalDeviceFlows", log.Fields{"logical-device-id": id.Id})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400285 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
286 if agent == nil {
287 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoodd237172019-05-27 16:37:17 -0400288 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400289
290 flows := agent.listLogicalDeviceFlows()
291 ctr, ret := 0, make([]*openflow_13.OfpFlowStats, len(flows))
292 for _, flow := range flows {
293 ret[ctr] = flow
294 ctr++
295 }
296 return &openflow_13.Flows{Items: ret}, nil
khenaidoodd237172019-05-27 16:37:17 -0400297}
298
npujar1d86a522019-11-14 17:11:16 +0530299// ListLogicalDeviceFlowGroups returns logical device flow groups
Kent Hagerman45a13e42020-04-13 12:23:50 -0400300func (ldMgr *LogicalManager) ListLogicalDeviceFlowGroups(ctx context.Context, id *voltha.ID) (*openflow_13.FlowGroups, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000301 logger.Debugw(ctx, "ListLogicalDeviceFlowGroups", log.Fields{"logical-device-id": 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 groups := agent.listLogicalDeviceGroups()
308 ctr, ret := 0, make([]*openflow_13.OfpGroupEntry, len(groups))
309 for _, group := range groups {
310 ret[ctr] = group
311 ctr++
312 }
313 return &openflow_13.FlowGroups{Items: ret}, nil
khenaidoodd237172019-05-27 16:37:17 -0400314}
315
npujar1d86a522019-11-14 17:11:16 +0530316// ListLogicalDevicePorts returns logical device ports
Kent Hagerman45a13e42020-04-13 12:23:50 -0400317func (ldMgr *LogicalManager) ListLogicalDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.LogicalPorts, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000318 logger.Debugw(ctx, "ListLogicalDevicePorts", log.Fields{"logical-device-id": id.Id})
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400319 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
320 if agent == nil {
321 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400322 }
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400323
Rohan Agrawal31f21802020-06-12 05:38:46 +0000324 ports := agent.listLogicalDevicePorts(ctx)
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400325 ctr, ret := 0, make([]*voltha.LogicalPort, len(ports))
326 for _, port := range ports {
327 ret[ctr] = port
328 ctr++
329 }
330 return &voltha.LogicalPorts{Items: ret}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400331}
332
Kent Hagerman45a13e42020-04-13 12:23:50 -0400333// GetLogicalDevicePort returns logical device port details
334func (ldMgr *LogicalManager) GetLogicalDevicePort(ctx context.Context, lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400335 // Get the logical device where this port is attached
336 agent := ldMgr.getLogicalDeviceAgent(ctx, lPortID.Id)
337 if agent == nil {
338 return nil, status.Errorf(codes.NotFound, "%s", lPortID.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400339 }
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400340
Rohan Agrawal31f21802020-06-12 05:38:46 +0000341 for _, port := range agent.listLogicalDevicePorts(ctx) {
npujar1d86a522019-11-14 17:11:16 +0530342 if port.Id == lPortID.PortId {
khenaidoo19d7b632018-10-30 10:49:50 -0400343 return port, nil
344 }
345 }
npujar1d86a522019-11-14 17:11:16 +0530346 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
khenaidoo19d7b632018-10-30 10:49:50 -0400347}
348
khenaidoo2c6a0992019-04-29 13:46:56 -0400349// updateLogicalPort sets up a logical port on the logical device based on the device port
350// information, if needed
Kent Hagerman2a07b862020-06-19 15:23:07 -0400351func (ldMgr *LogicalManager) updateLogicalPort(ctx context.Context, device *voltha.Device, devicePorts map[uint32]*voltha.Port, port *voltha.Port) error {
npujar467fe752020-01-16 20:17:45 +0530352 ldID, err := ldMgr.getLogicalDeviceID(ctx, device)
npujar1d86a522019-11-14 17:11:16 +0530353 if err != nil || *ldID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400354 // This is not an error as the logical device may not have been created at this time. In such a case,
355 // the ports will be created when the logical device is ready.
356 return nil
khenaidoo2c6a0992019-04-29 13:46:56 -0400357 }
npujar467fe752020-01-16 20:17:45 +0530358 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400359 if err := agent.updateLogicalPort(ctx, device, devicePorts, port); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530360 return err
khenaidoofc1314d2019-03-14 09:34:21 -0400361 }
362 }
363 return nil
364}
365
khenaidoo0a822f92019-05-08 15:15:57 -0400366// deleteLogicalPort removes the logical port associated with a child device
Kent Hagerman2b216042020-04-03 18:28:56 -0400367func (ldMgr *LogicalManager) deleteLogicalPorts(ctx context.Context, deviceID string) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000368 logger.Debugw(ctx, "deleting-logical-ports", log.Fields{"device-id": deviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400369 // Get logical port
npujar467fe752020-01-16 20:17:45 +0530370 ldID, err := ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID)
npujar1d86a522019-11-14 17:11:16 +0530371 if err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400372 return err
npujar1d86a522019-11-14 17:11:16 +0530373 }
npujar467fe752020-01-16 20:17:45 +0530374 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
375 if err = agent.deleteLogicalPorts(ctx, deviceID); err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000376 logger.Warnw(ctx, "delete-logical-ports-failed", log.Fields{"logical-device-id": *ldID})
npujar1d86a522019-11-14 17:11:16 +0530377 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400378 }
379 }
Rohan Agrawal31f21802020-06-12 05:38:46 +0000380 logger.Debug(ctx, "deleting-logical-ports-ends")
khenaidoo0a822f92019-05-08 15:15:57 -0400381 return nil
382}
383
Kent Hagerman2a07b862020-06-19 15:23:07 -0400384func (ldMgr *LogicalManager) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device, childDevicePorts map[uint32]*voltha.Port) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000385 logger.Debugw(ctx, "setupUNILogicalPorts", log.Fields{"childDeviceId": childDevice.Id, "parentDeviceId": childDevice.ParentId, "current-data": childDevice})
khenaidoob9203542018-09-17 22:56:37 -0400386 // Sanity check
387 if childDevice.Root {
388 return errors.New("Device-root")
389 }
390
391 // Get the logical device id parent device
npujar1d86a522019-11-14 17:11:16 +0530392 parentID := childDevice.ParentId
npujar467fe752020-01-16 20:17:45 +0530393 logDeviceID := ldMgr.deviceMgr.GetParentDeviceID(ctx, parentID)
khenaidoob9203542018-09-17 22:56:37 -0400394
Rohan Agrawal31f21802020-06-12 05:38:46 +0000395 logger.Debugw(ctx, "setupUNILogicalPorts", log.Fields{"logDeviceId": logDeviceID, "parentId": parentID})
khenaidoob9203542018-09-17 22:56:37 -0400396
npujar1d86a522019-11-14 17:11:16 +0530397 if parentID == "" || logDeviceID == "" {
khenaidoo2c6a0992019-04-29 13:46:56 -0400398 return errors.New("device-in-invalid-state")
khenaidoo5e677ae2019-02-28 17:26:29 -0500399 }
400
npujar467fe752020-01-16 20:17:45 +0530401 if agent := ldMgr.getLogicalDeviceAgent(ctx, logDeviceID); agent != nil {
Kent Hagerman2a07b862020-06-19 15:23:07 -0400402 if err := agent.setupUNILogicalPorts(ctx, childDevice, childDevicePorts); err != nil {
khenaidoobcf205b2019-01-25 22:21:14 -0500403 return err
404 }
khenaidoob9203542018-09-17 22:56:37 -0400405 }
khenaidoo21d51152019-02-01 13:48:37 -0500406 return nil
khenaidoob9203542018-09-17 22:56:37 -0400407}
khenaidoo19d7b632018-10-30 10:49:50 -0400408
Kent Hagerman2b216042020-04-03 18:28:56 -0400409func (ldMgr *LogicalManager) deleteAllLogicalPorts(ctx context.Context, device *voltha.Device) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000410 logger.Debugw(ctx, "deleteAllLogicalPorts", log.Fields{"device-id": device.Id})
khenaidoo0a822f92019-05-08 15:15:57 -0400411
npujar1d86a522019-11-14 17:11:16 +0530412 var ldID *string
khenaidoo0a822f92019-05-08 15:15:57 -0400413 var err error
414 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530415 if ldID, err = ldMgr.getLogicalDeviceID(ctx, device); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000416 logger.Warnw(ctx, "no-logical-device-found", log.Fields{"device-id": device.Id, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400417 return err
418 }
npujar467fe752020-01-16 20:17:45 +0530419 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
Girish Gowdra408cd962020-03-11 14:31:31 -0700420 if err := agent.deleteAllLogicalPorts(ctx); err != nil {
khenaidoo0a822f92019-05-08 15:15:57 -0400421 return err
422 }
423 }
424 return nil
425}
Hardik Windlassc704def2020-02-26 18:23:19 +0000426
Kent Hagerman2b216042020-04-03 18:28:56 -0400427func (ldMgr *LogicalManager) updatePortState(ctx context.Context, deviceID string, portNo uint32, state voltha.OperStatus_Types) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000428 logger.Debugw(ctx, "updatePortState", log.Fields{"device-id": deviceID, "state": state, "portNo": portNo})
khenaidoo171b98e2019-10-31 11:48:15 -0400429
npujar1d86a522019-11-14 17:11:16 +0530430 var ldID *string
khenaidoo171b98e2019-10-31 11:48:15 -0400431 var err error
432 //Get the logical device Id for this device
npujar467fe752020-01-16 20:17:45 +0530433 if ldID, err = ldMgr.getLogicalDeviceIDFromDeviceID(ctx, deviceID); err != nil {
divyadesaicb8b59d2020-08-18 09:55:47 +0000434 logger.Warnw(ctx, "no-logical-device-found", log.Fields{"device-id": deviceID, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400435 return err
436 }
npujar467fe752020-01-16 20:17:45 +0530437 if agent := ldMgr.getLogicalDeviceAgent(ctx, *ldID); agent != nil {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400438 if err := agent.updatePortState(ctx, portNo, state); err != nil {
khenaidoo171b98e2019-10-31 11:48:15 -0400439 return err
440 }
441 }
442 return nil
443}
khenaidoo0a822f92019-05-08 15:15:57 -0400444
Kent Hagerman45a13e42020-04-13 12:23:50 -0400445// UpdateLogicalDeviceFlowTable updates logical device flow table
446func (ldMgr *LogicalManager) UpdateLogicalDeviceFlowTable(ctx context.Context, flow *openflow_13.FlowTableUpdate) (*empty.Empty, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000447 logger.Debugw(ctx, "UpdateLogicalDeviceFlowTable", log.Fields{"logical-device-id": flow.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400448 agent := ldMgr.getLogicalDeviceAgent(ctx, flow.Id)
449 if agent == nil {
450 return nil, status.Errorf(codes.NotFound, "%s", flow.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400451 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400452 return &empty.Empty{}, agent.updateFlowTable(ctx, flow.FlowMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400453}
454
Kent Hagerman45a13e42020-04-13 12:23:50 -0400455// UpdateLogicalDeviceMeterTable - This function sends meter mod request to logical device manager and waits for response
456func (ldMgr *LogicalManager) UpdateLogicalDeviceMeterTable(ctx context.Context, meter *openflow_13.MeterModUpdate) (*empty.Empty, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000457 logger.Debugw(ctx, "UpdateLogicalDeviceMeterTable", log.Fields{"logical-device-id": meter.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400458 agent := ldMgr.getLogicalDeviceAgent(ctx, meter.Id)
459 if agent == nil {
460 return nil, status.Errorf(codes.NotFound, "%s", meter.Id)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400461 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400462 return &empty.Empty{}, agent.updateMeterTable(ctx, meter.MeterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400463}
464
npujar1d86a522019-11-14 17:11:16 +0530465// ListLogicalDeviceMeters returns logical device meters
Kent Hagerman45a13e42020-04-13 12:23:50 -0400466func (ldMgr *LogicalManager) ListLogicalDeviceMeters(ctx context.Context, id *voltha.ID) (*openflow_13.Meters, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000467 logger.Debugw(ctx, "ListLogicalDeviceMeters", log.Fields{"logical-device-id": id.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400468 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
469 if agent == nil {
470 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400471 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400472 meters := agent.listLogicalDeviceMeters()
473 ctr, ret := 0, make([]*openflow_13.OfpMeterEntry, len(meters))
474 for _, meter := range meters {
475 ret[ctr] = meter
476 ctr++
477 }
478 return &openflow_13.Meters{Items: ret}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400479}
480
Kent Hagerman45a13e42020-04-13 12:23:50 -0400481// UpdateLogicalDeviceFlowGroupTable updates logical device flow group table
482func (ldMgr *LogicalManager) UpdateLogicalDeviceFlowGroupTable(ctx context.Context, flow *openflow_13.FlowGroupTableUpdate) (*empty.Empty, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000483 logger.Debugw(ctx, "UpdateGroupTable", log.Fields{"logical-device-id": flow.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400484 agent := ldMgr.getLogicalDeviceAgent(ctx, flow.Id)
485 if agent == nil {
486 return nil, status.Errorf(codes.NotFound, "%s", flow.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400487 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400488 return &empty.Empty{}, agent.updateGroupTable(ctx, flow.GroupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400489}
490
Kent Hagerman45a13e42020-04-13 12:23:50 -0400491// EnableLogicalDevicePort enables logical device port
492func (ldMgr *LogicalManager) EnableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000493 logger.Debugw(ctx, "EnableLogicalDevicePort", log.Fields{"logical-device-id": id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400494 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
495 if agent == nil {
496 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
khenaidoo19d7b632018-10-30 10:49:50 -0400497 }
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400498 portNo, err := strconv.ParseUint(id.PortId, 10, 32)
499 if err != nil {
500 return nil, status.Errorf(codes.InvalidArgument, "failed to parse %s as a number", id.PortId)
501 }
502 return &empty.Empty{}, agent.enableLogicalPort(ctx, uint32(portNo))
Kent Hagerman45a13e42020-04-13 12:23:50 -0400503}
504
505// DisableLogicalDevicePort disables logical device port
506func (ldMgr *LogicalManager) DisableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
divyadesaicb8b59d2020-08-18 09:55:47 +0000507 logger.Debugw(ctx, "DisableLogicalDevicePort", log.Fields{"logical-device-id": id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400508 agent := ldMgr.getLogicalDeviceAgent(ctx, id.Id)
509 if agent == nil {
510 return nil, status.Errorf(codes.NotFound, "%s", id.Id)
511 }
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400512 portNo, err := strconv.ParseUint(id.PortId, 10, 32)
513 if err != nil {
514 return nil, status.Errorf(codes.InvalidArgument, "failed to parse %s as a number", id.PortId)
515 }
516 return &empty.Empty{}, agent.disableLogicalPort(ctx, uint32(portNo))
khenaidoo19d7b632018-10-30 10:49:50 -0400517}
khenaidoofdbad6e2018-11-06 22:26:38 -0500518
Kent Hagerman2b216042020-04-03 18:28:56 -0400519func (ldMgr *LogicalManager) packetIn(ctx context.Context, logicalDeviceID string, port uint32, transactionID string, packet []byte) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000520 logger.Debugw(ctx, "packetIn", log.Fields{"logical-device-id": logicalDeviceID, "port": port})
npujar467fe752020-01-16 20:17:45 +0530521 if agent := ldMgr.getLogicalDeviceAgent(ctx, logicalDeviceID); agent != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000522 agent.packetIn(ctx, port, transactionID, packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500523 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000524 logger.Error(ctx, "logical-device-not-exist", log.Fields{"logical-device-id": logicalDeviceID})
khenaidoofdbad6e2018-11-06 22:26:38 -0500525 }
526 return nil
527}
Kent Hagerman2b216042020-04-03 18:28:56 -0400528
Kent Hagerman45a13e42020-04-13 12:23:50 -0400529// StreamPacketsOut sends packets to adapter
530func (ldMgr *LogicalManager) StreamPacketsOut(packets voltha.VolthaService_StreamPacketsOutServer) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000531 ctx := context.Background()
532 logger.Debugw(ctx, "StreamPacketsOut-request", log.Fields{"packets": packets})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400533loop:
534 for {
535 select {
536 case <-packets.Context().Done():
Rohan Agrawal31f21802020-06-12 05:38:46 +0000537 logger.Infow(ctx, "StreamPacketsOut-context-done", log.Fields{"packets": packets, "error": packets.Context().Err()})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400538 break loop
539 default:
540 }
541
542 packet, err := packets.Recv()
543
544 if err == io.EOF {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000545 logger.Debugw(ctx, "Received-EOF", log.Fields{"packets": packets})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400546 break loop
547 }
548
549 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000550 logger.Errorw(ctx, "Failed to receive packet out", log.Fields{"error": err})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400551 continue
552 }
553
554 if agent := ldMgr.getLogicalDeviceAgent(packets.Context(), packet.Id); agent != nil {
555 agent.packetOut(packets.Context(), packet.PacketOut)
556 } else {
divyadesaicb8b59d2020-08-18 09:55:47 +0000557 logger.Errorf(ctx, "No logical device agent present", log.Fields{"logical-device-id": packet.Id})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400558 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400559 }
Kent Hagerman45a13e42020-04-13 12:23:50 -0400560
Rohan Agrawal31f21802020-06-12 05:38:46 +0000561 logger.Debugw(ctx, "StreamPacketsOut-request-done", log.Fields{"packets": packets})
Kent Hagerman45a13e42020-04-13 12:23:50 -0400562 return nil
Kent Hagerman2b216042020-04-03 18:28:56 -0400563}