blob: e0aac9de135647101fed5f05a264d83233e6e409 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
Matteo Scandolo360605d2019-11-05 18:29:17 -080021 "encoding/hex"
khenaidoo19d7b632018-10-30 10:49:50 -040022 "errors"
23 "fmt"
npujar1d86a522019-11-14 17:11:16 +053024 "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"
khenaidoo89b0e942018-10-21 21:11:33 -040031 "github.com/opencord/voltha-go/rw_core/graph"
Scott Bakerb671a862019-10-24 10:53:40 -070032 coreutils "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070033 fu "github.com/opencord/voltha-lib-go/v2/pkg/flows"
34 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker555307d2019-11-04 08:58:01 -080035 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
37 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040040)
41
npujar1d86a522019-11-14 17:11:16 +053042// LogicalDeviceAgent represent attributes of logical device agent
khenaidoob9203542018-09-17 22:56:37 -040043type LogicalDeviceAgent struct {
npujar1d86a522019-11-14 17:11:16 +053044 logicalDeviceID string
45 rootDeviceID string
khenaidoo3306c992019-05-24 16:57:35 -040046 deviceMgr *DeviceManager
47 ldeviceMgr *LogicalDeviceManager
48 clusterDataProxy *model.Proxy
49 exitChannel chan int
50 deviceGraph *graph.DeviceGraph
51 flowProxy *model.Proxy
52 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040053 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040054 ldProxy *model.Proxy
55 portProxies map[string]*model.Proxy
56 portProxiesLock sync.RWMutex
57 lockLogicalDevice sync.RWMutex
khenaidoo4c9e5592019-09-09 16:20:41 -040058 lockDeviceGraph sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040059 logicalPortsNo map[uint32]bool //value is true for NNI port
60 lockLogicalPortsNo sync.RWMutex
61 flowDecomposer *fd.FlowDecomposer
62 defaultTimeout int64
khenaidoo6e55d9e2019-12-12 18:26:26 -050063 logicalDevice *voltha.LogicalDevice
khenaidoob9203542018-09-17 22:56:37 -040064}
65
npujar1d86a522019-11-14 17:11:16 +053066func newLogicalDeviceAgent(id string, deviceID string, ldeviceMgr *LogicalDeviceManager,
Stephane Barbarie1ab43272018-12-08 21:42:13 -050067 deviceMgr *DeviceManager,
khenaidoo2c6a0992019-04-29 13:46:56 -040068 cdProxy *model.Proxy, timeout int64) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040069 var agent LogicalDeviceAgent
70 agent.exitChannel = make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +053071 agent.logicalDeviceID = id
72 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040073 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040074 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040075 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040076 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040077 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoofc1314d2019-03-14 09:34:21 -040078 agent.portProxies = make(map[string]*model.Proxy)
79 agent.portProxiesLock = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040080 agent.lockLogicalPortsNo = sync.RWMutex{}
khenaidoo4c9e5592019-09-09 16:20:41 -040081 agent.lockDeviceGraph = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040082 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040083 agent.defaultTimeout = timeout
khenaidoob9203542018-09-17 22:56:37 -040084 return &agent
85}
86
khenaidoo4d4802d2018-10-04 21:59:49 -040087// start creates the logical device and add it to the data model
khenaidoo297cd252019-02-07 22:10:23 -050088func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
npujar1d86a522019-11-14 17:11:16 +053089 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceID, "loadFromdB": loadFromdB})
khenaidoo297cd252019-02-07 22:10:23 -050090 var ld *voltha.LogicalDevice
91 if !loadFromdB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040092 //Build the logical device based on information retrieved from the device adapter
93 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -050094 var err error
npujar1d86a522019-11-14 17:11:16 +053095 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -040096 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
97 return err
98 }
npujar1d86a522019-11-14 17:11:16 +053099 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500100
101 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
102 var datapathID uint64
npujar1d86a522019-11-14 17:11:16 +0530103 if datapathID, err = CreateDataPathID(agent.logicalDeviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500104 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
105 return err
106 }
107 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400108 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
109 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
110 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500111 ld.Flows = &ofp.Flows{Items: nil}
112 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
113
khenaidoo297cd252019-02-07 22:10:23 -0500114 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500115 // Save the logical device
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400116 if added := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, ""); added == nil {
npujar1d86a522019-11-14 17:11:16 +0530117 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500118 } else {
npujar1d86a522019-11-14 17:11:16 +0530119 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500120 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500121
122 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoo297cd252019-02-07 22:10:23 -0500123 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400124
khenaidoo3d3b8c22019-05-22 18:10:39 -0400125 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
npujar1d86a522019-11-14 17:11:16 +0530126 go func() {
127 err := agent.setupLogicalPorts(ctx)
128 if err != nil {
129 log.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
130 }
131 }()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400132
khenaidoo297cd252019-02-07 22:10:23 -0500133 } else {
134 // load from dB - the logical may not exist at this time. On error, just return and the calling function
135 // will destroy this agent.
khenaidoo6e55d9e2019-12-12 18:26:26 -0500136 agent.lockLogicalDevice.Lock()
137 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, true, "")
138 ld, ok := logicalDevice.(*voltha.LogicalDevice)
139 if !ok {
140 agent.lockLogicalDevice.Unlock()
141 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500142 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500143 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530144 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400145
khenaidoo6e55d9e2019-12-12 18:26:26 -0500146 // Update the last data
147 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
148
149 agent.lockLogicalDevice.Unlock()
150
khenaidoo3d3b8c22019-05-22 18:10:39 -0400151 // Setup the local list of logical ports
152 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400153 }
khenaidoo92e62c52018-10-03 14:02:54 -0400154 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400155 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400156
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400157 agent.flowProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400158 ctx,
npujar1d86a522019-11-14 17:11:16 +0530159 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400160 false)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400161 agent.meterProxy = agent.clusterDataProxy.CreateProxy(
162 ctx,
npujar1d86a522019-11-14 17:11:16 +0530163 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400164 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400165 agent.groupProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400166 ctx,
npujar1d86a522019-11-14 17:11:16 +0530167 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400168 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400169 agent.ldProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400170 ctx,
npujar1d86a522019-11-14 17:11:16 +0530171 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400172 false)
khenaidoo19d7b632018-10-30 10:49:50 -0400173
khenaidoofc1314d2019-03-14 09:34:21 -0400174 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400175 if agent.ldProxy != nil {
176 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
177 } else {
npujar1d86a522019-11-14 17:11:16 +0530178 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400179 return status.Error(codes.Internal, "logical-device-proxy-null")
180 }
khenaidoobcf205b2019-01-25 22:21:14 -0500181
khenaidoo4c9e5592019-09-09 16:20:41 -0400182 // Setup the device graph - run it in its own routine
183 if loadFromdB {
184 go agent.generateDeviceGraph()
185 }
khenaidoob9203542018-09-17 22:56:37 -0400186 return nil
187}
188
khenaidoo4d4802d2018-10-04 21:59:49 -0400189// stop stops the logical devuce agent. This removes the logical device from the data model.
190func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
191 log.Info("stopping-logical_device-agent")
192 agent.lockLogicalDevice.Lock()
193 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500194
khenaidoo4d4802d2018-10-04 21:59:49 -0400195 //Remove the logical device from the model
npujar1d86a522019-11-14 17:11:16 +0530196 if removed := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); removed == nil {
197 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400198 } else {
npujar1d86a522019-11-14 17:11:16 +0530199 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400200 }
201 agent.exitChannel <- 1
202 log.Info("logical_device-agent-stopped")
203}
204
khenaidoo6e55d9e2019-12-12 18:26:26 -0500205// GetLogicalDevice returns the latest logical device data
206func (agent *LogicalDeviceAgent) GetLogicalDevice() *voltha.LogicalDevice {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400207 agent.lockLogicalDevice.RLock()
208 defer agent.lockLogicalDevice.RUnlock()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500209
210 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400211}
212
npujar1d86a522019-11-14 17:11:16 +0530213// ListLogicalDeviceFlows returns logical device flows
khenaidoo6e55d9e2019-12-12 18:26:26 -0500214func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() *ofp.Flows {
khenaidoodd237172019-05-27 16:37:17 -0400215 log.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500216
217 logicalDevice := agent.GetLogicalDevice()
218 if logicalDevice.Flows == nil {
219 return &ofp.Flows{}
khenaidoodd237172019-05-27 16:37:17 -0400220 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500221 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows)
khenaidoodd237172019-05-27 16:37:17 -0400222}
223
npujar1d86a522019-11-14 17:11:16 +0530224// ListLogicalDeviceMeters returns logical device meters
khenaidoo6e55d9e2019-12-12 18:26:26 -0500225func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() *ofp.Meters {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400226 log.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500227
228 logicalDevice := agent.GetLogicalDevice()
229 if logicalDevice.Meters == nil {
230 return &ofp.Meters{}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400231 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500232 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400233}
234
npujar1d86a522019-11-14 17:11:16 +0530235// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoo6e55d9e2019-12-12 18:26:26 -0500236func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() *ofp.FlowGroups {
khenaidoodd237172019-05-27 16:37:17 -0400237 log.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500238
239 logicalDevice := agent.GetLogicalDevice()
240 if logicalDevice.FlowGroups == nil {
241 return &ofp.FlowGroups{}
khenaidoodd237172019-05-27 16:37:17 -0400242 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500243 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups)
khenaidoodd237172019-05-27 16:37:17 -0400244}
245
npujar1d86a522019-11-14 17:11:16 +0530246// ListLogicalDevicePorts returns logical device ports
khenaidoo6e55d9e2019-12-12 18:26:26 -0500247func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() *voltha.LogicalPorts {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400248 log.Debug("ListLogicalDevicePorts")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500249
250 logicalDevice := agent.GetLogicalDevice()
251 lPorts := make([]*voltha.LogicalPort, 0)
252 lPorts = append(lPorts, logicalDevice.Ports...)
253 return &voltha.LogicalPorts{Items: lPorts}
khenaidoo19d7b632018-10-30 10:49:50 -0400254}
255
khenaidoo4c9e5592019-09-09 16:20:41 -0400256//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500257func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500258 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400259
khenaidoo6e55d9e2019-12-12 18:26:26 -0500260 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
261 ld.Flows = flows
262
263 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400264 log.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
265 return err
khenaidoo43c82122018-11-22 18:38:28 -0500266 }
khenaidoo43c82122018-11-22 18:38:28 -0500267 return nil
268}
269
khenaidoo4c9e5592019-09-09 16:20:41 -0400270//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400271func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500272 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400273
khenaidoo6e55d9e2019-12-12 18:26:26 -0500274 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
275 ld.Meters = meters
276
277 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400278 log.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
279 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400280 }
281 return nil
282}
283
khenaidoo4c9e5592019-09-09 16:20:41 -0400284//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
khenaidoo43c82122018-11-22 18:38:28 -0500285func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500286 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400287
khenaidoo6e55d9e2019-12-12 18:26:26 -0500288 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
289 ld.FlowGroups = flowGroups
290
291 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400292 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
293 return err
khenaidoo43c82122018-11-22 18:38:28 -0500294 }
khenaidoo43c82122018-11-22 18:38:28 -0500295 return nil
296}
297
khenaidoo6e55d9e2019-12-12 18:26:26 -0500298// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
299func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
khenaidoo92e62c52018-10-03 14:02:54 -0400300 log.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500301 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400302}
303
khenaidoo2c6a0992019-04-29 13:46:56 -0400304func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
305 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
306 var err error
307 if port.Type == voltha.Port_ETHERNET_NNI {
308 if _, err = agent.addNNILogicalPort(device, port); err != nil {
309 return err
310 }
311 agent.addLogicalPortToMap(port.PortNo, true)
312 } else if port.Type == voltha.Port_ETHERNET_UNI {
313 if _, err = agent.addUNILogicalPort(device, port); err != nil {
314 return err
315 }
316 agent.addLogicalPortToMap(port.PortNo, false)
317 } else {
318 // Update the device graph to ensure all routes on the logical device have been calculated
319 if err = agent.updateRoutes(device, port); err != nil {
320 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
321 return err
322 }
323 }
324 return nil
325}
326
khenaidoo3d3b8c22019-05-22 18:10:39 -0400327// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
328// added to it. While the logical device was being created we could have received requests to add
329// NNI and UNI ports which were discarded. Now is the time to add them if needed
330func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
npujar1d86a522019-11-14 17:11:16 +0530331 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400332 // First add any NNI ports which could have been missing
npujar1d86a522019-11-14 17:11:16 +0530333 if err := agent.setupNNILogicalPorts(context.TODO(), agent.rootDeviceID); err != nil {
334 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400335 return err
336 }
337
338 // Now, set up the UNI ports if needed.
npujar1d86a522019-11-14 17:11:16 +0530339 children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceID)
340 if err != nil {
341 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400342 return err
npujar1d86a522019-11-14 17:11:16 +0530343 }
344 responses := make([]coreutils.Response, 0)
345 for _, child := range children.Items {
346 response := coreutils.NewResponse()
347 responses = append(responses, response)
348 go func(child *voltha.Device) {
349 if err = agent.setupUNILogicalPorts(context.TODO(), child); err != nil {
350 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
351 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
352 }
353 response.Done()
354 }(child)
355 }
356 // Wait for completion
357 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
358 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400359 }
360 return nil
361}
362
khenaidoofc1314d2019-03-14 09:34:21 -0400363// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530364func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
365 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400366 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400367 var err error
368
369 var device *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530370 if device, err = agent.deviceMgr.GetDevice(deviceID); err != nil {
371 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400372 return err
373 }
374
375 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400376 for _, port := range device.Ports {
377 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400378 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400379 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400380 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400381 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400382 }
383 }
khenaidoofc1314d2019-03-14 09:34:21 -0400384 return err
385}
386
khenaidoo171b98e2019-10-31 11:48:15 -0400387// updatePortState updates the port state of the device
npujar1d86a522019-11-14 17:11:16 +0530388func (agent *LogicalDeviceAgent) updatePortState(deviceID string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
389 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo171b98e2019-10-31 11:48:15 -0400390 agent.lockLogicalDevice.Lock()
391 defer agent.lockLogicalDevice.Unlock()
392 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500393 cloned := agent.getLogicalDeviceWithoutLock()
394 for idx, lPort := range cloned.Ports {
npujar1d86a522019-11-14 17:11:16 +0530395 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530396 if operStatus == voltha.OperStatus_ACTIVE {
397 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
398 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
399 } else {
400 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
401 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
402 }
403 // Update the logical device
404 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
405 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
406 return err
407 }
408 return nil
409 }
410 }
411 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400412}
413
khenaidoo3ab34882019-05-02 21:33:30 -0400414// updatePortsState updates the ports state related to the device
415func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
npujar1d86a522019-11-14 17:11:16 +0530416 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400417 agent.lockLogicalDevice.Lock()
418 defer agent.lockLogicalDevice.Unlock()
419 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500420 cloned := agent.getLogicalDeviceWithoutLock()
npujar1d86a522019-11-14 17:11:16 +0530421 for _, lport := range cloned.Ports {
422 if lport.DeviceId == device.Id {
423 switch state {
424 case voltha.AdminState_ENABLED:
425 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
426 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
427 case voltha.AdminState_DISABLED:
428 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
429 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
430 default:
431 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
khenaidoo3ab34882019-05-02 21:33:30 -0400432 }
433 }
npujar1d86a522019-11-14 17:11:16 +0530434 }
435 // Updating the logical device will trigger the poprt change events to be populated to the controller
436 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
437 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
438 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400439 }
440 return nil
441}
442
khenaidoofc1314d2019-03-14 09:34:21 -0400443// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
444func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530445 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400446 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400447 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400448 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400449 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400450 for _, port := range childDevice.Ports {
451 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400452 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400453 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400454 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400455 if added {
456 agent.addLogicalPortToMap(port.PortNo, false)
457 }
khenaidoo19d7b632018-10-30 10:49:50 -0400458 }
459 }
khenaidoofc1314d2019-03-14 09:34:21 -0400460 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400461}
462
khenaidoo0a822f92019-05-08 15:15:57 -0400463// deleteAllLogicalPorts deletes all logical ports associated with this device
464func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530465 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400466 agent.lockLogicalDevice.Lock()
467 defer agent.lockLogicalDevice.Unlock()
468 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500469 ld := agent.getLogicalDeviceWithoutLock()
470
npujar1d86a522019-11-14 17:11:16 +0530471 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
472 updateLogicalPorts := []*voltha.LogicalPort{}
473 for _, lport := range cloned.Ports {
474 if lport.DeviceId != device.Id {
475 updateLogicalPorts = append(updateLogicalPorts, lport)
476 }
477 }
478 if len(updateLogicalPorts) < len(cloned.Ports) {
479 cloned.Ports = updateLogicalPorts
480 // Updating the logical device will trigger the poprt change events to be populated to the controller
481 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
482 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
483 return err
484 }
khenaidoo0a822f92019-05-08 15:15:57 -0400485 } else {
npujar1d86a522019-11-14 17:11:16 +0530486 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400487 }
488 return nil
489}
490
khenaidoo92e62c52018-10-03 14:02:54 -0400491//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
492func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400493 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
npujar1d86a522019-11-14 17:11:16 +0530494 afterUpdate := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400495 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530496 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400497 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500498 agent.logicalDevice = (proto.Clone(logicalDevice)).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400499 return nil
500}
501
khenaidoo4c9e5592019-09-09 16:20:41 -0400502//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
503//that device graph was generated.
504func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500505 ld := agent.GetLogicalDevice()
npujar1d86a522019-11-14 17:11:16 +0530506 agent.lockDeviceGraph.Lock()
507 defer agent.lockDeviceGraph.Unlock()
508 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
509 return nil
510 }
511 log.Debug("Generation of device graph required")
512 agent.generateDeviceGraph()
khenaidoo4c9e5592019-09-09 16:20:41 -0400513 return nil
514}
515
khenaidoo19d7b632018-10-30 10:49:50 -0400516//updateFlowTable updates the flow table of that logical device
517func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
518 log.Debug("updateFlowTable")
519 if flow == nil {
520 return nil
521 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400522 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
523 return err
524 }
khenaidoo19d7b632018-10-30 10:49:50 -0400525 switch flow.GetCommand() {
526 case ofp.OfpFlowModCommand_OFPFC_ADD:
527 return agent.flowAdd(flow)
528 case ofp.OfpFlowModCommand_OFPFC_DELETE:
529 return agent.flowDelete(flow)
530 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
531 return agent.flowDeleteStrict(flow)
532 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
533 return agent.flowModify(flow)
534 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
535 return agent.flowModifyStrict(flow)
536 }
537 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530538 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400539}
540
541//updateGroupTable updates the group table of that logical device
542func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
543 log.Debug("updateGroupTable")
544 if groupMod == nil {
545 return nil
546 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400547 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
548 return err
549 }
khenaidoo19d7b632018-10-30 10:49:50 -0400550 switch groupMod.GetCommand() {
551 case ofp.OfpGroupModCommand_OFPGC_ADD:
552 return agent.groupAdd(groupMod)
553 case ofp.OfpGroupModCommand_OFPGC_DELETE:
554 return agent.groupDelete(groupMod)
555 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
556 return agent.groupModify(groupMod)
557 }
558 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530559 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400560}
561
Manikkaraj kb1a10922019-07-29 12:10:34 -0400562// updateMeterTable updates the meter table of that logical device
563func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
564 log.Debug("updateMeterTable")
565 if meterMod == nil {
566 return nil
567 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400568 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
569 return err
570 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400571 switch meterMod.GetCommand() {
572 case ofp.OfpMeterModCommand_OFPMC_ADD:
573 return agent.meterAdd(meterMod)
574 case ofp.OfpMeterModCommand_OFPMC_DELETE:
575 return agent.meterDelete(meterMod)
576 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
577 return agent.meterModify(meterMod)
578 }
579 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530580 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400581
582}
583
584func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
585 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
586 if meterMod == nil {
587 return nil
588 }
589 log.Debug("Waiting for logical device lock!!")
590 agent.lockLogicalDevice.Lock()
591 defer agent.lockLogicalDevice.Unlock()
592 log.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500593 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400594
595 var meters []*ofp.OfpMeterEntry
596 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
597 meters = lDevice.Meters.Items
598 }
599 log.Debugw("Available meters", log.Fields{"meters": meters})
600
601 for _, meter := range meters {
602 if meterMod.MeterId == meter.Config.MeterId {
603 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
604 return nil
605 }
606 }
607
608 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
609 meters = append(meters, meterEntry)
610 //Update model
611 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530612 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400613 return err
614 }
615 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
616 return nil
617}
618
619func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
620 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
621 if meterMod == nil {
622 return nil
623 }
624 agent.lockLogicalDevice.Lock()
625 defer agent.lockLogicalDevice.Unlock()
626
khenaidoo6e55d9e2019-12-12 18:26:26 -0500627 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400628
629 var meters []*ofp.OfpMeterEntry
630 var flows []*ofp.OfpFlowStats
631 updatedFlows := make([]*ofp.OfpFlowStats, 0)
632 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
633 meters = lDevice.Meters.Items
634 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400635
636 changedMeter := false
637 changedFow := false
638 log.Debugw("Available meters", log.Fields{"meters": meters})
639 for index, meter := range meters {
640 if meterMod.MeterId == meter.Config.MeterId {
641 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530642 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400643 meters = append(meters[:index], meters[index+1:]...)
644 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
645 changedMeter = true
646 break
647 }
648 }
649 if changedMeter {
650 //Update model
651 metersToUpdate := &ofp.Meters{}
652 if lDevice.Meters != nil {
653 metersToUpdate = &ofp.Meters{Items: meters}
654 }
655 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530656 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400657 return err
658 }
659 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
660
661 }
662 if changedFow {
663 //Update model
664 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530665 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400666 return err
667 }
668 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
669 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
670 }
671 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
672 return nil
673}
674
675func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
676 log.Debug("meterModify")
677 if meterMod == nil {
678 return nil
679 }
680 agent.lockLogicalDevice.Lock()
681 defer agent.lockLogicalDevice.Unlock()
682
khenaidoo6e55d9e2019-12-12 18:26:26 -0500683 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400684
685 var meters []*ofp.OfpMeterEntry
686 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
687 meters = lDevice.Meters.Items
688 }
689 changedMeter := false
690 for index, meter := range meters {
691 if meterMod.MeterId == meter.Config.MeterId {
692 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
693 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
694 meters[index] = newmeterEntry
695 changedMeter = true
696 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
697 break
698 }
699 }
700 if changedMeter {
701 //Update model
702 metersToUpdate := &ofp.Meters{}
703 if lDevice.Meters != nil {
704 metersToUpdate = &ofp.Meters{Items: meters}
705 }
706 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530707 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400708 return err
709 }
710 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
711 return nil
712 }
713
714 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530715 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400716
717}
718
npujar1d86a522019-11-14 17:11:16 +0530719func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
720 log.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400721 changed := false
722 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
723 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530724 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400725 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
726 flows = append(flows[:index], flows[index+1:]...)
727 changed = true
728 }
729 }
730 return changed, flows
731}
732
733func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
734
735 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530736 meterID := fu.GetMeterIdFromFlow(flow)
737 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
738 if meterID == 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400739 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
740 return false
741 }
742 if meters == nil {
743 log.Debug("No meters present in logical device")
744 return false
745 }
746 changedMeter := false
747 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530748 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400749 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530750 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400751 changedMeter = true
752 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530753 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400754 changedMeter = true
755 }
npujar1d86a522019-11-14 17:11:16 +0530756 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400757 break
758 }
759 }
760 return changedMeter
761}
762
khenaidoo19d7b632018-10-30 10:49:50 -0400763//flowAdd adds a flow to the flow table of that logical device
764func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400765 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400766 if mod == nil {
767 return nil
768 }
khenaidoo92e62c52018-10-03 14:02:54 -0400769 agent.lockLogicalDevice.Lock()
770 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400771
khenaidoo6e55d9e2019-12-12 18:26:26 -0500772 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400773
774 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400775 var meters []*ofp.OfpMeterEntry
776 var flow *ofp.OfpFlowStats
777
khenaidoo19d7b632018-10-30 10:49:50 -0400778 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
779 flows = lDevice.Flows.Items
780 }
781
Manikkaraj kb1a10922019-07-29 12:10:34 -0400782 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
783 meters = lDevice.Meters.Items
784 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400785 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400786 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400787 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400788 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
789 if checkOverlap {
790 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
791 // TODO: should this error be notified other than being logged?
npujar1d86a522019-11-14 17:11:16 +0530792 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400793 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400794 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400795 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400796 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400797 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400798 changed = true
799 }
800 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400801 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400802 idx := fu.FindFlows(flows, flow)
803 if idx >= 0 {
804 oldFlow := flows[idx]
805 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
806 flow.ByteCount = oldFlow.ByteCount
807 flow.PacketCount = oldFlow.PacketCount
808 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400809 if !reflect.DeepEqual(oldFlow, flow) {
810 flows[idx] = flow
811 updatedFlows = append(updatedFlows, flow)
812 changed = true
813 updated = true
814 }
815 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400816 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400817 updatedFlows = append(updatedFlows, flow)
818 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400819 }
khenaidoo19d7b632018-10-30 10:49:50 -0400820 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400821 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
822
khenaidoo19d7b632018-10-30 10:49:50 -0400823 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400824 var flowMetadata voltha.FlowMetadata
825 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
826 log.Error("Meter-referred-in-flows-not-present")
827 return err
828 }
khenaidoo0458db62019-06-20 08:50:36 -0400829 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
830 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
831
Manikkaraj kb1a10922019-07-29 12:10:34 -0400832 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530833 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400834 return err
835 }
836
khenaidoo19d7b632018-10-30 10:49:50 -0400837 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400838 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530839 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400840 return err
841 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400842 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400843 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
844 metersToUpdate := &ofp.Meters{}
845 if lDevice.Meters != nil {
846 metersToUpdate = &ofp.Meters{Items: meters}
847 }
848 if changedMeterStats {
849 //Update model
850 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530851 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400852 return err
853 }
854 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
855
856 }
857 }
858
khenaidoo19d7b632018-10-30 10:49:50 -0400859 }
khenaidoo19d7b632018-10-30 10:49:50 -0400860 return nil
861}
862
npujar1d86a522019-11-14 17:11:16 +0530863// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400864func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
865 m := make(map[uint32]bool)
866 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530867 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400868 foundMeter := false
869 // Meter is present in the flow , Get from logical device
870 for _, meter := range meters {
871 if flowMeterID == meter.Config.MeterId {
872 metadata.Meters = append(metadata.Meters, meter.Config)
873 log.Debugw("Found meter in logical device",
874 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
875 m[flowMeterID] = true
876 foundMeter = true
877 break
878 }
879 }
880 if !foundMeter {
881 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +0530882 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400883 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
884 }
885 }
886 }
887 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
888 return nil
889
890}
891
khenaidoo19d7b632018-10-30 10:49:50 -0400892//flowDelete deletes a flow from the flow table of that logical device
893func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
894 log.Debug("flowDelete")
895 if mod == nil {
896 return nil
897 }
898 agent.lockLogicalDevice.Lock()
899 defer agent.lockLogicalDevice.Unlock()
900
khenaidoo6e55d9e2019-12-12 18:26:26 -0500901 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400902
Manikkaraj kb1a10922019-07-29 12:10:34 -0400903 var meters []*ofp.OfpMeterEntry
904 var flows []*ofp.OfpFlowStats
905
906 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
907 flows = lDevice.Flows.Items
908 }
909
910 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
911 meters = lDevice.Meters.Items
912 }
khenaidoo19d7b632018-10-30 10:49:50 -0400913 //build a list of what to keep vs what to delete
914 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400915 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400916 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -0400917 // Check whether the flow and the flowmod matches
918 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
919 toDelete = append(toDelete, f)
920 continue
921 }
922 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -0400923 if !fu.FlowMatchesMod(f, mod) {
924 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -0400925 } else {
926 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -0400927 }
928 }
929
npujar1d86a522019-11-14 17:11:16 +0530930 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -0400931
khenaidoo19d7b632018-10-30 10:49:50 -0400932 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -0400933 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400934 var flowMetadata voltha.FlowMetadata
935 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
936 log.Error("Meter-referred-in-flows-not-present")
937 return errors.New("Meter-referred-in-flows-not-present")
938 }
khenaidoo0458db62019-06-20 08:50:36 -0400939 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
940 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
941
Manikkaraj kb1a10922019-07-29 12:10:34 -0400942 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530943 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -0400944 return err
945 }
946
khenaidoo43c82122018-11-22 18:38:28 -0500947 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530948 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400949 return err
950 }
951 }
952
953 //TODO: send announcement on delete
954 return nil
955}
956
Manikkaraj kb1a10922019-07-29 12:10:34 -0400957func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530958 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400959
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500960 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530961 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500962 response := coreutils.NewResponse()
963 responses = append(responses, response)
964 go func(deviceId string, value *fu.FlowsAndGroups) {
965 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400966 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500967 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400968 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500969 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530970 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -0400971 }
khenaidoo0458db62019-06-20 08:50:36 -0400972 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500973 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400974 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -0400975 }
khenaidoo0458db62019-06-20 08:50:36 -0400976 return nil
977}
khenaidoo19d7b632018-10-30 10:49:50 -0400978
Manikkaraj kb1a10922019-07-29 12:10:34 -0400979func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530980 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -0400981
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500982 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530983 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500984 response := coreutils.NewResponse()
985 responses = append(responses, response)
986 go func(deviceId string, value *fu.FlowsAndGroups) {
987 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400988 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500989 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400990 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500991 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530992 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -0400993 }
994 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500995 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400996 return status.Errorf(codes.Aborted, "errors-%s", res)
997 }
998 return nil
999}
1000
Manikkaraj kb1a10922019-07-29 12:10:34 -04001001func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301002 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001003
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001004 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301005 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001006 response := coreutils.NewResponse()
1007 responses = append(responses, response)
1008 go func(deviceId string, value *fu.FlowsAndGroups) {
1009 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001010 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001011 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001012 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001013 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301014 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001015 }
1016 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001017 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001018 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001019 }
1020 return nil
1021}
1022
1023//flowDeleteStrict deletes a flow from the flow table of that logical device
1024func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1025 log.Debug("flowDeleteStrict")
1026 if mod == nil {
1027 return nil
1028 }
1029 agent.lockLogicalDevice.Lock()
1030 defer agent.lockLogicalDevice.Unlock()
1031
khenaidoo6e55d9e2019-12-12 18:26:26 -05001032 lDevice := agent.getLogicalDeviceWithoutLock()
1033
Manikkaraj kb1a10922019-07-29 12:10:34 -04001034 var meters []*ofp.OfpMeterEntry
1035 var flows []*ofp.OfpFlowStats
1036 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1037 meters = lDevice.Meters.Items
1038 }
1039 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1040 flows = lDevice.Flows.Items
1041 }
1042
1043 changedFlow := false
1044 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001045 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001046 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001047 idx := fu.FindFlows(flows, flow)
1048 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001049 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001050 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001051 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001052 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001053 } else {
npujar1d86a522019-11-14 17:11:16 +05301054 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001055 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001056 if changedMeter {
1057 //Update model
1058 metersToUpdate := &ofp.Meters{}
1059 if lDevice.Meters != nil {
1060 metersToUpdate = &ofp.Meters{Items: meters}
1061 }
1062 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301063 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001064 return err
1065 }
khenaidoo19d7b632018-10-30 10:49:50 -04001066
Manikkaraj kb1a10922019-07-29 12:10:34 -04001067 }
1068 if changedFlow {
1069 var flowMetadata voltha.FlowMetadata
1070 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
1071 log.Error("Meter-referred-in-flows-not-present")
1072 return err
1073 }
1074 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001075 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1076
Manikkaraj kb1a10922019-07-29 12:10:34 -04001077 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301078 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001079 return err
1080 }
1081
khenaidoo43c82122018-11-22 18:38:28 -05001082 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301083 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001084 return err
1085 }
1086 }
khenaidoo19d7b632018-10-30 10:49:50 -04001087 return nil
1088}
1089
1090//flowModify modifies a flow from the flow table of that logical device
1091func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1092 return errors.New("flowModify not implemented")
1093}
1094
1095//flowModifyStrict deletes a flow from the flow table of that logical device
1096func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1097 return errors.New("flowModifyStrict not implemented")
1098}
1099
1100func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1101 log.Debug("groupAdd")
1102 if groupMod == nil {
1103 return nil
1104 }
1105 agent.lockLogicalDevice.Lock()
1106 defer agent.lockLogicalDevice.Unlock()
1107
khenaidoo6e55d9e2019-12-12 18:26:26 -05001108 lDevice := agent.getLogicalDeviceWithoutLock()
1109
khenaidoo19d7b632018-10-30 10:49:50 -04001110 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001111 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001112 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001113
Esin Karaman2ea59212019-12-06 11:41:58 +00001114 deviceRules := fu.NewDeviceRules()
1115 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1116 fg := fu.NewFlowsAndGroups()
1117 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1118 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1119
1120 log.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
1121 if err := agent.addDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301122 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001123 return err
1124 }
1125
khenaidoo43c82122018-11-22 18:38:28 -05001126 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301127 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001128 return err
1129 }
1130 } else {
npujar1d86a522019-11-14 17:11:16 +05301131 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001132 }
khenaidoo19d7b632018-10-30 10:49:50 -04001133 return nil
1134}
1135
1136func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1137 log.Debug("groupDelete")
1138 if groupMod == nil {
1139 return nil
1140 }
1141 agent.lockLogicalDevice.Lock()
1142 defer agent.lockLogicalDevice.Unlock()
1143
khenaidoo6e55d9e2019-12-12 18:26:26 -05001144 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001145 groups := lDevice.FlowGroups.Items
1146 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301147 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001148 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301149 groupID := groupMod.GroupId
1150 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001151 //TODO we must delete all flows that point to this group and
1152 //signal controller as requested by flow's flag
1153 groups = []*ofp.OfpGroupEntry{}
1154 groupsChanged = true
1155 } else {
npujar1d86a522019-11-14 17:11:16 +05301156 idx := fu.FindGroup(groups, groupID)
1157 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001158 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001159 }
npujar1d86a522019-11-14 17:11:16 +05301160 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1161 groups = append(groups[:idx], groups[idx+1:]...)
1162 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001163 }
khenaidoo0458db62019-06-20 08:50:36 -04001164 if flowsChanged || groupsChanged {
1165 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1166 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1167
Manikkaraj kb1a10922019-07-29 12:10:34 -04001168 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301169 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001170 return err
1171 }
1172 }
1173
khenaidoo43c82122018-11-22 18:38:28 -05001174 if groupsChanged {
1175 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301176 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001177 return err
1178 }
1179 }
khenaidoo43c82122018-11-22 18:38:28 -05001180 if flowsChanged {
1181 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301182 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo43c82122018-11-22 18:38:28 -05001183 return err
1184 }
1185 }
khenaidoo19d7b632018-10-30 10:49:50 -04001186 return nil
1187}
1188
1189func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1190 log.Debug("groupModify")
1191 if groupMod == nil {
1192 return nil
1193 }
1194 agent.lockLogicalDevice.Lock()
1195 defer agent.lockLogicalDevice.Unlock()
1196
khenaidoo6e55d9e2019-12-12 18:26:26 -05001197 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001198 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301199 var groupsChanged bool
1200 groupID := groupMod.GroupId
1201 idx := fu.FindGroup(groups, groupID)
1202 if idx == -1 {
1203 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001204 }
npujar1d86a522019-11-14 17:11:16 +05301205 //replace existing group entry with new group definition
1206 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1207 groups[idx] = groupEntry
1208 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001209 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001210 deviceRules := fu.NewDeviceRules()
1211 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1212 fg := fu.NewFlowsAndGroups()
1213 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1214 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001215
Esin Karaman2ea59212019-12-06 11:41:58 +00001216 log.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
1217 if err := agent.updateDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301218 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001219 return err
1220 }
1221
khenaidoo43c82122018-11-22 18:38:28 -05001222 //lDevice.FlowGroups.Items = groups
1223 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301224 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001225 return err
1226 }
1227 }
1228 return nil
1229}
1230
1231// deleteLogicalPort removes the logical port
1232func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1233 agent.lockLogicalDevice.Lock()
1234 defer agent.lockLogicalDevice.Unlock()
1235
khenaidoo6e55d9e2019-12-12 18:26:26 -05001236 logicalDevice := agent.getLogicalDeviceWithoutLock()
1237
khenaidoo92e62c52018-10-03 14:02:54 -04001238 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001239 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001240 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001241 index = i
1242 break
1243 }
1244 }
1245 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001246 copy(logicalDevice.Ports[index:], logicalDevice.Ports[index+1:])
1247 logicalDevice.Ports[len(logicalDevice.Ports)-1] = nil
1248 logicalDevice.Ports = logicalDevice.Ports[:len(logicalDevice.Ports)-1]
npujar1d86a522019-11-14 17:11:16 +05301249 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001250 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301251 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001252 return err
1253 }
1254 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001255 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001256 }
1257 return nil
khenaidoob9203542018-09-17 22:56:37 -04001258}
1259
khenaidoo0a822f92019-05-08 15:15:57 -04001260// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar1d86a522019-11-14 17:11:16 +05301261func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001262 agent.lockLogicalDevice.Lock()
1263 defer agent.lockLogicalDevice.Unlock()
1264
khenaidoo6e55d9e2019-12-12 18:26:26 -05001265 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo0a822f92019-05-08 15:15:57 -04001266 updatedLPorts := []*voltha.LogicalPort{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001267 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301268 if logicalPort.DeviceId != deviceID {
khenaidoo0a822f92019-05-08 15:15:57 -04001269 updatedLPorts = append(updatedLPorts, logicalPort)
1270 }
1271 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001272 logicalDevice.Ports = updatedLPorts
khenaidoo0a822f92019-05-08 15:15:57 -04001273 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001274 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301275 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001276 return err
1277 }
1278 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001279 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001280
1281 return nil
1282}
1283
khenaidoo19d7b632018-10-30 10:49:50 -04001284// enableLogicalPort enables the logical port
npujar1d86a522019-11-14 17:11:16 +05301285func (agent *LogicalDeviceAgent) enableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001286 agent.lockLogicalDevice.Lock()
1287 defer agent.lockLogicalDevice.Unlock()
1288
khenaidoo6e55d9e2019-12-12 18:26:26 -05001289 logicalDevice := agent.getLogicalDeviceWithoutLock()
1290
khenaidoo19d7b632018-10-30 10:49:50 -04001291 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001292 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301293 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001294 index = i
1295 break
1296 }
1297 }
1298 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001299 logicalDevice.Ports[index].OfpPort.Config = logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1300 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001301 }
npujar1d86a522019-11-14 17:11:16 +05301302 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001303}
1304
1305// disableLogicalPort disabled the logical port
npujar1d86a522019-11-14 17:11:16 +05301306func (agent *LogicalDeviceAgent) disableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001307 agent.lockLogicalDevice.Lock()
1308 defer agent.lockLogicalDevice.Unlock()
1309
1310 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001311 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001312 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001313 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301314 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001315 index = i
1316 break
1317 }
1318 }
1319 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001320 logicalDevice.Ports[index].OfpPort.Config = (logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1321 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001322 }
npujar1d86a522019-11-14 17:11:16 +05301323 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001324}
1325
khenaidoo89b0e942018-10-21 21:11:33 -04001326func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001327 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001328 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001329 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001330 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1331 return route
1332 }
1333 }
npujar1d86a522019-11-14 17:11:16 +05301334 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "ingress": ingress, "egress": egress})
khenaidoo89b0e942018-10-21 21:11:33 -04001335 return nil
1336}
1337
npujar1d86a522019-11-14 17:11:16 +05301338// GetRoute returns route
khenaidoo19d7b632018-10-30 10:49:50 -04001339func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001340 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001341 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001342
khenaidoo19d7b632018-10-30 10:49:50 -04001343 // Note: A port value of 0 is equivalent to a nil port
1344
khenaidoo89b0e942018-10-21 21:11:33 -04001345 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001346 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001347 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1348 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001349 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001350 if len(agent.deviceGraph.Routes) == 0 {
1351 // 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 -04001352 // route with same IngressHop and EgressHop
npujar1d86a522019-11-14 17:11:16 +05301353 hop := graph.RouteHop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001354 routes = append(routes, hop)
1355 routes = append(routes, hop)
1356 return routes
1357 }
khenaidoo89b0e942018-10-21 21:11:33 -04001358 //Return a 'half' route to make the flow decomposer logic happy
1359 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001360 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001361 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1362 routes = append(routes, route[1])
1363 return routes
1364 }
1365 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001366 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001367 return nil
1368 }
1369 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001370 var err error
1371 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1372 log.Warnw("no-nni-port", log.Fields{"error": err})
1373 return nil
1374 }
khenaidoo89b0e942018-10-21 21:11:33 -04001375 }
1376 //If ingress port is not specified (nil), it may be a wildcarded
1377 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1378 //in which case we need to create a half-route where only the egress
1379 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001380 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001381 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1382 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001383 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001384 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1385 routes = append(routes, route[1])
1386 return routes
1387 }
1388 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001389 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001390 return nil
1391 }
1392 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001393 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001394 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001395 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001396 routes = append(routes, route[0])
1397 routes = append(routes, graph.RouteHop{})
1398 return routes
1399 }
1400 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001401 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001402 return nil
1403 }
khenaidoo89b0e942018-10-21 21:11:33 -04001404 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001405 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001406}
1407
khenaidoo3d3b8c22019-05-22 18:10:39 -04001408//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1409//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1410//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001411func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1412 lPorts := make([]uint32, 0)
1413 var exclPort uint32
1414 if len(excludePort) == 1 {
1415 exclPort = excludePort[0]
1416 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001417 lDevice := agent.getLogicalDeviceWithoutLock()
1418 for _, port := range lDevice.Ports {
1419 if port.OfpPort.PortNo != exclPort {
1420 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001421 }
1422 }
1423 return lPorts
1424}
khenaidoo19d7b632018-10-30 10:49:50 -04001425
npujar1d86a522019-11-14 17:11:16 +05301426// GetDeviceGraph returns device graph
khenaidoo19d7b632018-10-30 10:49:50 -04001427func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1428 return agent.deviceGraph
1429}
1430
khenaidoo3306c992019-05-24 16:57:35 -04001431//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001432func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
npujar1d86a522019-11-14 17:11:16 +05301433 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001434 agent.lockLogicalDevice.Lock()
1435 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001436 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301437 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001438 }
1439 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001440 lDevice := agent.getLogicalDeviceWithoutLock()
1441
npujar1d86a522019-11-14 17:11:16 +05301442 //TODO: Find a better way to refresh only missing routes
1443 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
khenaidoo2c6a0992019-04-29 13:46:56 -04001444 agent.deviceGraph.Print()
1445 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001446}
1447
khenaidoo2c6a0992019-04-29 13:46:56 -04001448//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001449func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
npujar1d86a522019-11-14 17:11:16 +05301450 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -04001451 agent.lockLogicalDevice.Lock()
1452 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001453 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301454 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001455 }
1456 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001457 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001458}
khenaidoofdbad6e2018-11-06 22:26:38 -05001459
khenaidoo3d3b8c22019-05-22 18:10:39 -04001460//generateDeviceGraph regenerates the device graph
1461func (agent *LogicalDeviceAgent) generateDeviceGraph() {
npujar1d86a522019-11-14 17:11:16 +05301462 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001463 agent.lockLogicalDevice.Lock()
1464 defer agent.lockLogicalDevice.Unlock()
1465 // Get the latest logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001466 ld := agent.getLogicalDeviceWithoutLock()
1467 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceID, "lPorts": len(ld.Ports)})
1468 if agent.deviceGraph == nil {
1469 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001470 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001471 agent.deviceGraph.ComputeRoutes(ld.Ports)
1472 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001473}
1474
khenaidoofc1314d2019-03-14 09:34:21 -04001475// 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 -04001476func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001477 newPorts = make([]*voltha.LogicalPort, 0)
1478 changedPorts = make([]*voltha.LogicalPort, 0)
1479 deletedPorts = make([]*voltha.LogicalPort, 0)
1480 for _, o := range oldList {
1481 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001482 for _, n := range newList {
1483 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001484 found = true
1485 break
1486 }
1487 }
1488 if !found {
1489 deletedPorts = append(deletedPorts, o)
1490 }
khenaidoofc1314d2019-03-14 09:34:21 -04001491 }
1492 for _, n := range newList {
1493 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001494 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001495 for _, o := range oldList {
1496 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001497 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001498 found = true
1499 break
1500 }
1501 }
1502 if !found {
1503 newPorts = append(newPorts, n)
1504 }
khenaidoo2bc48282019-07-16 18:13:46 -04001505 if changed {
1506 changedPorts = append(changedPorts, n)
1507 }
khenaidoofc1314d2019-03-14 09:34:21 -04001508 }
1509 return
1510}
1511
1512// portUpdated is invoked when a port is updated on the logical device. Until
1513// the POST_ADD notification is fixed, we will use the logical device to
1514// update that data.
1515func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1516 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1517
1518 var oldLD *voltha.LogicalDevice
1519 var newlD *voltha.LogicalDevice
1520
1521 var ok bool
1522 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1523 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1524 return nil
1525 }
1526 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1527 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1528 return nil
1529 }
1530
1531 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1532 log.Debug("ports-have-not-changed")
1533 return nil
1534 }
1535
1536 // Get the difference between the two list
1537 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1538
1539 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001540 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301541 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001542 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001543 }
1544 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301545 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001546 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001547 }
1548 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301549 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001550 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001551 }
1552
1553 return nil
1554}
1555
khenaidoo8f474192019-04-03 17:20:44 -04001556// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1557// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1558// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1559// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001560func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001561 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001562 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1563 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1564 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001565 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001566 agent.lockLogicalDevice.RLock()
1567 if agent.portExist(device, port) {
1568 log.Debugw("port-already-exist", log.Fields{"port": port})
1569 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001570 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001571 }
1572 agent.lockLogicalDevice.RUnlock()
1573
khenaidoofc1314d2019-03-14 09:34:21 -04001574 var portCap *ic.PortCapability
1575 var err error
1576 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301577 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), device.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001578 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001579 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001580 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001581
1582 agent.lockLogicalDevice.Lock()
1583 defer agent.lockLogicalDevice.Unlock()
1584 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1585 if agent.portExist(device, port) {
1586 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001587 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001588 }
1589
khenaidoofc1314d2019-03-14 09:34:21 -04001590 portCap.Port.RootPort = true
1591 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1592 lp.DeviceId = device.Id
1593 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1594 lp.OfpPort.PortNo = port.PortNo
1595 lp.OfpPort.Name = lp.Id
1596 lp.DevicePortNo = port.PortNo
1597
khenaidoo6e55d9e2019-12-12 18:26:26 -05001598 ld := agent.getLogicalDeviceWithoutLock()
1599
khenaidoofc1314d2019-03-14 09:34:21 -04001600 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1601 if cloned.Ports == nil {
1602 cloned.Ports = make([]*voltha.LogicalPort, 0)
1603 }
1604 cloned.Ports = append(cloned.Ports, lp)
1605
1606 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1607 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001608 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001609 }
khenaidoo910204f2019-04-08 17:56:40 -04001610
1611 // Update the device graph with this new logical port
1612 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1613 go agent.updateDeviceGraph(clonedLP)
1614
khenaidoo8f474192019-04-03 17:20:44 -04001615 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001616}
1617
khenaidoo910204f2019-04-08 17:56:40 -04001618func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001619 ldevice := agent.getLogicalDeviceWithoutLock()
1620 for _, lPort := range ldevice.Ports {
1621 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1622 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001623 }
1624 }
1625 return false
1626}
1627
khenaidoo8f474192019-04-03 17:20:44 -04001628// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1629// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1630// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1631// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001632func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001633 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001634 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1635 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1636 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001637 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001638 agent.lockLogicalDevice.RLock()
1639 if agent.portExist(childDevice, port) {
1640 log.Debugw("port-already-exist", log.Fields{"port": port})
1641 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001642 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001643 }
1644 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001645 var portCap *ic.PortCapability
1646 var err error
1647 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301648 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), childDevice.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001649 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001650 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001651 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001652 agent.lockLogicalDevice.Lock()
1653 defer agent.lockLogicalDevice.Unlock()
1654 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1655 if agent.portExist(childDevice, port) {
1656 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001657 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001658 }
khenaidoofc1314d2019-03-14 09:34:21 -04001659 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001660 ldevice := agent.getLogicalDeviceWithoutLock()
1661
npujar1d86a522019-11-14 17:11:16 +05301662 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1663 portCap.Port.RootPort = false
1664 portCap.Port.Id = port.Label
1665 portCap.Port.OfpPort.PortNo = port.PortNo
1666 portCap.Port.DeviceId = childDevice.Id
1667 portCap.Port.DevicePortNo = port.PortNo
1668 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1669 if cloned.Ports == nil {
1670 cloned.Ports = make([]*voltha.LogicalPort, 0)
1671 }
1672 cloned.Ports = append(cloned.Ports, portCap.Port)
1673 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1674 return false, err
1675 }
1676 // Update the device graph with this new logical port
1677 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1678 go agent.updateDeviceGraph(clonedLP)
1679 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001680}
1681
khenaidoo43c82122018-11-22 18:38:28 -05001682func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001683 log.Debugw("packet-out", log.Fields{
1684 "packet": hex.EncodeToString(packet.Data),
1685 "inPort": packet.GetInPort(),
1686 })
khenaidoo68c930b2019-05-13 11:46:51 -04001687 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001688 //frame := packet.GetData()
1689 //TODO: Use a channel between the logical agent and the device agent
npujar1d86a522019-11-14 17:11:16 +05301690 if err := agent.deviceMgr.packetOut(agent.rootDeviceID, outPort, packet); err != nil {
1691 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001692 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001693}
1694
npujar1d86a522019-11-14 17:11:16 +05301695func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001696 log.Debugw("packet-in", log.Fields{
1697 "port": port,
1698 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301699 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001700 })
khenaidoo68c930b2019-05-13 11:46:51 -04001701 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301702 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Matteo Scandolo360605d2019-11-05 18:29:17 -08001703 log.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001704}
khenaidoo2c6a0992019-04-29 13:46:56 -04001705
1706func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1707 agent.lockLogicalPortsNo.Lock()
1708 defer agent.lockLogicalPortsNo.Unlock()
1709 if exist := agent.logicalPortsNo[portNo]; !exist {
1710 agent.logicalPortsNo[portNo] = nniPort
1711 }
1712}
1713
khenaidoo3d3b8c22019-05-22 18:10:39 -04001714func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1715 agent.lockLogicalPortsNo.Lock()
1716 defer agent.lockLogicalPortsNo.Unlock()
1717 for _, lp := range lps {
1718 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1719 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1720 }
1721 }
1722}
1723
khenaidoo2c6a0992019-04-29 13:46:56 -04001724func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1725 agent.lockLogicalPortsNo.RLock()
1726 defer agent.lockLogicalPortsNo.RUnlock()
1727 if exist := agent.logicalPortsNo[portNo]; exist {
1728 return agent.logicalPortsNo[portNo]
1729 }
1730 return false
1731}
1732
1733func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1734 agent.lockLogicalPortsNo.RLock()
1735 defer agent.lockLogicalPortsNo.RUnlock()
1736 for portNo, nni := range agent.logicalPortsNo {
1737 if nni {
1738 return portNo, nil
1739 }
1740 }
1741 return 0, status.Error(codes.NotFound, "No NNI port found")
1742}