blob: c6e4e730e342942b3f1c731964f3ca7d83ae4e1b [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"
Matteo Scandolo360605d2019-11-05 18:29:17 -080021 "encoding/hex"
khenaidoo19d7b632018-10-30 10:49:50 -040022 "errors"
23 "fmt"
David Bainbridged1afd662020-03-26 18:27:41 -070024 "reflect"
25 "sync"
26 "time"
27
khenaidoob9203542018-09-17 22:56:37 -040028 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
npujar1d86a522019-11-14 17:11:16 +053030 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo442e7c72020-03-10 16:13:48 -040031 "github.com/opencord/voltha-go/rw_core/route"
Scott Bakerb671a862019-10-24 10:53:40 -070032 coreutils "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
34 "github.com/opencord/voltha-lib-go/v3/pkg/log"
35 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
37 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040040)
41
Kent Hagerman2b216042020-04-03 18:28:56 -040042// LogicalAgent represent attributes of logical device agent
43type LogicalAgent struct {
npujar1d86a522019-11-14 17:11:16 +053044 logicalDeviceID string
David Bainbridged1afd662020-03-26 18:27:41 -070045 serialNumber string
npujar1d86a522019-11-14 17:11:16 +053046 rootDeviceID string
Kent Hagerman2b216042020-04-03 18:28:56 -040047 deviceMgr *Manager
48 ldeviceMgr *LogicalManager
khenaidoo3306c992019-05-24 16:57:35 -040049 clusterDataProxy *model.Proxy
Kent Hagerman4f355f52020-03-30 16:01:33 -040050 stopped bool
khenaidoo820197c2020-02-13 16:35:33 -050051 deviceRoutes *route.DeviceRoutes
khenaidoo820197c2020-02-13 16:35:33 -050052 lockDeviceRoutes sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040053 logicalPortsNo map[uint32]bool //value is true for NNI port
54 lockLogicalPortsNo sync.RWMutex
55 flowDecomposer *fd.FlowDecomposer
khenaidoo442e7c72020-03-10 16:13:48 -040056 defaultTimeout time.Duration
khenaidoo6e55d9e2019-12-12 18:26:26 -050057 logicalDevice *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -040058 requestQueue *coreutils.RequestQueue
59 startOnce sync.Once
60 stopOnce sync.Once
khenaidoob9203542018-09-17 22:56:37 -040061}
62
Kent Hagerman2b216042020-04-03 18:28:56 -040063func newLogicalDeviceAgent(id string, sn string, deviceID string, ldeviceMgr *LogicalManager,
64 deviceMgr *Manager, cdProxy *model.Proxy, timeout time.Duration) *LogicalAgent {
65 var agent LogicalAgent
npujar1d86a522019-11-14 17:11:16 +053066 agent.logicalDeviceID = id
David Bainbridged1afd662020-03-26 18:27:41 -070067 agent.serialNumber = sn
npujar1d86a522019-11-14 17:11:16 +053068 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040069 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040070 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040071 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040072 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo2c6a0992019-04-29 13:46:56 -040073 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040074 agent.defaultTimeout = timeout
Kent Hagerman730cbdf2020-03-31 12:22:08 -040075 agent.requestQueue = coreutils.NewRequestQueue()
khenaidoob9203542018-09-17 22:56:37 -040076 return &agent
77}
78
khenaidoo4d4802d2018-10-04 21:59:49 -040079// start creates the logical device and add it to the data model
Kent Hagerman2b216042020-04-03 18:28:56 -040080func (agent *LogicalAgent) start(ctx context.Context, loadFromDB bool) error {
khenaidoo442e7c72020-03-10 16:13:48 -040081 needToStart := false
82 if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
83 return nil
84 }
85
Girish Kumarf56a4682020-03-20 20:07:46 +000086 logger.Infow("starting-logical_device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB})
khenaidoo442e7c72020-03-10 16:13:48 -040087
88 var startSucceeded bool
89 defer func() {
90 if !startSucceeded {
91 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +000092 logger.Errorw("failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -040093 }
94 }
95 }()
96
khenaidoo297cd252019-02-07 22:10:23 -050097 var ld *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -040098 if !loadFromDB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040099 //Build the logical device based on information retrieved from the device adapter
100 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -0500101 var err error
npujar1d86a522019-11-14 17:11:16 +0530102 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400103 return err
104 }
npujar1d86a522019-11-14 17:11:16 +0530105 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500106
107 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
108 var datapathID uint64
Kent Hagerman2b216042020-04-03 18:28:56 -0400109 if datapathID, err = coreutils.CreateDataPathID(agent.serialNumber); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500110 return err
111 }
112 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400113 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
Girish Kumarf56a4682020-03-20 20:07:46 +0000114 logger.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo7e3d8f12019-08-02 16:06:30 -0400115 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500116 ld.Flows = &ofp.Flows{Items: nil}
117 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoo49085352020-01-13 19:15:43 -0500118 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500119
khenaidoo297cd252019-02-07 22:10:23 -0500120 // Save the logical device
Kent Hagerman4f355f52020-03-30 16:01:33 -0400121 if err := agent.clusterDataProxy.AddWithID(ctx, "logical_devices", ld.Id, ld); err != nil {
122 logger.Errorw("failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530123 return err
124 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400125 logger.Debugw("logicaldevice-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500126
127 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoofc1314d2019-03-14 09:34:21 -0400128
khenaidoo442e7c72020-03-10 16:13:48 -0400129 // Setup the logicalports - internal processing, no need to propagate the client context
npujar1d86a522019-11-14 17:11:16 +0530130 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400131 err := agent.setupLogicalPorts(context.Background())
npujar1d86a522019-11-14 17:11:16 +0530132 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000133 logger.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530134 }
135 }()
khenaidoo297cd252019-02-07 22:10:23 -0500136 } else {
137 // load from dB - the logical may not exist at this time. On error, just return and the calling function
138 // will destroy this agent.
Kent Hagerman4f355f52020-03-30 16:01:33 -0400139 ld := &voltha.LogicalDevice{}
140 have, err := agent.clusterDataProxy.Get(ctx, "logical_devices/"+agent.logicalDeviceID, ld)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530141 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400142 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400143 } else if !have {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500144 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500145 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400146
khenaidoo8c3303d2019-02-13 14:59:39 -0500147 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530148 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400149
khenaidoo6e55d9e2019-12-12 18:26:26 -0500150 // Update the last data
151 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
152
khenaidoo3d3b8c22019-05-22 18:10:39 -0400153 // Setup the local list of logical ports
154 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400155 }
khenaidoofc1314d2019-03-14 09:34:21 -0400156
khenaidoo820197c2020-02-13 16:35:33 -0500157 // Setup the device routes. Building routes may fail if the pre-conditions are not satisfied (e.g. no PON ports present)
khenaidoo442e7c72020-03-10 16:13:48 -0400158 if loadFromDB {
khenaidoo820197c2020-02-13 16:35:33 -0500159 go func() {
160 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000161 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -0500162 }
163 }()
khenaidoo4c9e5592019-09-09 16:20:41 -0400164 }
khenaidoo442e7c72020-03-10 16:13:48 -0400165 startSucceeded = true
166
khenaidoob9203542018-09-17 22:56:37 -0400167 return nil
168}
169
khenaidoo442e7c72020-03-10 16:13:48 -0400170// stop stops the logical device agent. This removes the logical device from the data model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400171func (agent *LogicalAgent) stop(ctx context.Context) error {
khenaidoo442e7c72020-03-10 16:13:48 -0400172 var returnErr error
173 agent.stopOnce.Do(func() {
Girish Kumarf56a4682020-03-20 20:07:46 +0000174 logger.Info("stopping-logical_device-agent")
khenaidoo8c3303d2019-02-13 14:59:39 -0500175
khenaidoo442e7c72020-03-10 16:13:48 -0400176 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
177 // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once.
178 returnErr = err
179 return
180 }
181 defer agent.requestQueue.RequestComplete()
182
183 //Remove the logical device from the model
Kent Hagerman4f355f52020-03-30 16:01:33 -0400184 if err := agent.clusterDataProxy.Remove(ctx, "logical_devices/"+agent.logicalDeviceID); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400185 returnErr = err
khenaidoo442e7c72020-03-10 16:13:48 -0400186 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000187 logger.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400188 }
189
Kent Hagerman4f355f52020-03-30 16:01:33 -0400190 agent.stopped = true
khenaidoo442e7c72020-03-10 16:13:48 -0400191
Girish Kumarf56a4682020-03-20 20:07:46 +0000192 logger.Info("logical_device-agent-stopped")
khenaidoo442e7c72020-03-10 16:13:48 -0400193 })
194 return returnErr
khenaidoo4d4802d2018-10-04 21:59:49 -0400195}
196
khenaidoo6e55d9e2019-12-12 18:26:26 -0500197// GetLogicalDevice returns the latest logical device data
Kent Hagerman2b216042020-04-03 18:28:56 -0400198func (agent *LogicalAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
khenaidoo442e7c72020-03-10 16:13:48 -0400199 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
200 return nil, err
201 }
202 defer agent.requestQueue.RequestComplete()
203 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400204}
205
npujar1d86a522019-11-14 17:11:16 +0530206// ListLogicalDeviceFlows returns logical device flows
Kent Hagerman2b216042020-04-03 18:28:56 -0400207func (agent *LogicalAgent) ListLogicalDeviceFlows(ctx context.Context) (*ofp.Flows, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000208 logger.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500209
khenaidoo442e7c72020-03-10 16:13:48 -0400210 logicalDevice, err := agent.GetLogicalDevice(ctx)
211 if err != nil {
212 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400213 }
khenaidoo442e7c72020-03-10 16:13:48 -0400214 if logicalDevice.Flows == nil {
215 return &ofp.Flows{}, nil
216 }
217 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows), nil
khenaidoodd237172019-05-27 16:37:17 -0400218}
219
npujar1d86a522019-11-14 17:11:16 +0530220// ListLogicalDeviceMeters returns logical device meters
Kent Hagerman2b216042020-04-03 18:28:56 -0400221func (agent *LogicalAgent) ListLogicalDeviceMeters(ctx context.Context) (*ofp.Meters, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000222 logger.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500223
khenaidoo442e7c72020-03-10 16:13:48 -0400224 logicalDevice, err := agent.GetLogicalDevice(ctx)
225 if err != nil {
226 return nil, err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400227 }
khenaidoo442e7c72020-03-10 16:13:48 -0400228 if logicalDevice.Meters == nil {
229 return &ofp.Meters{}, nil
230 }
231 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters), nil
Manikkaraj kb1a10922019-07-29 12:10:34 -0400232}
233
npujar1d86a522019-11-14 17:11:16 +0530234// ListLogicalDeviceFlowGroups returns logical device flow groups
Kent Hagerman2b216042020-04-03 18:28:56 -0400235func (agent *LogicalAgent) ListLogicalDeviceFlowGroups(ctx context.Context) (*ofp.FlowGroups, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000236 logger.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500237
khenaidoo442e7c72020-03-10 16:13:48 -0400238 logicalDevice, err := agent.GetLogicalDevice(ctx)
239 if err != nil {
240 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400241 }
khenaidoo442e7c72020-03-10 16:13:48 -0400242 if logicalDevice.FlowGroups == nil {
243 return &ofp.FlowGroups{}, nil
244 }
245 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups), nil
khenaidoodd237172019-05-27 16:37:17 -0400246}
247
npujar1d86a522019-11-14 17:11:16 +0530248// ListLogicalDevicePorts returns logical device ports
Kent Hagerman2b216042020-04-03 18:28:56 -0400249func (agent *LogicalAgent) ListLogicalDevicePorts(ctx context.Context) (*voltha.LogicalPorts, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000250 logger.Debug("ListLogicalDevicePorts")
khenaidoo442e7c72020-03-10 16:13:48 -0400251 logicalDevice, err := agent.GetLogicalDevice(ctx)
252 if err != nil {
253 return nil, err
254 }
255 if logicalDevice == nil {
256 return &voltha.LogicalPorts{}, nil
257 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500258 lPorts := make([]*voltha.LogicalPort, 0)
259 lPorts = append(lPorts, logicalDevice.Ports...)
khenaidoo442e7c72020-03-10 16:13:48 -0400260 return &voltha.LogicalPorts{Items: lPorts}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400261}
262
khenaidoo4c9e5592019-09-09 16:20:41 -0400263//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400264func (agent *LogicalAgent) updateLogicalDeviceFlowsWithoutLock(ctx context.Context, flows *ofp.Flows) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500265 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400266
Girish Kumarf56a4682020-03-20 20:07:46 +0000267 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500268 ld.Flows = flows
269
npujar467fe752020-01-16 20:17:45 +0530270 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000271 logger.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400272 return err
khenaidoo43c82122018-11-22 18:38:28 -0500273 }
khenaidoo43c82122018-11-22 18:38:28 -0500274 return nil
275}
276
khenaidoo4c9e5592019-09-09 16:20:41 -0400277//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Kent Hagerman2b216042020-04-03 18:28:56 -0400278func (agent *LogicalAgent) updateLogicalDeviceMetersWithoutLock(ctx context.Context, meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500279 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400280
Girish Kumarf56a4682020-03-20 20:07:46 +0000281 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500282 ld.Meters = meters
283
npujar467fe752020-01-16 20:17:45 +0530284 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000285 logger.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400286 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400287 }
288 return nil
289}
290
khenaidoo4c9e5592019-09-09 16:20:41 -0400291//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
Kent Hagerman2b216042020-04-03 18:28:56 -0400292func (agent *LogicalAgent) updateLogicalDeviceFlowGroupsWithoutLock(ctx context.Context, flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500293 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400294
Girish Kumarf56a4682020-03-20 20:07:46 +0000295 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500296 ld.FlowGroups = flowGroups
297
npujar467fe752020-01-16 20:17:45 +0530298 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000299 logger.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400300 return err
khenaidoo43c82122018-11-22 18:38:28 -0500301 }
khenaidoo43c82122018-11-22 18:38:28 -0500302 return nil
303}
304
khenaidoo6e55d9e2019-12-12 18:26:26 -0500305// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
Kent Hagerman2b216042020-04-03 18:28:56 -0400306func (agent *LogicalAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
Girish Kumarf56a4682020-03-20 20:07:46 +0000307 logger.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500308 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400309}
310
Kent Hagerman2b216042020-04-03 18:28:56 -0400311func (agent *LogicalAgent) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000312 logger.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
khenaidoo2c6a0992019-04-29 13:46:56 -0400313 var err error
314 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530315 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400316 return err
317 }
318 agent.addLogicalPortToMap(port.PortNo, true)
319 } else if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530320 if _, err = agent.addUNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400321 return err
322 }
323 agent.addLogicalPortToMap(port.PortNo, false)
324 } else {
khenaidoo820197c2020-02-13 16:35:33 -0500325 // Update the device routes to ensure all routes on the logical device have been calculated
326 if err = agent.buildRoutes(ctx); err != nil {
327 // Not an error - temporary state
Girish Kumarf56a4682020-03-20 20:07:46 +0000328 logger.Warnw("failed-to-update-routes", log.Fields{"device-id": device.Id, "port": port, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400329 }
330 }
331 return nil
332}
333
khenaidoo3d3b8c22019-05-22 18:10:39 -0400334// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
335// added to it. While the logical device was being created we could have received requests to add
336// NNI and UNI ports which were discarded. Now is the time to add them if needed
Kent Hagerman2b216042020-04-03 18:28:56 -0400337func (agent *LogicalAgent) setupLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000338 logger.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400339 // First add any NNI ports which could have been missing
npujar467fe752020-01-16 20:17:45 +0530340 if err := agent.setupNNILogicalPorts(ctx, agent.rootDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000341 logger.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400342 return err
343 }
344
345 // Now, set up the UNI ports if needed.
Kent Hagerman2b216042020-04-03 18:28:56 -0400346 children, err := agent.deviceMgr.GetAllChildDevices(ctx, agent.rootDeviceID)
npujar1d86a522019-11-14 17:11:16 +0530347 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000348 logger.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400349 return err
npujar1d86a522019-11-14 17:11:16 +0530350 }
351 responses := make([]coreutils.Response, 0)
352 for _, child := range children.Items {
353 response := coreutils.NewResponse()
354 responses = append(responses, response)
355 go func(child *voltha.Device) {
khenaidoo442e7c72020-03-10 16:13:48 -0400356 if err = agent.setupUNILogicalPorts(context.Background(), child); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000357 logger.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
npujar1d86a522019-11-14 17:11:16 +0530358 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
359 }
360 response.Done()
361 }(child)
362 }
363 // Wait for completion
364 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
365 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400366 }
367 return nil
368}
369
khenaidoofc1314d2019-03-14 09:34:21 -0400370// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
Kent Hagerman2b216042020-04-03 18:28:56 -0400371func (agent *LogicalAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000372 logger.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400373 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400374 var err error
375
376 var device *voltha.Device
npujar467fe752020-01-16 20:17:45 +0530377 if device, err = agent.deviceMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000378 logger.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400379 return err
380 }
381
382 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400383 for _, port := range device.Ports {
384 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530385 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000386 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400387 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400388 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400389 }
390 }
khenaidoofc1314d2019-03-14 09:34:21 -0400391 return err
392}
393
khenaidoo171b98e2019-10-31 11:48:15 -0400394// updatePortState updates the port state of the device
Kent Hagerman2b216042020-04-03 18:28:56 -0400395func (agent *LogicalAgent) updatePortState(ctx context.Context, deviceID string, portNo uint32, operStatus voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000396 logger.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo442e7c72020-03-10 16:13:48 -0400397 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
398 return err
399 }
400 defer agent.requestQueue.RequestComplete()
khenaidoo171b98e2019-10-31 11:48:15 -0400401 // Get the latest logical device info
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500402 original := agent.getLogicalDeviceWithoutLock()
403 updatedPorts := clonePorts(original.Ports)
404 for _, port := range updatedPorts {
405 if port.DeviceId == deviceID && port.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530406 if operStatus == voltha.OperStatus_ACTIVE {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500407 port.OfpPort.Config = port.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
408 port.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
npujar1d86a522019-11-14 17:11:16 +0530409 } else {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500410 port.OfpPort.Config = port.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
411 port.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
npujar1d86a522019-11-14 17:11:16 +0530412 }
413 // Update the logical device
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500414 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, original, updatedPorts); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000415 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530416 return err
417 }
418 return nil
419 }
420 }
421 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400422}
423
khenaidoo3ab34882019-05-02 21:33:30 -0400424// updatePortsState updates the ports state related to the device
Kent Hagerman2b216042020-04-03 18:28:56 -0400425func (agent *LogicalAgent) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000426 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400427 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
428 return err
429 }
430 defer agent.requestQueue.RequestComplete()
khenaidoo3ab34882019-05-02 21:33:30 -0400431 // Get the latest logical device info
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500432 original := agent.getLogicalDeviceWithoutLock()
433 updatedPorts := clonePorts(original.Ports)
434 for _, port := range updatedPorts {
435 if port.DeviceId == device.Id {
kesavandbc2d1622020-01-21 00:42:01 -0500436 if state == voltha.OperStatus_ACTIVE {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500437 port.OfpPort.Config = port.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
438 port.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
kesavandbc2d1622020-01-21 00:42:01 -0500439 } else {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500440 port.OfpPort.Config = port.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
441 port.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
khenaidoo3ab34882019-05-02 21:33:30 -0400442 }
443 }
npujar1d86a522019-11-14 17:11:16 +0530444 }
445 // Updating the logical device will trigger the poprt change events to be populated to the controller
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500446 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, original, updatedPorts); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000447 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530448 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400449 }
450 return nil
451}
452
khenaidoofc1314d2019-03-14 09:34:21 -0400453// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
Kent Hagerman2b216042020-04-03 18:28:56 -0400454func (agent *LogicalAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000455 logger.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400456 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400457 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400458 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400459 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400460 for _, port := range childDevice.Ports {
461 if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530462 if added, err = agent.addUNILogicalPort(ctx, childDevice, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000463 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400464 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400465 if added {
466 agent.addLogicalPortToMap(port.PortNo, false)
467 }
khenaidoo19d7b632018-10-30 10:49:50 -0400468 }
469 }
khenaidoofc1314d2019-03-14 09:34:21 -0400470 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400471}
472
Girish Gowdra408cd962020-03-11 14:31:31 -0700473// deleteAllLogicalPorts deletes all logical ports associated with this logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400474func (agent *LogicalAgent) deleteAllLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000475 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400476 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
477 return err
478 }
479 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -0400480 // Get the latest logical device info
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500481 cloned := agent.getLogicalDeviceWithoutLock()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500482
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500483 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, cloned, []*voltha.LogicalPort{}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000484 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -0700485 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400486 }
487 return nil
488}
489
Hardik Windlassc704def2020-02-26 18:23:19 +0000490// deleteAllUNILogicalPorts deletes all UNI logical ports associated with this parent device
Kent Hagerman2b216042020-04-03 18:28:56 -0400491func (agent *LogicalAgent) deleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000492 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400493 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
494 return err
495 }
496 defer agent.requestQueue.RequestComplete()
Hardik Windlassc704def2020-02-26 18:23:19 +0000497 // Get the latest logical device info
498 ld := agent.getLogicalDeviceWithoutLock()
499
Hardik Windlassc704def2020-02-26 18:23:19 +0000500 updateLogicalPorts := []*voltha.LogicalPort{}
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500501 for _, lport := range ld.Ports {
Hardik Windlassc704def2020-02-26 18:23:19 +0000502 // Save NNI ports only
503 if agent.isNNIPort(lport.DevicePortNo) {
504 updateLogicalPorts = append(updateLogicalPorts, lport)
505 }
506 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500507 if len(updateLogicalPorts) < len(ld.Ports) {
Hardik Windlassc704def2020-02-26 18:23:19 +0000508 // Updating the logical device will trigger the port change events to be populated to the controller
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500509 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, ld, updateLogicalPorts); err != nil {
Hardik Windlassc704def2020-02-26 18:23:19 +0000510 return err
511 }
512 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000513 logger.Debugw("no-change-required", log.Fields{"logical-device-id": agent.logicalDeviceID})
Hardik Windlassc704def2020-02-26 18:23:19 +0000514 }
515 return nil
516}
517
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500518func clonePorts(ports []*voltha.LogicalPort) []*voltha.LogicalPort {
519 return proto.Clone(&voltha.LogicalPorts{Items: ports}).(*voltha.LogicalPorts).Items
520}
521
522//updateLogicalDevicePortsWithoutLock updates the
Kent Hagerman2b216042020-04-03 18:28:56 -0400523func (agent *LogicalAgent) updateLogicalDevicePortsWithoutLock(ctx context.Context, device *voltha.LogicalDevice, newPorts []*voltha.LogicalPort) error {
Kent Hagermand9cc2e92019-11-04 13:28:15 -0500524 oldPorts := device.Ports
525 device.Ports = newPorts
526 if err := agent.updateLogicalDeviceWithoutLock(ctx, device); err != nil {
527 return err
528 }
529 agent.portUpdated(oldPorts, newPorts)
530 return nil
531}
532
khenaidoo92e62c52018-10-03 14:02:54 -0400533//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
Kent Hagerman2b216042020-04-03 18:28:56 -0400534func (agent *LogicalAgent) updateLogicalDeviceWithoutLock(ctx context.Context, logicalDevice *voltha.LogicalDevice) error {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400535 if agent.stopped {
536 return errors.New("logical device agent stopped")
537 }
538
npujar467fe752020-01-16 20:17:45 +0530539 updateCtx := context.WithValue(ctx, model.RequestTimestamp, time.Now().UnixNano())
Kent Hagerman4f355f52020-03-30 16:01:33 -0400540 if err := agent.clusterDataProxy.Update(updateCtx, "logical_devices/"+agent.logicalDeviceID, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000541 logger.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530542 return err
543 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400544
khenaidoo442e7c72020-03-10 16:13:48 -0400545 agent.logicalDevice = logicalDevice
546
khenaidoo92e62c52018-10-03 14:02:54 -0400547 return nil
548}
549
khenaidoo820197c2020-02-13 16:35:33 -0500550//generateDeviceRoutesIfNeeded generates the device routes if the logical device has been updated since the last time
khenaidoo4c9e5592019-09-09 16:20:41 -0400551//that device graph was generated.
Kent Hagerman2b216042020-04-03 18:28:56 -0400552func (agent *LogicalAgent) generateDeviceRoutesIfNeeded(ctx context.Context) error {
khenaidoo820197c2020-02-13 16:35:33 -0500553 agent.lockDeviceRoutes.Lock()
554 defer agent.lockDeviceRoutes.Unlock()
555
khenaidoo442e7c72020-03-10 16:13:48 -0400556 ld, err := agent.GetLogicalDevice(ctx)
557 if err != nil {
558 return err
559 }
khenaidoo820197c2020-02-13 16:35:33 -0500560
561 if agent.deviceRoutes != nil && agent.deviceRoutes.IsUpToDate(ld) {
npujar1d86a522019-11-14 17:11:16 +0530562 return nil
563 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000564 logger.Debug("Generation of device route required")
khenaidoo820197c2020-02-13 16:35:33 -0500565 if err := agent.buildRoutes(ctx); err != nil {
566 return err
567 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400568 return nil
569}
570
khenaidoo19d7b632018-10-30 10:49:50 -0400571//updateFlowTable updates the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400572func (agent *LogicalAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
573 logger.Debug("UpdateFlowTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400574 if flow == nil {
575 return nil
576 }
khenaidoo820197c2020-02-13 16:35:33 -0500577 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400578 return err
579 }
khenaidoo19d7b632018-10-30 10:49:50 -0400580 switch flow.GetCommand() {
581 case ofp.OfpFlowModCommand_OFPFC_ADD:
npujar467fe752020-01-16 20:17:45 +0530582 return agent.flowAdd(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400583 case ofp.OfpFlowModCommand_OFPFC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530584 return agent.flowDelete(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400585 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
npujar467fe752020-01-16 20:17:45 +0530586 return agent.flowDeleteStrict(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400587 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
588 return agent.flowModify(flow)
589 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
590 return agent.flowModifyStrict(flow)
591 }
592 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530593 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400594}
595
596//updateGroupTable updates the group table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400597func (agent *LogicalAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000598 logger.Debug("updateGroupTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400599 if groupMod == nil {
600 return nil
601 }
khenaidoo820197c2020-02-13 16:35:33 -0500602 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400603 return err
604 }
khenaidoo820197c2020-02-13 16:35:33 -0500605
khenaidoo19d7b632018-10-30 10:49:50 -0400606 switch groupMod.GetCommand() {
607 case ofp.OfpGroupModCommand_OFPGC_ADD:
npujar467fe752020-01-16 20:17:45 +0530608 return agent.groupAdd(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400609 case ofp.OfpGroupModCommand_OFPGC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530610 return agent.groupDelete(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400611 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530612 return agent.groupModify(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400613 }
614 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530615 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400616}
617
Manikkaraj kb1a10922019-07-29 12:10:34 -0400618// updateMeterTable updates the meter table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400619func (agent *LogicalAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000620 logger.Debug("updateMeterTable")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400621 if meterMod == nil {
622 return nil
623 }
624 switch meterMod.GetCommand() {
625 case ofp.OfpMeterModCommand_OFPMC_ADD:
npujar467fe752020-01-16 20:17:45 +0530626 return agent.meterAdd(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400627 case ofp.OfpMeterModCommand_OFPMC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530628 return agent.meterDelete(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400629 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530630 return agent.meterModify(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400631 }
632 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530633 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400634
635}
636
Kent Hagerman2b216042020-04-03 18:28:56 -0400637func (agent *LogicalAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000638 logger.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400639 if meterMod == nil {
640 return nil
641 }
khenaidoo442e7c72020-03-10 16:13:48 -0400642 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
643 return err
644 }
645 defer agent.requestQueue.RequestComplete()
Girish Kumarf56a4682020-03-20 20:07:46 +0000646 logger.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500647 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400648
649 var meters []*ofp.OfpMeterEntry
650 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
651 meters = lDevice.Meters.Items
652 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000653 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400654
655 for _, meter := range meters {
656 if meterMod.MeterId == meter.Config.MeterId {
Girish Kumarf56a4682020-03-20 20:07:46 +0000657 logger.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400658 return nil
659 }
660 }
661
662 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
663 meters = append(meters, meterEntry)
664 //Update model
npujar467fe752020-01-16 20:17:45 +0530665 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, &ofp.Meters{Items: meters}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000666 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400667 return err
668 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000669 logger.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400670 return nil
671}
672
Kent Hagerman2b216042020-04-03 18:28:56 -0400673func (agent *LogicalAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000674 logger.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400675 if meterMod == nil {
676 return nil
677 }
khenaidoo442e7c72020-03-10 16:13:48 -0400678 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
679 return err
680 }
681 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400682
khenaidoo6e55d9e2019-12-12 18:26:26 -0500683 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400684
685 var meters []*ofp.OfpMeterEntry
686 var flows []*ofp.OfpFlowStats
687 updatedFlows := make([]*ofp.OfpFlowStats, 0)
688 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
689 meters = lDevice.Meters.Items
690 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400691
692 changedMeter := false
693 changedFow := false
Girish Kumarf56a4682020-03-20 20:07:46 +0000694 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400695 for index, meter := range meters {
696 if meterMod.MeterId == meter.Config.MeterId {
697 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530698 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400699 meters = append(meters[:index], meters[index+1:]...)
Girish Kumarf56a4682020-03-20 20:07:46 +0000700 logger.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400701 changedMeter = true
702 break
703 }
704 }
705 if changedMeter {
706 //Update model
707 metersToUpdate := &ofp.Meters{}
708 if lDevice.Meters != nil {
709 metersToUpdate = &ofp.Meters{Items: meters}
710 }
npujar467fe752020-01-16 20:17:45 +0530711 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000712 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400713 return err
714 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000715 logger.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400716
717 }
718 if changedFow {
719 //Update model
npujar467fe752020-01-16 20:17:45 +0530720 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: updatedFlows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000721 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400722 return err
723 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000724 logger.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
Manikkaraj kb1a10922019-07-29 12:10:34 -0400725 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
726 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000727 logger.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400728 return nil
729}
730
Kent Hagerman2b216042020-04-03 18:28:56 -0400731func (agent *LogicalAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000732 logger.Debug("meterModify")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400733 if meterMod == nil {
734 return nil
735 }
khenaidoo442e7c72020-03-10 16:13:48 -0400736 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
737 return err
738 }
739 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400740
khenaidoo6e55d9e2019-12-12 18:26:26 -0500741 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400742
743 var meters []*ofp.OfpMeterEntry
744 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
745 meters = lDevice.Meters.Items
746 }
747 changedMeter := false
748 for index, meter := range meters {
749 if meterMod.MeterId == meter.Config.MeterId {
750 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
751 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
752 meters[index] = newmeterEntry
753 changedMeter = true
Girish Kumarf56a4682020-03-20 20:07:46 +0000754 logger.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400755 break
756 }
757 }
758 if changedMeter {
759 //Update model
760 metersToUpdate := &ofp.Meters{}
761 if lDevice.Meters != nil {
762 metersToUpdate = &ofp.Meters{Items: meters}
763 }
npujar467fe752020-01-16 20:17:45 +0530764 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000765 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400766 return err
767 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000768 logger.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400769 return nil
770 }
771
Girish Kumarf56a4682020-03-20 20:07:46 +0000772 logger.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530773 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400774
775}
776
Kent Hagerman2b216042020-04-03 18:28:56 -0400777func (agent *LogicalAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000778 logger.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400779 changed := false
780 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
781 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530782 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Girish Kumarf56a4682020-03-20 20:07:46 +0000783 logger.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400784 flows = append(flows[:index], flows[index+1:]...)
785 changed = true
786 }
787 }
788 return changed, flows
789}
790
Kent Hagerman2b216042020-04-03 18:28:56 -0400791func (agent *LogicalAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400792
793 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530794 meterID := fu.GetMeterIdFromFlow(flow)
Girish Kumarf56a4682020-03-20 20:07:46 +0000795 logger.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
npujar1d86a522019-11-14 17:11:16 +0530796 if meterID == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000797 logger.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400798 return false
799 }
800 if meters == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000801 logger.Debug("No meters present in logical device")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400802 return false
803 }
804 changedMeter := false
805 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530806 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400807 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530808 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400809 changedMeter = true
810 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530811 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400812 changedMeter = true
813 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000814 logger.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400815 break
816 }
817 }
818 return changedMeter
819}
820
khenaidoo19d7b632018-10-30 10:49:50 -0400821//flowAdd adds a flow to the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400822func (agent *LogicalAgent) flowAdd(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000823 logger.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400824 if mod == nil {
825 return nil
826 }
khenaidoo442e7c72020-03-10 16:13:48 -0400827 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
828 return err
829 }
830 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -0400831
khenaidoo6e55d9e2019-12-12 18:26:26 -0500832 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400833
834 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400835 var meters []*ofp.OfpMeterEntry
836 var flow *ofp.OfpFlowStats
Scott Bakerfdea1e32020-02-21 15:35:41 -0800837 var err error
Manikkaraj kb1a10922019-07-29 12:10:34 -0400838
khenaidoo19d7b632018-10-30 10:49:50 -0400839 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
840 flows = lDevice.Flows.Items
841 }
842
Manikkaraj kb1a10922019-07-29 12:10:34 -0400843 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
844 meters = lDevice.Meters.Items
845 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400846 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400847 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400848 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400849 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
850 if checkOverlap {
851 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
852 // TODO: should this error be notified other than being logged?
Girish Kumarf56a4682020-03-20 20:07:46 +0000853 logger.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400854 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400855 // Add flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800856 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
857 if err != nil {
858 return err
859 }
khenaidoo19d7b632018-10-30 10:49:50 -0400860 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400861 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400862 changed = true
863 }
864 } else {
Scott Bakerfdea1e32020-02-21 15:35:41 -0800865 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
866 if err != nil {
867 return err
868 }
khenaidoo19d7b632018-10-30 10:49:50 -0400869 idx := fu.FindFlows(flows, flow)
870 if idx >= 0 {
871 oldFlow := flows[idx]
872 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
873 flow.ByteCount = oldFlow.ByteCount
874 flow.PacketCount = oldFlow.PacketCount
875 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400876 if !reflect.DeepEqual(oldFlow, flow) {
877 flows[idx] = flow
878 updatedFlows = append(updatedFlows, flow)
879 changed = true
880 updated = true
881 }
882 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400883 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400884 updatedFlows = append(updatedFlows, flow)
885 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400886 }
khenaidoo19d7b632018-10-30 10:49:50 -0400887 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000888 logger.Debugw("flowAdd-changed", log.Fields{"changed": changed})
khenaidoo4c9e5592019-09-09 16:20:41 -0400889
khenaidoo19d7b632018-10-30 10:49:50 -0400890 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400891 var flowMetadata voltha.FlowMetadata
892 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
Girish Kumarf56a4682020-03-20 20:07:46 +0000893 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400894 return err
895 }
khenaidoo820197c2020-02-13 16:35:33 -0500896 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
897 if err != nil {
898 return err
899 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000900 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -0400901
khenaidoo19d7b632018-10-30 10:49:50 -0400902 // Update model
npujar467fe752020-01-16 20:17:45 +0530903 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000904 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400905 return err
906 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400907 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400908 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
909 metersToUpdate := &ofp.Meters{}
910 if lDevice.Meters != nil {
911 metersToUpdate = &ofp.Meters{Items: meters}
912 }
913 if changedMeterStats {
914 //Update model
npujar467fe752020-01-16 20:17:45 +0530915 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000916 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400917 return err
918 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000919 logger.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400920
921 }
922 }
khenaidoo442e7c72020-03-10 16:13:48 -0400923 // Send the flows to the devices
924 respChannels := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &flowMetadata)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400925
khenaidoo442e7c72020-03-10 16:13:48 -0400926 // Create the go routines to wait
927 go func() {
928 // Wait for completion
929 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChannels...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000930 logger.Warnw("failure-to-add-flows", log.Fields{"errors": res, "logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400931 // TODO : revert added flow
932 }
933 }()
khenaidoo19d7b632018-10-30 10:49:50 -0400934 }
khenaidoo19d7b632018-10-30 10:49:50 -0400935 return nil
936}
937
npujar1d86a522019-11-14 17:11:16 +0530938// GetMeterConfig returns meter config
Kent Hagerman2b216042020-04-03 18:28:56 -0400939func (agent *LogicalAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400940 m := make(map[uint32]bool)
941 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530942 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400943 foundMeter := false
944 // Meter is present in the flow , Get from logical device
945 for _, meter := range meters {
946 if flowMeterID == meter.Config.MeterId {
947 metadata.Meters = append(metadata.Meters, meter.Config)
Girish Kumarf56a4682020-03-20 20:07:46 +0000948 logger.Debugw("Found meter in logical device",
Manikkaraj kb1a10922019-07-29 12:10:34 -0400949 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
950 m[flowMeterID] = true
951 foundMeter = true
952 break
953 }
954 }
955 if !foundMeter {
Girish Kumarf56a4682020-03-20 20:07:46 +0000956 logger.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +0530957 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400958 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
959 }
960 }
961 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000962 logger.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400963 return nil
964
965}
966
khenaidoo19d7b632018-10-30 10:49:50 -0400967//flowDelete deletes a flow from the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -0400968func (agent *LogicalAgent) flowDelete(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000969 logger.Debug("flowDelete")
khenaidoo19d7b632018-10-30 10:49:50 -0400970 if mod == nil {
971 return nil
972 }
khenaidoo442e7c72020-03-10 16:13:48 -0400973 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
974 return err
975 }
976 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -0400977
khenaidoo6e55d9e2019-12-12 18:26:26 -0500978 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400979
Manikkaraj kb1a10922019-07-29 12:10:34 -0400980 var meters []*ofp.OfpMeterEntry
981 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +0000982 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -0400983
984 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
985 flows = lDevice.Flows.Items
986 }
987
988 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
989 meters = lDevice.Meters.Items
990 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +0000991
992 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
993 flowGroups = lDevice.FlowGroups.Items
994 }
995
khenaidoo19d7b632018-10-30 10:49:50 -0400996 //build a list of what to keep vs what to delete
997 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400998 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400999 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -04001000 // Check whether the flow and the flowmod matches
Scott Bakerfdea1e32020-02-21 15:35:41 -08001001 fs, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1002 if err != nil {
1003 return err
1004 }
1005 if fu.FlowMatch(f, fs) {
khenaidoo0458db62019-06-20 08:50:36 -04001006 toDelete = append(toDelete, f)
1007 continue
1008 }
1009 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -04001010 if !fu.FlowMatchesMod(f, mod) {
1011 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -04001012 } else {
1013 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -04001014 }
1015 }
1016
Girish Kumarf56a4682020-03-20 20:07:46 +00001017 logger.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -04001018
khenaidoo19d7b632018-10-30 10:49:50 -04001019 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -04001020 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001021 var flowMetadata voltha.FlowMetadata
1022 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
Girish Kumarf56a4682020-03-20 20:07:46 +00001023 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001024 return errors.New("Meter-referred-in-flows-not-present")
1025 }
khenaidoo820197c2020-02-13 16:35:33 -05001026 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{Items: flowGroups})
1027 if err != nil {
1028 return err
1029 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001030 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001031
npujar467fe752020-01-16 20:17:45 +05301032 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: toKeep}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001033 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001034 return err
1035 }
khenaidoo442e7c72020-03-10 16:13:48 -04001036
1037 // Update the devices
1038 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1039
1040 // Wait for the responses
1041 go func() {
1042 // Wait for completion
1043 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001044 logger.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001045 // TODO: Revert the flow deletion
1046 }
1047 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001048 }
1049
1050 //TODO: send announcement on delete
1051 return nil
1052}
1053
Kent Hagerman2b216042020-04-03 18:28:56 -04001054func (agent *LogicalAgent) addFlowsAndGroupsToDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001055 logger.Debugw("send-add-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001056
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001057 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301058 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001059 response := coreutils.NewResponse()
1060 responses = append(responses, response)
1061 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001062 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1063 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301064 if err := agent.deviceMgr.addFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001065 logger.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001066 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001067 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001068 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301069 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001070 }
khenaidoo442e7c72020-03-10 16:13:48 -04001071 // Return responses (an array of channels) for the caller to wait for a response from the far end.
1072 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001073}
khenaidoo19d7b632018-10-30 10:49:50 -04001074
Kent Hagerman2b216042020-04-03 18:28:56 -04001075func (agent *LogicalAgent) deleteFlowsAndGroupsFromDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001076 logger.Debugw("send-delete-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001077
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001078 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301079 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001080 response := coreutils.NewResponse()
1081 responses = append(responses, response)
1082 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001083 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1084 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301085 if err := agent.deviceMgr.deleteFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001086 logger.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001087 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001088 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001089 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301090 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001091 }
khenaidoo442e7c72020-03-10 16:13:48 -04001092 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001093}
1094
Kent Hagerman2b216042020-04-03 18:28:56 -04001095func (agent *LogicalAgent) updateFlowsAndGroupsOfDevice(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001096 logger.Debugw("send-update-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001097
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001098 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301099 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001100 response := coreutils.NewResponse()
1101 responses = append(responses, response)
1102 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001103 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1104 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301105 if err := agent.deviceMgr.updateFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001107 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001108 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001109 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301110 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001111 }
khenaidoo442e7c72020-03-10 16:13:48 -04001112 return responses
khenaidoo19d7b632018-10-30 10:49:50 -04001113}
1114
1115//flowDeleteStrict deletes a flow from the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -04001116func (agent *LogicalAgent) flowDeleteStrict(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001117 logger.Debug("flowDeleteStrict")
khenaidoo19d7b632018-10-30 10:49:50 -04001118 if mod == nil {
1119 return nil
1120 }
khenaidoo442e7c72020-03-10 16:13:48 -04001121 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1122 return err
1123 }
1124 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001125
khenaidoo6e55d9e2019-12-12 18:26:26 -05001126 lDevice := agent.getLogicalDeviceWithoutLock()
1127
Manikkaraj kb1a10922019-07-29 12:10:34 -04001128 var meters []*ofp.OfpMeterEntry
1129 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001130 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -04001131 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1132 meters = lDevice.Meters.Items
1133 }
1134 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1135 flows = lDevice.Flows.Items
1136 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001137 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
1138 flowGroups = lDevice.FlowGroups.Items
1139 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001140
1141 changedFlow := false
1142 changedMeter := false
Scott Bakerfdea1e32020-02-21 15:35:41 -08001143 flow, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1144 if err != nil {
1145 return err
1146 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001147 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001148 idx := fu.FindFlows(flows, flow)
1149 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001150 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001151 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001152 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001153 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001154 } else {
npujar1d86a522019-11-14 17:11:16 +05301155 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001156 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001157 if changedMeter {
1158 //Update model
1159 metersToUpdate := &ofp.Meters{}
1160 if lDevice.Meters != nil {
1161 metersToUpdate = &ofp.Meters{Items: meters}
1162 }
npujar467fe752020-01-16 20:17:45 +05301163 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001164 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001165 return err
1166 }
khenaidoo19d7b632018-10-30 10:49:50 -04001167
Manikkaraj kb1a10922019-07-29 12:10:34 -04001168 }
1169 if changedFlow {
1170 var flowMetadata voltha.FlowMetadata
1171 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001172 logger.Error("meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001173 return err
1174 }
khenaidoo820197c2020-02-13 16:35:33 -05001175 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{Items: flowGroups})
1176 if err != nil {
1177 return err
1178 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001179 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001180
npujar467fe752020-01-16 20:17:45 +05301181 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001182 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001183 return err
1184 }
khenaidoo442e7c72020-03-10 16:13:48 -04001185
1186 // Update the devices
1187 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1188
1189 // Wait for completion
1190 go func() {
1191 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001192 logger.Warnw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001193 //TODO: Revert flow changes
1194 }
1195 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001196 }
khenaidoo19d7b632018-10-30 10:49:50 -04001197 return nil
1198}
1199
1200//flowModify modifies a flow from the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -04001201func (agent *LogicalAgent) flowModify(mod *ofp.OfpFlowMod) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001202 return errors.New("flowModify not implemented")
1203}
1204
1205//flowModifyStrict deletes a flow from the flow table of that logical device
Kent Hagerman2b216042020-04-03 18:28:56 -04001206func (agent *LogicalAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001207 return errors.New("flowModifyStrict not implemented")
1208}
1209
Kent Hagerman2b216042020-04-03 18:28:56 -04001210func (agent *LogicalAgent) groupAdd(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001211 logger.Debug("groupAdd")
khenaidoo19d7b632018-10-30 10:49:50 -04001212 if groupMod == nil {
1213 return nil
1214 }
khenaidoo442e7c72020-03-10 16:13:48 -04001215 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1216 return err
1217 }
1218 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001219
khenaidoo6e55d9e2019-12-12 18:26:26 -05001220 lDevice := agent.getLogicalDeviceWithoutLock()
1221
khenaidoo19d7b632018-10-30 10:49:50 -04001222 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001223 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001224 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001225
Esin Karaman2ea59212019-12-06 11:41:58 +00001226 deviceRules := fu.NewDeviceRules()
1227 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1228 fg := fu.NewFlowsAndGroups()
1229 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1230 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1231
Girish Kumarf56a4682020-03-20 20:07:46 +00001232 logger.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001233
npujar467fe752020-01-16 20:17:45 +05301234 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001236 return err
1237 }
khenaidoo442e7c72020-03-10 16:13:48 -04001238
1239 // Update the devices
1240 respChnls := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &voltha.FlowMetadata{})
1241
1242 // Wait for completion
1243 go func() {
1244 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001245 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001246 //TODO: Revert flow changes
1247 }
1248 }()
1249 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001250 }
khenaidoo442e7c72020-03-10 16:13:48 -04001251 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001252}
1253
Kent Hagerman2b216042020-04-03 18:28:56 -04001254func (agent *LogicalAgent) groupDelete(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001255 logger.Debug("groupDelete")
khenaidoo19d7b632018-10-30 10:49:50 -04001256 if groupMod == nil {
1257 return nil
1258 }
khenaidoo442e7c72020-03-10 16:13:48 -04001259 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1260 return err
1261 }
1262 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001263
khenaidoo6e55d9e2019-12-12 18:26:26 -05001264 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001265 groups := lDevice.FlowGroups.Items
1266 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301267 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001268 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301269 groupID := groupMod.GroupId
1270 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001271 //TODO we must delete all flows that point to this group and
1272 //signal controller as requested by flow's flag
1273 groups = []*ofp.OfpGroupEntry{}
1274 groupsChanged = true
1275 } else {
npujar1d86a522019-11-14 17:11:16 +05301276 idx := fu.FindGroup(groups, groupID)
1277 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001278 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001279 }
npujar1d86a522019-11-14 17:11:16 +05301280 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1281 groups = append(groups[:idx], groups[idx+1:]...)
1282 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001283 }
khenaidoo0458db62019-06-20 08:50:36 -04001284 if flowsChanged || groupsChanged {
khenaidoo820197c2020-02-13 16:35:33 -05001285 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1286 if err != nil {
1287 return err
1288 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001289 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001290
khenaidoo442e7c72020-03-10 16:13:48 -04001291 if groupsChanged {
1292 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001293 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001294 return err
1295 }
khenaidoo0458db62019-06-20 08:50:36 -04001296 }
khenaidoo442e7c72020-03-10 16:13:48 -04001297 if flowsChanged {
1298 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001299 logger.Errorw("cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001300 return err
1301 }
1302 }
khenaidoo0458db62019-06-20 08:50:36 -04001303
khenaidoo442e7c72020-03-10 16:13:48 -04001304 // Update the devices
1305 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, nil)
1306
1307 // Wait for completion
1308 go func() {
1309 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001310 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001311 //TODO: Revert flow changes
1312 }
1313 }()
khenaidoo43c82122018-11-22 18:38:28 -05001314 }
khenaidoo19d7b632018-10-30 10:49:50 -04001315 return nil
1316}
1317
Kent Hagerman2b216042020-04-03 18:28:56 -04001318func (agent *LogicalAgent) groupModify(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001319 logger.Debug("groupModify")
khenaidoo19d7b632018-10-30 10:49:50 -04001320 if groupMod == nil {
1321 return nil
1322 }
khenaidoo442e7c72020-03-10 16:13:48 -04001323 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1324 return err
1325 }
1326 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001327
khenaidoo6e55d9e2019-12-12 18:26:26 -05001328 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001329 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301330 var groupsChanged bool
1331 groupID := groupMod.GroupId
1332 idx := fu.FindGroup(groups, groupID)
1333 if idx == -1 {
1334 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001335 }
npujar1d86a522019-11-14 17:11:16 +05301336 //replace existing group entry with new group definition
1337 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1338 groups[idx] = groupEntry
1339 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001340 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001341 deviceRules := fu.NewDeviceRules()
1342 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1343 fg := fu.NewFlowsAndGroups()
1344 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1345 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001346
Girish Kumarf56a4682020-03-20 20:07:46 +00001347 logger.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001348
npujar467fe752020-01-16 20:17:45 +05301349 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001350 logger.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001351 return err
1352 }
khenaidoo442e7c72020-03-10 16:13:48 -04001353
1354 // Update the devices
1355 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, &voltha.FlowMetadata{})
1356
1357 // Wait for completion
1358 go func() {
1359 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001360 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001361 //TODO: Revert flow changes
1362 }
1363 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001364 }
1365 return nil
1366}
1367
1368// deleteLogicalPort removes the logical port
Kent Hagerman2b216042020-04-03 18:28:56 -04001369func (agent *LogicalAgent) deleteLogicalPort(ctx context.Context, lPort *voltha.LogicalPort) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001370 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1371 return err
1372 }
1373 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001374
khenaidoo6e55d9e2019-12-12 18:26:26 -05001375 logicalDevice := agent.getLogicalDeviceWithoutLock()
1376
khenaidoo92e62c52018-10-03 14:02:54 -04001377 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001378 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001379 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001380 index = i
1381 break
1382 }
1383 }
1384 if index >= 0 {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001385 clonedPorts := clonePorts(logicalDevice.Ports)
1386 if index < len(clonedPorts)-1 {
1387 copy(clonedPorts[index:], clonedPorts[index+1:])
1388 }
1389 clonedPorts[len(clonedPorts)-1] = nil
1390 clonedPorts = clonedPorts[:len(clonedPorts)-1]
Girish Kumarf56a4682020-03-20 20:07:46 +00001391 logger.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001392 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, logicalDevice, clonedPorts); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001393 logger.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001394 return err
1395 }
khenaidoo820197c2020-02-13 16:35:33 -05001396
1397 // Remove the logical port from cache
1398 agent.deleteLogicalPortsFromMap([]uint32{lPort.DevicePortNo})
1399
1400 // Reset the logical device routes
1401 go func() {
1402 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001403 logger.Warnw("device-routes-not-ready", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001404 }
1405 }()
khenaidoo92e62c52018-10-03 14:02:54 -04001406 }
1407 return nil
khenaidoob9203542018-09-17 22:56:37 -04001408}
1409
khenaidoo0a822f92019-05-08 15:15:57 -04001410// deleteLogicalPorts removes the logical ports associated with that deviceId
Kent Hagerman2b216042020-04-03 18:28:56 -04001411func (agent *LogicalAgent) deleteLogicalPorts(ctx context.Context, deviceID string) error {
Andrea Campanella09400bd2020-04-02 11:58:04 +02001412 logger.Debugw("deleting-logical-ports", log.Fields{"device-id": deviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001413 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1414 return err
1415 }
1416 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -04001417
khenaidoo6e55d9e2019-12-12 18:26:26 -05001418 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo820197c2020-02-13 16:35:33 -05001419 lPortstoKeep := []*voltha.LogicalPort{}
1420 lPortsNoToDelete := []uint32{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001421 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301422 if logicalPort.DeviceId != deviceID {
khenaidoo820197c2020-02-13 16:35:33 -05001423 lPortstoKeep = append(lPortstoKeep, logicalPort)
1424 } else {
1425 lPortsNoToDelete = append(lPortsNoToDelete, logicalPort.DevicePortNo)
khenaidoo0a822f92019-05-08 15:15:57 -04001426 }
1427 }
Andrea Campanella09400bd2020-04-02 11:58:04 +02001428 logger.Debugw("deleted-logical-ports", log.Fields{"ports": lPortstoKeep})
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001429 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, logicalDevice, lPortstoKeep); err != nil {
Andrea Campanella09400bd2020-04-02 11:58:04 +02001430 logger.Errorw("logical-device-update-failed", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001431 return err
1432 }
khenaidoo820197c2020-02-13 16:35:33 -05001433 // Remove the port from the cached logical ports set
1434 agent.deleteLogicalPortsFromMap(lPortsNoToDelete)
1435
1436 // Reset the logical device routes
1437 go func() {
1438 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001439 logger.Warnw("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001440 }
1441 }()
khenaidoo0a822f92019-05-08 15:15:57 -04001442
1443 return nil
1444}
1445
khenaidoo19d7b632018-10-30 10:49:50 -04001446// enableLogicalPort enables the logical port
Kent Hagerman2b216042020-04-03 18:28:56 -04001447func (agent *LogicalAgent) enableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001448 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1449 return err
1450 }
1451 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001452
khenaidoo6e55d9e2019-12-12 18:26:26 -05001453 logicalDevice := agent.getLogicalDeviceWithoutLock()
1454
khenaidoo19d7b632018-10-30 10:49:50 -04001455 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001456 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301457 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001458 index = i
1459 break
1460 }
1461 }
1462 if index >= 0 {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001463 clonedPorts := clonePorts(logicalDevice.Ports)
1464 clonedPorts[index].OfpPort.Config = clonedPorts[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1465 return agent.updateLogicalDevicePortsWithoutLock(ctx, logicalDevice, clonedPorts)
khenaidoo19d7b632018-10-30 10:49:50 -04001466 }
npujar1d86a522019-11-14 17:11:16 +05301467 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001468}
1469
1470// disableLogicalPort disabled the logical port
Kent Hagerman2b216042020-04-03 18:28:56 -04001471func (agent *LogicalAgent) disableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001472 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1473 return err
1474 }
1475 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001476
1477 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001478 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001479 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001480 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301481 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001482 index = i
1483 break
1484 }
1485 }
1486 if index >= 0 {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001487 clonedPorts := clonePorts(logicalDevice.Ports)
1488 clonedPorts[index].OfpPort.Config = (clonedPorts[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1489 return agent.updateLogicalDevicePortsWithoutLock(ctx, logicalDevice, clonedPorts)
khenaidoo19d7b632018-10-30 10:49:50 -04001490 }
npujar1d86a522019-11-14 17:11:16 +05301491 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001492}
1493
Kent Hagerman2b216042020-04-03 18:28:56 -04001494func (agent *LogicalAgent) getPreCalculatedRoute(ingress, egress uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001495 logger.Debugw("ROUTE", log.Fields{"len": len(agent.deviceRoutes.Routes)})
khenaidoo820197c2020-02-13 16:35:33 -05001496 for routeLink, route := range agent.deviceRoutes.Routes {
Girish Kumarf56a4682020-03-20 20:07:46 +00001497 logger.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001498 if ingress == routeLink.Ingress && egress == routeLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -05001499 return route, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001500 }
1501 }
khenaidoo820197c2020-02-13 16:35:33 -05001502 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingress, egress)
khenaidoo89b0e942018-10-21 21:11:33 -04001503}
1504
npujar1d86a522019-11-14 17:11:16 +05301505// GetRoute returns route
Kent Hagerman2b216042020-04-03 18:28:56 -04001506func (agent *LogicalAgent) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001507 logger.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo820197c2020-02-13 16:35:33 -05001508 routes := make([]route.Hop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001509
khenaidoo19d7b632018-10-30 10:49:50 -04001510 // Note: A port value of 0 is equivalent to a nil port
1511
khenaidoo89b0e942018-10-21 21:11:33 -04001512 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001513 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001514 logger.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo2c6a0992019-04-29 13:46:56 -04001515 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001516 //This is a trap on the NNI Port
khenaidoo820197c2020-02-13 16:35:33 -05001517 if len(agent.deviceRoutes.Routes) == 0 {
khenaidoo8f474192019-04-03 17:20:44 -04001518 // If there are no routes set (usually when the logical device has only NNI port(s), then just return an
Humera Kouser4ff89012019-08-25 19:01:51 -04001519 // route with same IngressHop and EgressHop
khenaidoo820197c2020-02-13 16:35:33 -05001520 hop := route.Hop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001521 routes = append(routes, hop)
1522 routes = append(routes, hop)
khenaidoo820197c2020-02-13 16:35:33 -05001523 return routes, nil
khenaidoo8f474192019-04-03 17:20:44 -04001524 }
khenaidoo89b0e942018-10-21 21:11:33 -04001525 //Return a 'half' route to make the flow decomposer logic happy
khenaidoo820197c2020-02-13 16:35:33 -05001526 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001527 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001528 routes = append(routes, route.Hop{}) // first hop is set to empty
1529 routes = append(routes, path[1])
1530 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001531 }
1532 }
khenaidoo820197c2020-02-13 16:35:33 -05001533 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001534 }
1535 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001536 var err error
1537 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001538 logger.Warnw("no-nni-port", log.Fields{"error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001539 return nil, err
khenaidoo2c6a0992019-04-29 13:46:56 -04001540 }
khenaidoo89b0e942018-10-21 21:11:33 -04001541 }
1542 //If ingress port is not specified (nil), it may be a wildcarded
1543 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1544 //in which case we need to create a half-route where only the egress
1545 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001546 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001547 // We can use the 2nd hop of any upstream route, so just find the first upstream:
khenaidoo820197c2020-02-13 16:35:33 -05001548 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001549 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001550 routes = append(routes, route.Hop{}) // first hop is set to empty
1551 routes = append(routes, path[1])
1552 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001553 }
1554 }
khenaidoo820197c2020-02-13 16:35:33 -05001555 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001556 }
1557 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001558 if egressPortNo == 0 {
khenaidoo820197c2020-02-13 16:35:33 -05001559 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001560 if routeLink.Ingress == ingressPortNo {
khenaidoo820197c2020-02-13 16:35:33 -05001561 routes = append(routes, path[0])
1562 routes = append(routes, route.Hop{})
1563 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001564 }
1565 }
khenaidoo820197c2020-02-13 16:35:33 -05001566 return nil, status.Errorf(codes.FailedPrecondition, "no downstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001567 }
khenaidoo89b0e942018-10-21 21:11:33 -04001568 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001569 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001570}
1571
khenaidoo3d3b8c22019-05-22 18:10:39 -04001572//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1573//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1574//device is already held. Therefore it is safe to retrieve the logical device without lock.
Kent Hagerman2b216042020-04-03 18:28:56 -04001575func (agent *LogicalAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
khenaidoo89b0e942018-10-21 21:11:33 -04001576 lPorts := make([]uint32, 0)
1577 var exclPort uint32
1578 if len(excludePort) == 1 {
1579 exclPort = excludePort[0]
1580 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001581 lDevice := agent.getLogicalDeviceWithoutLock()
1582 for _, port := range lDevice.Ports {
1583 if port.OfpPort.PortNo != exclPort {
1584 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001585 }
1586 }
1587 return lPorts
1588}
khenaidoo19d7b632018-10-30 10:49:50 -04001589
khenaidoo820197c2020-02-13 16:35:33 -05001590// GetDeviceRoutes returns device graph
Kent Hagerman2b216042020-04-03 18:28:56 -04001591func (agent *LogicalAgent) GetDeviceRoutes() *route.DeviceRoutes {
khenaidoo820197c2020-02-13 16:35:33 -05001592 return agent.deviceRoutes
khenaidoo19d7b632018-10-30 10:49:50 -04001593}
1594
khenaidoo820197c2020-02-13 16:35:33 -05001595//rebuildRoutes rebuilds the device routes
Kent Hagerman2b216042020-04-03 18:28:56 -04001596func (agent *LogicalAgent) buildRoutes(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001597 logger.Debugf("building-routes", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001598 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1599 return err
1600 }
1601 defer agent.requestQueue.RequestComplete()
1602
khenaidoo820197c2020-02-13 16:35:33 -05001603 if agent.deviceRoutes == nil {
1604 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001605 }
1606 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001607 lDevice := agent.getLogicalDeviceWithoutLock()
1608
khenaidoo820197c2020-02-13 16:35:33 -05001609 if err := agent.deviceRoutes.ComputeRoutes(ctx, lDevice.Ports); err != nil {
1610 return err
1611 }
1612 if err := agent.deviceRoutes.Print(); err != nil {
1613 return err
1614 }
1615
khenaidoo2c6a0992019-04-29 13:46:56 -04001616 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001617}
1618
khenaidoo820197c2020-02-13 16:35:33 -05001619//updateRoutes updates the device routes
Kent Hagerman2b216042020-04-03 18:28:56 -04001620func (agent *LogicalAgent) updateRoutes(ctx context.Context, lp *voltha.LogicalPort) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001621 logger.Debugw("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001622 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1623 return err
1624 }
1625 defer agent.requestQueue.RequestComplete()
1626
khenaidoo820197c2020-02-13 16:35:33 -05001627 if agent.deviceRoutes == nil {
1628 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001629 }
khenaidoo820197c2020-02-13 16:35:33 -05001630 if err := agent.deviceRoutes.AddPort(ctx, lp, agent.logicalDevice.Ports); err != nil {
1631 return err
khenaidoo0a822f92019-05-08 15:15:57 -04001632 }
khenaidoo820197c2020-02-13 16:35:33 -05001633 if err := agent.deviceRoutes.Print(); err != nil {
1634 return err
1635 }
1636 return nil
khenaidoo0a822f92019-05-08 15:15:57 -04001637}
1638
khenaidoofc1314d2019-03-14 09:34:21 -04001639// diff go over two lists of logical ports and return what's new, what's changed and what's removed.
khenaidoo910204f2019-04-08 17:56:40 -04001640func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001641 newPorts = make([]*voltha.LogicalPort, 0)
1642 changedPorts = make([]*voltha.LogicalPort, 0)
1643 deletedPorts = make([]*voltha.LogicalPort, 0)
1644 for _, o := range oldList {
1645 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001646 for _, n := range newList {
1647 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001648 found = true
1649 break
1650 }
1651 }
1652 if !found {
1653 deletedPorts = append(deletedPorts, o)
1654 }
khenaidoofc1314d2019-03-14 09:34:21 -04001655 }
1656 for _, n := range newList {
1657 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001658 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001659 for _, o := range oldList {
1660 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001661 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001662 found = true
1663 break
1664 }
1665 }
1666 if !found {
1667 newPorts = append(newPorts, n)
1668 }
khenaidoo2bc48282019-07-16 18:13:46 -04001669 if changed {
1670 changedPorts = append(changedPorts, n)
1671 }
khenaidoofc1314d2019-03-14 09:34:21 -04001672 }
1673 return
1674}
1675
1676// portUpdated is invoked when a port is updated on the logical device. Until
1677// the POST_ADD notification is fixed, we will use the logical device to
1678// update that data.
Kent Hagerman2b216042020-04-03 18:28:56 -04001679func (agent *LogicalAgent) portUpdated(oldPorts, newPorts []*voltha.LogicalPort) interface{} {
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001680 if reflect.DeepEqual(oldPorts, newPorts) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001681 logger.Debug("ports-have-not-changed")
khenaidoofc1314d2019-03-14 09:34:21 -04001682 return nil
1683 }
1684
1685 // Get the difference between the two list
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001686 newPorts, changedPorts, deletedPorts := diff(oldPorts, newPorts)
khenaidoofc1314d2019-03-14 09:34:21 -04001687
1688 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001689 for _, newP := range newPorts {
Kent Hagerman2b216042020-04-03 18:28:56 -04001690 go agent.ldeviceMgr.eventCallbacks.SendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001691 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001692 }
1693 for _, change := range changedPorts {
Kent Hagerman2b216042020-04-03 18:28:56 -04001694 go agent.ldeviceMgr.eventCallbacks.SendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001695 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001696 }
1697 for _, del := range deletedPorts {
Kent Hagerman2b216042020-04-03 18:28:56 -04001698 go agent.ldeviceMgr.eventCallbacks.SendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001699 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001700 }
1701
1702 return nil
1703}
1704
khenaidoo8f474192019-04-03 17:20:44 -04001705// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1706// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1707// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1708// scenario. This also applies to the case where the port was already added.
Kent Hagerman2b216042020-04-03 18:28:56 -04001709func (agent *LogicalAgent) addNNILogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001710 logger.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
Chaitrashree G S7849b322020-03-29 19:25:49 -04001711
khenaidoo442e7c72020-03-10 16:13:48 -04001712 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1713 return false, err
1714 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001715 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001716 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001717 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001718 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001719 }
khenaidoo442e7c72020-03-10 16:13:48 -04001720 agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001721
khenaidoofc1314d2019-03-14 09:34:21 -04001722 var portCap *ic.PortCapability
1723 var err error
1724 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301725 if portCap, err = agent.deviceMgr.getPortCapability(ctx, device.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001726 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001727 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001728 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001729
khenaidoo442e7c72020-03-10 16:13:48 -04001730 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1731 return false, err
1732 }
1733
1734 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001735 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1736 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001737 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001738 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001739 }
1740
khenaidoofc1314d2019-03-14 09:34:21 -04001741 portCap.Port.RootPort = true
1742 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1743 lp.DeviceId = device.Id
1744 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1745 lp.OfpPort.PortNo = port.PortNo
1746 lp.OfpPort.Name = lp.Id
1747 lp.DevicePortNo = port.PortNo
1748
khenaidoo6e55d9e2019-12-12 18:26:26 -05001749 ld := agent.getLogicalDeviceWithoutLock()
1750
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001751 clonedPorts := clonePorts(ld.Ports)
1752 if clonedPorts == nil {
1753 clonedPorts = make([]*voltha.LogicalPort, 0)
khenaidoofc1314d2019-03-14 09:34:21 -04001754 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001755 clonedPorts = append(clonedPorts, lp)
khenaidoofc1314d2019-03-14 09:34:21 -04001756
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001757 if err = agent.updateLogicalDevicePortsWithoutLock(ctx, ld, clonedPorts); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001758 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001759 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001760 }
khenaidoo910204f2019-04-08 17:56:40 -04001761
khenaidoo820197c2020-02-13 16:35:33 -05001762 // Update the device routes with this new logical port
khenaidoo910204f2019-04-08 17:56:40 -04001763 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001764 go func() {
1765 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001766 logger.Warnw("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": lp.OfpPort.PortNo, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001767 }
1768 }()
khenaidoo910204f2019-04-08 17:56:40 -04001769
khenaidoo8f474192019-04-03 17:20:44 -04001770 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001771}
1772
Kent Hagerman2b216042020-04-03 18:28:56 -04001773func (agent *LogicalAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001774 ldevice := agent.getLogicalDeviceWithoutLock()
1775 for _, lPort := range ldevice.Ports {
1776 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1777 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001778 }
1779 }
1780 return false
1781}
1782
khenaidoo8f474192019-04-03 17:20:44 -04001783// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1784// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1785// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1786// scenario. This also applies to the case where the port was already added.
Kent Hagerman2b216042020-04-03 18:28:56 -04001787func (agent *LogicalAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001788 logger.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001789 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
Girish Kumarf56a4682020-03-20 20:07:46 +00001790 logger.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
khenaidoo8f474192019-04-03 17:20:44 -04001791 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001792 }
khenaidoo442e7c72020-03-10 16:13:48 -04001793 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1794 return false, err
1795 }
1796
khenaidoo1ce37ad2019-03-24 22:07:24 -04001797 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001798 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001799 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001800 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001801 }
khenaidoo442e7c72020-03-10 16:13:48 -04001802 agent.requestQueue.RequestComplete()
khenaidoofc1314d2019-03-14 09:34:21 -04001803 var portCap *ic.PortCapability
1804 var err error
1805 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301806 if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001807 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001808 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001809 }
khenaidoo442e7c72020-03-10 16:13:48 -04001810 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1811 return false, err
1812 }
1813 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001814 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1815 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001816 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001817 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001818 }
khenaidoofc1314d2019-03-14 09:34:21 -04001819 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001820 ldevice := agent.getLogicalDeviceWithoutLock()
1821
Girish Kumarf56a4682020-03-20 20:07:46 +00001822 logger.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
npujar1d86a522019-11-14 17:11:16 +05301823 portCap.Port.RootPort = false
1824 portCap.Port.Id = port.Label
1825 portCap.Port.OfpPort.PortNo = port.PortNo
1826 portCap.Port.DeviceId = childDevice.Id
1827 portCap.Port.DevicePortNo = port.PortNo
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001828 clonedPorts := clonePorts(ldevice.Ports)
1829 if clonedPorts == nil {
1830 clonedPorts = make([]*voltha.LogicalPort, 0)
npujar1d86a522019-11-14 17:11:16 +05301831 }
Kent Hagermand9cc2e92019-11-04 13:28:15 -05001832 clonedPorts = append(clonedPorts, portCap.Port)
1833 if err := agent.updateLogicalDevicePortsWithoutLock(ctx, ldevice, clonedPorts); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301834 return false, err
1835 }
1836 // Update the device graph with this new logical port
1837 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001838
1839 go func() {
1840 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001841 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001842 }
1843 }()
1844
npujar1d86a522019-11-14 17:11:16 +05301845 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001846}
1847
Kent Hagerman2b216042020-04-03 18:28:56 -04001848func (agent *LogicalAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001849 logger.Debugw("packet-out", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001850 "packet": hex.EncodeToString(packet.Data),
1851 "inPort": packet.GetInPort(),
1852 })
khenaidoo68c930b2019-05-13 11:46:51 -04001853 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001854 //frame := packet.GetData()
1855 //TODO: Use a channel between the logical agent and the device agent
npujar467fe752020-01-16 20:17:45 +05301856 if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001857 logger.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001858 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001859}
1860
Kent Hagerman2b216042020-04-03 18:28:56 -04001861func (agent *LogicalAgent) packetIn(port uint32, transactionID string, packet []byte) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001862 logger.Debugw("packet-in", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001863 "port": port,
1864 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301865 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001866 })
khenaidoo68c930b2019-05-13 11:46:51 -04001867 packetIn := fu.MkPacketIn(port, packet)
Kent Hagerman2b216042020-04-03 18:28:56 -04001868 agent.ldeviceMgr.eventCallbacks.SendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Girish Kumarf56a4682020-03-20 20:07:46 +00001869 logger.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001870}
khenaidoo2c6a0992019-04-29 13:46:56 -04001871
Kent Hagerman2b216042020-04-03 18:28:56 -04001872func (agent *LogicalAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001873 agent.lockLogicalPortsNo.Lock()
1874 defer agent.lockLogicalPortsNo.Unlock()
1875 if exist := agent.logicalPortsNo[portNo]; !exist {
1876 agent.logicalPortsNo[portNo] = nniPort
1877 }
1878}
1879
Kent Hagerman2b216042020-04-03 18:28:56 -04001880func (agent *LogicalAgent) deleteLogicalPortsFromMap(portsNo []uint32) {
khenaidoo820197c2020-02-13 16:35:33 -05001881 agent.lockLogicalPortsNo.Lock()
1882 defer agent.lockLogicalPortsNo.Unlock()
1883 for _, pNo := range portsNo {
1884 delete(agent.logicalPortsNo, pNo)
1885 }
1886}
1887
Kent Hagerman2b216042020-04-03 18:28:56 -04001888func (agent *LogicalAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
khenaidoo3d3b8c22019-05-22 18:10:39 -04001889 agent.lockLogicalPortsNo.Lock()
1890 defer agent.lockLogicalPortsNo.Unlock()
1891 for _, lp := range lps {
1892 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1893 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1894 }
1895 }
1896}
1897
Kent Hagerman2b216042020-04-03 18:28:56 -04001898func (agent *LogicalAgent) isNNIPort(portNo uint32) bool {
khenaidoo2c6a0992019-04-29 13:46:56 -04001899 agent.lockLogicalPortsNo.RLock()
1900 defer agent.lockLogicalPortsNo.RUnlock()
1901 if exist := agent.logicalPortsNo[portNo]; exist {
1902 return agent.logicalPortsNo[portNo]
1903 }
1904 return false
1905}
1906
Kent Hagerman2b216042020-04-03 18:28:56 -04001907func (agent *LogicalAgent) getFirstNNIPort() (uint32, error) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001908 agent.lockLogicalPortsNo.RLock()
1909 defer agent.lockLogicalPortsNo.RUnlock()
1910 for portNo, nni := range agent.logicalPortsNo {
1911 if nni {
1912 return portNo, nil
1913 }
1914 }
1915 return 0, status.Error(codes.NotFound, "No NNI port found")
1916}
Esin Karaman09959ae2019-11-29 13:59:58 +00001917
1918//GetNNIPorts returns NNI ports.
Kent Hagerman2b216042020-04-03 18:28:56 -04001919func (agent *LogicalAgent) GetNNIPorts() []uint32 {
Esin Karaman09959ae2019-11-29 13:59:58 +00001920 agent.lockLogicalPortsNo.RLock()
1921 defer agent.lockLogicalPortsNo.RUnlock()
1922 nniPorts := make([]uint32, 0)
1923 for portNo, nni := range agent.logicalPortsNo {
1924 if nni {
1925 nniPorts = append(nniPorts, portNo)
1926 }
1927 }
1928 return nniPorts
1929}