blob: b85d5728f85fdcc2d6c87ba2415684ca465298df [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
Thomas Lee Se5a44012019-11-07 20:32:24 +053091 var err error
khenaidoo297cd252019-02-07 22:10:23 -050092 if !loadFromdB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040093 //Build the logical device based on information retrieved from the device adapter
94 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -050095 var err error
npujar1d86a522019-11-14 17:11:16 +053096 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -040097 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
98 return err
99 }
npujar1d86a522019-11-14 17:11:16 +0530100 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500101
102 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
103 var datapathID uint64
npujar1d86a522019-11-14 17:11:16 +0530104 if datapathID, err = CreateDataPathID(agent.logicalDeviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500105 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
106 return err
107 }
108 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400109 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
110 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
111 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500112 ld.Flows = &ofp.Flows{Items: nil}
113 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
114
khenaidoo297cd252019-02-07 22:10:23 -0500115 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500116 // Save the logical device
Thomas Lee Se5a44012019-11-07 20:32:24 +0530117 added, err := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, "")
118 if err != nil {
119 log.Errorw("failed-to-save-logical-devices-to-cluster-proxy", log.Fields{"error": err})
120 agent.lockLogicalDevice.Unlock()
121 return err
122 }
123 if added == nil {
npujar1d86a522019-11-14 17:11:16 +0530124 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500125 } else {
npujar1d86a522019-11-14 17:11:16 +0530126 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500127 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500128
129 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoo297cd252019-02-07 22:10:23 -0500130 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400131
khenaidoo3d3b8c22019-05-22 18:10:39 -0400132 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
npujar1d86a522019-11-14 17:11:16 +0530133 go func() {
134 err := agent.setupLogicalPorts(ctx)
135 if err != nil {
136 log.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
137 }
138 }()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400139
khenaidoo297cd252019-02-07 22:10:23 -0500140 } else {
141 // load from dB - the logical may not exist at this time. On error, just return and the calling function
142 // will destroy this agent.
khenaidoo6e55d9e2019-12-12 18:26:26 -0500143 agent.lockLogicalDevice.Lock()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530144 logicalDevice, err := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, true, "")
145 if err != nil {
146 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
147 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500148 ld, ok := logicalDevice.(*voltha.LogicalDevice)
149 if !ok {
150 agent.lockLogicalDevice.Unlock()
151 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500152 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500153 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530154 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400155
khenaidoo6e55d9e2019-12-12 18:26:26 -0500156 // Update the last data
157 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
158
159 agent.lockLogicalDevice.Unlock()
160
khenaidoo3d3b8c22019-05-22 18:10:39 -0400161 // Setup the local list of logical ports
162 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400163 }
khenaidoo92e62c52018-10-03 14:02:54 -0400164 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400165 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400166
Thomas Lee Se5a44012019-11-07 20:32:24 +0530167 agent.flowProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400168 ctx,
npujar1d86a522019-11-14 17:11:16 +0530169 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400170 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530171 if err != nil {
172 log.Errorw("failed-to-create-flow-proxy", log.Fields{"error": err})
173 return err
174 }
175 agent.meterProxy, err = agent.clusterDataProxy.CreateProxy(
Manikkaraj kb1a10922019-07-29 12:10:34 -0400176 ctx,
npujar1d86a522019-11-14 17:11:16 +0530177 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400178 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 if err != nil {
180 log.Errorw("failed-to-create-meter-proxy", log.Fields{"error": err})
181 return err
182 }
183 agent.groupProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400184 ctx,
npujar1d86a522019-11-14 17:11:16 +0530185 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400186 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530187 if err != nil {
188 log.Errorw("failed-to-create-group-proxy", log.Fields{"error": err})
189 return err
190 }
191 agent.ldProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400192 ctx,
npujar1d86a522019-11-14 17:11:16 +0530193 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400194 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530195 if err != nil {
196 log.Errorw("failed-to-create-logical-device-proxy", log.Fields{"error": err})
197 return err
198 }
khenaidoofc1314d2019-03-14 09:34:21 -0400199 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400200 if agent.ldProxy != nil {
201 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
202 } else {
npujar1d86a522019-11-14 17:11:16 +0530203 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400204 return status.Error(codes.Internal, "logical-device-proxy-null")
205 }
khenaidoobcf205b2019-01-25 22:21:14 -0500206
khenaidoo4c9e5592019-09-09 16:20:41 -0400207 // Setup the device graph - run it in its own routine
208 if loadFromdB {
209 go agent.generateDeviceGraph()
210 }
khenaidoob9203542018-09-17 22:56:37 -0400211 return nil
212}
213
khenaidoo4d4802d2018-10-04 21:59:49 -0400214// stop stops the logical devuce agent. This removes the logical device from the data model.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530215func (agent *LogicalDeviceAgent) stop(ctx context.Context) error {
khenaidoo4d4802d2018-10-04 21:59:49 -0400216 log.Info("stopping-logical_device-agent")
217 agent.lockLogicalDevice.Lock()
218 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500219
khenaidoo4d4802d2018-10-04 21:59:49 -0400220 //Remove the logical device from the model
Thomas Lee Se5a44012019-11-07 20:32:24 +0530221 if removed, err := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); err != nil {
222 log.Errorw("failed-to-remove-device", log.Fields{"error": err})
223 return err
224 } else if removed == nil {
npujar1d86a522019-11-14 17:11:16 +0530225 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400226 } else {
npujar1d86a522019-11-14 17:11:16 +0530227 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400228 }
229 agent.exitChannel <- 1
230 log.Info("logical_device-agent-stopped")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530231 return nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400232}
233
khenaidoo6e55d9e2019-12-12 18:26:26 -0500234// GetLogicalDevice returns the latest logical device data
235func (agent *LogicalDeviceAgent) GetLogicalDevice() *voltha.LogicalDevice {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400236 agent.lockLogicalDevice.RLock()
237 defer agent.lockLogicalDevice.RUnlock()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500238
239 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400240}
241
npujar1d86a522019-11-14 17:11:16 +0530242// ListLogicalDeviceFlows returns logical device flows
khenaidoo6e55d9e2019-12-12 18:26:26 -0500243func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() *ofp.Flows {
khenaidoodd237172019-05-27 16:37:17 -0400244 log.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500245
246 logicalDevice := agent.GetLogicalDevice()
247 if logicalDevice.Flows == nil {
248 return &ofp.Flows{}
khenaidoodd237172019-05-27 16:37:17 -0400249 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500250 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows)
khenaidoodd237172019-05-27 16:37:17 -0400251}
252
npujar1d86a522019-11-14 17:11:16 +0530253// ListLogicalDeviceMeters returns logical device meters
khenaidoo6e55d9e2019-12-12 18:26:26 -0500254func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() *ofp.Meters {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400255 log.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500256
257 logicalDevice := agent.GetLogicalDevice()
258 if logicalDevice.Meters == nil {
259 return &ofp.Meters{}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400260 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500261 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400262}
263
npujar1d86a522019-11-14 17:11:16 +0530264// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoo6e55d9e2019-12-12 18:26:26 -0500265func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() *ofp.FlowGroups {
khenaidoodd237172019-05-27 16:37:17 -0400266 log.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500267
268 logicalDevice := agent.GetLogicalDevice()
269 if logicalDevice.FlowGroups == nil {
270 return &ofp.FlowGroups{}
khenaidoodd237172019-05-27 16:37:17 -0400271 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500272 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups)
khenaidoodd237172019-05-27 16:37:17 -0400273}
274
npujar1d86a522019-11-14 17:11:16 +0530275// ListLogicalDevicePorts returns logical device ports
khenaidoo6e55d9e2019-12-12 18:26:26 -0500276func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() *voltha.LogicalPorts {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400277 log.Debug("ListLogicalDevicePorts")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500278 logicalDevice := agent.GetLogicalDevice()
279 lPorts := make([]*voltha.LogicalPort, 0)
280 lPorts = append(lPorts, logicalDevice.Ports...)
281 return &voltha.LogicalPorts{Items: lPorts}
khenaidoo19d7b632018-10-30 10:49:50 -0400282}
283
khenaidoo4c9e5592019-09-09 16:20:41 -0400284//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500285func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) 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.Flows = flows
290
291 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400292 log.Errorw("error-updating-logical-device-with-flows", 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
khenaidoo4c9e5592019-09-09 16:20:41 -0400298//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400299func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500300 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400301
khenaidoo6e55d9e2019-12-12 18:26:26 -0500302 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
303 ld.Meters = meters
304
305 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400306 log.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
307 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400308 }
309 return nil
310}
311
khenaidoo4c9e5592019-09-09 16:20:41 -0400312//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
khenaidoo43c82122018-11-22 18:38:28 -0500313func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500314 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400315
khenaidoo6e55d9e2019-12-12 18:26:26 -0500316 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
317 ld.FlowGroups = flowGroups
318
319 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400320 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
321 return err
khenaidoo43c82122018-11-22 18:38:28 -0500322 }
khenaidoo43c82122018-11-22 18:38:28 -0500323 return nil
324}
325
khenaidoo6e55d9e2019-12-12 18:26:26 -0500326// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
327func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
khenaidoo92e62c52018-10-03 14:02:54 -0400328 log.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500329 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400330}
331
khenaidoo2c6a0992019-04-29 13:46:56 -0400332func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
333 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
334 var err error
335 if port.Type == voltha.Port_ETHERNET_NNI {
336 if _, err = agent.addNNILogicalPort(device, port); err != nil {
337 return err
338 }
339 agent.addLogicalPortToMap(port.PortNo, true)
340 } else if port.Type == voltha.Port_ETHERNET_UNI {
341 if _, err = agent.addUNILogicalPort(device, port); err != nil {
342 return err
343 }
344 agent.addLogicalPortToMap(port.PortNo, false)
345 } else {
346 // Update the device graph to ensure all routes on the logical device have been calculated
347 if err = agent.updateRoutes(device, port); err != nil {
348 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
349 return err
350 }
351 }
352 return nil
353}
354
khenaidoo3d3b8c22019-05-22 18:10:39 -0400355// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
356// added to it. While the logical device was being created we could have received requests to add
357// NNI and UNI ports which were discarded. Now is the time to add them if needed
358func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
npujar1d86a522019-11-14 17:11:16 +0530359 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400360 // First add any NNI ports which could have been missing
npujar1d86a522019-11-14 17:11:16 +0530361 if err := agent.setupNNILogicalPorts(context.TODO(), agent.rootDeviceID); err != nil {
362 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400363 return err
364 }
365
366 // Now, set up the UNI ports if needed.
npujar1d86a522019-11-14 17:11:16 +0530367 children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceID)
368 if err != nil {
369 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400370 return err
npujar1d86a522019-11-14 17:11:16 +0530371 }
372 responses := make([]coreutils.Response, 0)
373 for _, child := range children.Items {
374 response := coreutils.NewResponse()
375 responses = append(responses, response)
376 go func(child *voltha.Device) {
377 if err = agent.setupUNILogicalPorts(context.TODO(), child); err != nil {
378 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
379 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
380 }
381 response.Done()
382 }(child)
383 }
384 // Wait for completion
385 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
386 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400387 }
388 return nil
389}
390
khenaidoofc1314d2019-03-14 09:34:21 -0400391// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530392func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
393 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400394 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400395 var err error
396
397 var device *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530398 if device, err = agent.deviceMgr.GetDevice(deviceID); err != nil {
399 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400400 return err
401 }
402
403 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400404 for _, port := range device.Ports {
405 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400406 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400407 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400408 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400409 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400410 }
411 }
khenaidoofc1314d2019-03-14 09:34:21 -0400412 return err
413}
414
khenaidoo171b98e2019-10-31 11:48:15 -0400415// updatePortState updates the port state of the device
npujar1d86a522019-11-14 17:11:16 +0530416func (agent *LogicalDeviceAgent) updatePortState(deviceID string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
417 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo171b98e2019-10-31 11:48:15 -0400418 agent.lockLogicalDevice.Lock()
419 defer agent.lockLogicalDevice.Unlock()
420 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500421 cloned := agent.getLogicalDeviceWithoutLock()
422 for idx, lPort := range cloned.Ports {
npujar1d86a522019-11-14 17:11:16 +0530423 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530424 if operStatus == voltha.OperStatus_ACTIVE {
425 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
426 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
427 } else {
428 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
429 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
430 }
431 // Update the logical device
432 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
433 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
434 return err
435 }
436 return nil
437 }
438 }
439 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400440}
441
khenaidoo3ab34882019-05-02 21:33:30 -0400442// updatePortsState updates the ports state related to the device
443func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
npujar1d86a522019-11-14 17:11:16 +0530444 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400445 agent.lockLogicalDevice.Lock()
446 defer agent.lockLogicalDevice.Unlock()
447 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500448 cloned := agent.getLogicalDeviceWithoutLock()
npujar1d86a522019-11-14 17:11:16 +0530449 for _, lport := range cloned.Ports {
450 if lport.DeviceId == device.Id {
451 switch state {
452 case voltha.AdminState_ENABLED:
453 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
454 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
455 case voltha.AdminState_DISABLED:
456 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
457 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
458 default:
459 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
khenaidoo3ab34882019-05-02 21:33:30 -0400460 }
461 }
npujar1d86a522019-11-14 17:11:16 +0530462 }
463 // Updating the logical device will trigger the poprt change events to be populated to the controller
464 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
465 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
466 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400467 }
468 return nil
469}
470
khenaidoofc1314d2019-03-14 09:34:21 -0400471// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
472func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530473 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400474 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400475 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400476 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400477 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400478 for _, port := range childDevice.Ports {
479 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400480 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400481 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400482 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400483 if added {
484 agent.addLogicalPortToMap(port.PortNo, false)
485 }
khenaidoo19d7b632018-10-30 10:49:50 -0400486 }
487 }
khenaidoofc1314d2019-03-14 09:34:21 -0400488 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400489}
490
khenaidoo0a822f92019-05-08 15:15:57 -0400491// deleteAllLogicalPorts deletes all logical ports associated with this device
492func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530493 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400494 agent.lockLogicalDevice.Lock()
495 defer agent.lockLogicalDevice.Unlock()
496 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500497 ld := agent.getLogicalDeviceWithoutLock()
498
npujar1d86a522019-11-14 17:11:16 +0530499 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
500 updateLogicalPorts := []*voltha.LogicalPort{}
501 for _, lport := range cloned.Ports {
502 if lport.DeviceId != device.Id {
503 updateLogicalPorts = append(updateLogicalPorts, lport)
504 }
505 }
506 if len(updateLogicalPorts) < len(cloned.Ports) {
507 cloned.Ports = updateLogicalPorts
508 // Updating the logical device will trigger the poprt change events to be populated to the controller
509 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
510 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
511 return err
512 }
khenaidoo0a822f92019-05-08 15:15:57 -0400513 } else {
npujar1d86a522019-11-14 17:11:16 +0530514 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400515 }
516 return nil
517}
518
khenaidoo92e62c52018-10-03 14:02:54 -0400519//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
520func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400521 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
Thomas Lee Se5a44012019-11-07 20:32:24 +0530522 afterUpdate, err := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
523 if err != nil {
524 log.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
525 return err
526 }
khenaidoo92e62c52018-10-03 14:02:54 -0400527 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530528 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400529 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500530 agent.logicalDevice = (proto.Clone(logicalDevice)).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400531 return nil
532}
533
khenaidoo4c9e5592019-09-09 16:20:41 -0400534//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
535//that device graph was generated.
536func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500537 ld := agent.GetLogicalDevice()
npujar1d86a522019-11-14 17:11:16 +0530538 agent.lockDeviceGraph.Lock()
539 defer agent.lockDeviceGraph.Unlock()
540 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
541 return nil
542 }
543 log.Debug("Generation of device graph required")
544 agent.generateDeviceGraph()
khenaidoo4c9e5592019-09-09 16:20:41 -0400545 return nil
546}
547
khenaidoo19d7b632018-10-30 10:49:50 -0400548//updateFlowTable updates the flow table of that logical device
549func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
550 log.Debug("updateFlowTable")
551 if flow == nil {
552 return nil
553 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400554 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
555 return err
556 }
khenaidoo19d7b632018-10-30 10:49:50 -0400557 switch flow.GetCommand() {
558 case ofp.OfpFlowModCommand_OFPFC_ADD:
559 return agent.flowAdd(flow)
560 case ofp.OfpFlowModCommand_OFPFC_DELETE:
561 return agent.flowDelete(flow)
562 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
563 return agent.flowDeleteStrict(flow)
564 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
565 return agent.flowModify(flow)
566 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
567 return agent.flowModifyStrict(flow)
568 }
569 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530570 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400571}
572
573//updateGroupTable updates the group table of that logical device
574func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
575 log.Debug("updateGroupTable")
576 if groupMod == nil {
577 return nil
578 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400579 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
580 return err
581 }
khenaidoo19d7b632018-10-30 10:49:50 -0400582 switch groupMod.GetCommand() {
583 case ofp.OfpGroupModCommand_OFPGC_ADD:
584 return agent.groupAdd(groupMod)
585 case ofp.OfpGroupModCommand_OFPGC_DELETE:
586 return agent.groupDelete(groupMod)
587 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
588 return agent.groupModify(groupMod)
589 }
590 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530591 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400592}
593
Manikkaraj kb1a10922019-07-29 12:10:34 -0400594// updateMeterTable updates the meter table of that logical device
595func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
596 log.Debug("updateMeterTable")
597 if meterMod == nil {
598 return nil
599 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400600 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
601 return err
602 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400603 switch meterMod.GetCommand() {
604 case ofp.OfpMeterModCommand_OFPMC_ADD:
605 return agent.meterAdd(meterMod)
606 case ofp.OfpMeterModCommand_OFPMC_DELETE:
607 return agent.meterDelete(meterMod)
608 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
609 return agent.meterModify(meterMod)
610 }
611 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530612 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400613
614}
615
616func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
617 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
618 if meterMod == nil {
619 return nil
620 }
621 log.Debug("Waiting for logical device lock!!")
622 agent.lockLogicalDevice.Lock()
623 defer agent.lockLogicalDevice.Unlock()
624 log.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500625 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400626
627 var meters []*ofp.OfpMeterEntry
628 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
629 meters = lDevice.Meters.Items
630 }
631 log.Debugw("Available meters", log.Fields{"meters": meters})
632
633 for _, meter := range meters {
634 if meterMod.MeterId == meter.Config.MeterId {
635 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
636 return nil
637 }
638 }
639
640 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
641 meters = append(meters, meterEntry)
642 //Update model
643 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530644 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400645 return err
646 }
647 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
648 return nil
649}
650
651func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
652 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
653 if meterMod == nil {
654 return nil
655 }
656 agent.lockLogicalDevice.Lock()
657 defer agent.lockLogicalDevice.Unlock()
658
khenaidoo6e55d9e2019-12-12 18:26:26 -0500659 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400660
661 var meters []*ofp.OfpMeterEntry
662 var flows []*ofp.OfpFlowStats
663 updatedFlows := make([]*ofp.OfpFlowStats, 0)
664 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
665 meters = lDevice.Meters.Items
666 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400667
668 changedMeter := false
669 changedFow := false
670 log.Debugw("Available meters", log.Fields{"meters": meters})
671 for index, meter := range meters {
672 if meterMod.MeterId == meter.Config.MeterId {
673 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530674 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400675 meters = append(meters[:index], meters[index+1:]...)
676 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
677 changedMeter = true
678 break
679 }
680 }
681 if changedMeter {
682 //Update model
683 metersToUpdate := &ofp.Meters{}
684 if lDevice.Meters != nil {
685 metersToUpdate = &ofp.Meters{Items: meters}
686 }
687 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530688 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400689 return err
690 }
691 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
692
693 }
694 if changedFow {
695 //Update model
696 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530697 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400698 return err
699 }
700 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
701 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
702 }
703 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
704 return nil
705}
706
707func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
708 log.Debug("meterModify")
709 if meterMod == nil {
710 return nil
711 }
712 agent.lockLogicalDevice.Lock()
713 defer agent.lockLogicalDevice.Unlock()
714
khenaidoo6e55d9e2019-12-12 18:26:26 -0500715 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400716
717 var meters []*ofp.OfpMeterEntry
718 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
719 meters = lDevice.Meters.Items
720 }
721 changedMeter := false
722 for index, meter := range meters {
723 if meterMod.MeterId == meter.Config.MeterId {
724 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
725 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
726 meters[index] = newmeterEntry
727 changedMeter = true
728 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
729 break
730 }
731 }
732 if changedMeter {
733 //Update model
734 metersToUpdate := &ofp.Meters{}
735 if lDevice.Meters != nil {
736 metersToUpdate = &ofp.Meters{Items: meters}
737 }
738 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530739 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400740 return err
741 }
742 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
743 return nil
744 }
745
746 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530747 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400748
749}
750
npujar1d86a522019-11-14 17:11:16 +0530751func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
752 log.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400753 changed := false
754 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
755 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530756 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400757 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
758 flows = append(flows[:index], flows[index+1:]...)
759 changed = true
760 }
761 }
762 return changed, flows
763}
764
765func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
766
767 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530768 meterID := fu.GetMeterIdFromFlow(flow)
769 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
770 if meterID == 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400771 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
772 return false
773 }
774 if meters == nil {
775 log.Debug("No meters present in logical device")
776 return false
777 }
778 changedMeter := false
779 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530780 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400781 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530782 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400783 changedMeter = true
784 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530785 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400786 changedMeter = true
787 }
npujar1d86a522019-11-14 17:11:16 +0530788 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400789 break
790 }
791 }
792 return changedMeter
793}
794
khenaidoo19d7b632018-10-30 10:49:50 -0400795//flowAdd adds a flow to the flow table of that logical device
796func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400797 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400798 if mod == nil {
799 return nil
800 }
khenaidoo92e62c52018-10-03 14:02:54 -0400801 agent.lockLogicalDevice.Lock()
802 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400803
khenaidoo6e55d9e2019-12-12 18:26:26 -0500804 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400805
806 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400807 var meters []*ofp.OfpMeterEntry
808 var flow *ofp.OfpFlowStats
809
khenaidoo19d7b632018-10-30 10:49:50 -0400810 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
811 flows = lDevice.Flows.Items
812 }
813
Manikkaraj kb1a10922019-07-29 12:10:34 -0400814 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
815 meters = lDevice.Meters.Items
816 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400817 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400818 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400819 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400820 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
821 if checkOverlap {
822 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
823 // TODO: should this error be notified other than being logged?
npujar1d86a522019-11-14 17:11:16 +0530824 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400825 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400826 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400827 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400828 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400829 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400830 changed = true
831 }
832 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400833 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400834 idx := fu.FindFlows(flows, flow)
835 if idx >= 0 {
836 oldFlow := flows[idx]
837 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
838 flow.ByteCount = oldFlow.ByteCount
839 flow.PacketCount = oldFlow.PacketCount
840 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400841 if !reflect.DeepEqual(oldFlow, flow) {
842 flows[idx] = flow
843 updatedFlows = append(updatedFlows, flow)
844 changed = true
845 updated = true
846 }
847 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400848 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400849 updatedFlows = append(updatedFlows, flow)
850 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400851 }
khenaidoo19d7b632018-10-30 10:49:50 -0400852 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400853 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
854
khenaidoo19d7b632018-10-30 10:49:50 -0400855 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400856 var flowMetadata voltha.FlowMetadata
857 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
858 log.Error("Meter-referred-in-flows-not-present")
859 return err
860 }
khenaidoo0458db62019-06-20 08:50:36 -0400861 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
862 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
863
Manikkaraj kb1a10922019-07-29 12:10:34 -0400864 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530865 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400866 return err
867 }
868
khenaidoo19d7b632018-10-30 10:49:50 -0400869 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400870 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530871 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400872 return err
873 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400874 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400875 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
876 metersToUpdate := &ofp.Meters{}
877 if lDevice.Meters != nil {
878 metersToUpdate = &ofp.Meters{Items: meters}
879 }
880 if changedMeterStats {
881 //Update model
882 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530883 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400884 return err
885 }
886 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
887
888 }
889 }
890
khenaidoo19d7b632018-10-30 10:49:50 -0400891 }
khenaidoo19d7b632018-10-30 10:49:50 -0400892 return nil
893}
894
npujar1d86a522019-11-14 17:11:16 +0530895// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400896func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
897 m := make(map[uint32]bool)
898 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530899 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400900 foundMeter := false
901 // Meter is present in the flow , Get from logical device
902 for _, meter := range meters {
903 if flowMeterID == meter.Config.MeterId {
904 metadata.Meters = append(metadata.Meters, meter.Config)
905 log.Debugw("Found meter in logical device",
906 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
907 m[flowMeterID] = true
908 foundMeter = true
909 break
910 }
911 }
912 if !foundMeter {
913 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +0530914 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400915 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
916 }
917 }
918 }
919 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
920 return nil
921
922}
923
khenaidoo19d7b632018-10-30 10:49:50 -0400924//flowDelete deletes a flow from the flow table of that logical device
925func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
926 log.Debug("flowDelete")
927 if mod == nil {
928 return nil
929 }
930 agent.lockLogicalDevice.Lock()
931 defer agent.lockLogicalDevice.Unlock()
932
khenaidoo6e55d9e2019-12-12 18:26:26 -0500933 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400934
Manikkaraj kb1a10922019-07-29 12:10:34 -0400935 var meters []*ofp.OfpMeterEntry
936 var flows []*ofp.OfpFlowStats
937
938 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
939 flows = lDevice.Flows.Items
940 }
941
942 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
943 meters = lDevice.Meters.Items
944 }
khenaidoo19d7b632018-10-30 10:49:50 -0400945 //build a list of what to keep vs what to delete
946 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400947 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400948 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -0400949 // Check whether the flow and the flowmod matches
950 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
951 toDelete = append(toDelete, f)
952 continue
953 }
954 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -0400955 if !fu.FlowMatchesMod(f, mod) {
956 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -0400957 } else {
958 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -0400959 }
960 }
961
npujar1d86a522019-11-14 17:11:16 +0530962 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -0400963
khenaidoo19d7b632018-10-30 10:49:50 -0400964 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -0400965 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400966 var flowMetadata voltha.FlowMetadata
967 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
968 log.Error("Meter-referred-in-flows-not-present")
969 return errors.New("Meter-referred-in-flows-not-present")
970 }
khenaidoo0458db62019-06-20 08:50:36 -0400971 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
972 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
973
Manikkaraj kb1a10922019-07-29 12:10:34 -0400974 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530975 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -0400976 return err
977 }
978
khenaidoo43c82122018-11-22 18:38:28 -0500979 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530980 log.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400981 return err
982 }
983 }
984
985 //TODO: send announcement on delete
986 return nil
987}
988
Manikkaraj kb1a10922019-07-29 12:10:34 -0400989func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530990 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400991
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500992 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530993 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500994 response := coreutils.NewResponse()
995 responses = append(responses, response)
996 go func(deviceId string, value *fu.FlowsAndGroups) {
997 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400998 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500999 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001000 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001001 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301002 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001003 }
khenaidoo0458db62019-06-20 08:50:36 -04001004 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001005 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001006 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001007 }
khenaidoo0458db62019-06-20 08:50:36 -04001008 return nil
1009}
khenaidoo19d7b632018-10-30 10:49:50 -04001010
Manikkaraj kb1a10922019-07-29 12:10:34 -04001011func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301012 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001013
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001014 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301015 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001016 response := coreutils.NewResponse()
1017 responses = append(responses, response)
1018 go func(deviceId string, value *fu.FlowsAndGroups) {
1019 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001020 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001021 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001022 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001023 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301024 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001025 }
1026 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001027 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001028 return status.Errorf(codes.Aborted, "errors-%s", res)
1029 }
1030 return nil
1031}
1032
Manikkaraj kb1a10922019-07-29 12:10:34 -04001033func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301034 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001035
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001036 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301037 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001038 response := coreutils.NewResponse()
1039 responses = append(responses, response)
1040 go func(deviceId string, value *fu.FlowsAndGroups) {
1041 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001042 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001043 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001044 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001045 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301046 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001047 }
1048 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001049 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001050 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001051 }
1052 return nil
1053}
1054
1055//flowDeleteStrict deletes a flow from the flow table of that logical device
1056func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1057 log.Debug("flowDeleteStrict")
1058 if mod == nil {
1059 return nil
1060 }
1061 agent.lockLogicalDevice.Lock()
1062 defer agent.lockLogicalDevice.Unlock()
1063
khenaidoo6e55d9e2019-12-12 18:26:26 -05001064 lDevice := agent.getLogicalDeviceWithoutLock()
1065
Manikkaraj kb1a10922019-07-29 12:10:34 -04001066 var meters []*ofp.OfpMeterEntry
1067 var flows []*ofp.OfpFlowStats
1068 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1069 meters = lDevice.Meters.Items
1070 }
1071 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1072 flows = lDevice.Flows.Items
1073 }
1074
1075 changedFlow := false
1076 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001077 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001078 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001079 idx := fu.FindFlows(flows, flow)
1080 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001081 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001082 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001083 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001084 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001085 } else {
npujar1d86a522019-11-14 17:11:16 +05301086 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001087 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001088 if changedMeter {
1089 //Update model
1090 metersToUpdate := &ofp.Meters{}
1091 if lDevice.Meters != nil {
1092 metersToUpdate = &ofp.Meters{Items: meters}
1093 }
1094 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301095 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001096 return err
1097 }
khenaidoo19d7b632018-10-30 10:49:50 -04001098
Manikkaraj kb1a10922019-07-29 12:10:34 -04001099 }
1100 if changedFlow {
1101 var flowMetadata voltha.FlowMetadata
1102 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301103 log.Error("meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001104 return err
1105 }
1106 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001107 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1108
Manikkaraj kb1a10922019-07-29 12:10:34 -04001109 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301110 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001111 return err
1112 }
1113
khenaidoo43c82122018-11-22 18:38:28 -05001114 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301115 log.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001116 return err
1117 }
1118 }
khenaidoo19d7b632018-10-30 10:49:50 -04001119 return nil
1120}
1121
1122//flowModify modifies a flow from the flow table of that logical device
1123func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1124 return errors.New("flowModify not implemented")
1125}
1126
1127//flowModifyStrict deletes a flow from the flow table of that logical device
1128func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1129 return errors.New("flowModifyStrict not implemented")
1130}
1131
1132func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1133 log.Debug("groupAdd")
1134 if groupMod == nil {
1135 return nil
1136 }
1137 agent.lockLogicalDevice.Lock()
1138 defer agent.lockLogicalDevice.Unlock()
1139
khenaidoo6e55d9e2019-12-12 18:26:26 -05001140 lDevice := agent.getLogicalDeviceWithoutLock()
1141
khenaidoo19d7b632018-10-30 10:49:50 -04001142 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001143 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001144 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001145
Esin Karaman2ea59212019-12-06 11:41:58 +00001146 deviceRules := fu.NewDeviceRules()
1147 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1148 fg := fu.NewFlowsAndGroups()
1149 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1150 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1151
1152 log.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
1153 if err := agent.addDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301154 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001155 return err
1156 }
1157
khenaidoo43c82122018-11-22 18:38:28 -05001158 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301159 log.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001160 return err
1161 }
1162 } else {
npujar1d86a522019-11-14 17:11:16 +05301163 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001164 }
khenaidoo19d7b632018-10-30 10:49:50 -04001165 return nil
1166}
1167
1168func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1169 log.Debug("groupDelete")
1170 if groupMod == nil {
1171 return nil
1172 }
1173 agent.lockLogicalDevice.Lock()
1174 defer agent.lockLogicalDevice.Unlock()
1175
khenaidoo6e55d9e2019-12-12 18:26:26 -05001176 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001177 groups := lDevice.FlowGroups.Items
1178 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301179 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001180 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301181 groupID := groupMod.GroupId
1182 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001183 //TODO we must delete all flows that point to this group and
1184 //signal controller as requested by flow's flag
1185 groups = []*ofp.OfpGroupEntry{}
1186 groupsChanged = true
1187 } else {
npujar1d86a522019-11-14 17:11:16 +05301188 idx := fu.FindGroup(groups, groupID)
1189 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001190 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001191 }
npujar1d86a522019-11-14 17:11:16 +05301192 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1193 groups = append(groups[:idx], groups[idx+1:]...)
1194 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001195 }
khenaidoo0458db62019-06-20 08:50:36 -04001196 if flowsChanged || groupsChanged {
1197 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1198 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1199
Manikkaraj kb1a10922019-07-29 12:10:34 -04001200 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301201 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001202 return err
1203 }
1204 }
1205
khenaidoo43c82122018-11-22 18:38:28 -05001206 if groupsChanged {
1207 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301208 log.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001209 return err
1210 }
1211 }
khenaidoo43c82122018-11-22 18:38:28 -05001212 if flowsChanged {
1213 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301214 log.Errorw("cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo43c82122018-11-22 18:38:28 -05001215 return err
1216 }
1217 }
khenaidoo19d7b632018-10-30 10:49:50 -04001218 return nil
1219}
1220
1221func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1222 log.Debug("groupModify")
1223 if groupMod == nil {
1224 return nil
1225 }
1226 agent.lockLogicalDevice.Lock()
1227 defer agent.lockLogicalDevice.Unlock()
1228
khenaidoo6e55d9e2019-12-12 18:26:26 -05001229 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001230 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301231 var groupsChanged bool
1232 groupID := groupMod.GroupId
1233 idx := fu.FindGroup(groups, groupID)
1234 if idx == -1 {
1235 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001236 }
npujar1d86a522019-11-14 17:11:16 +05301237 //replace existing group entry with new group definition
1238 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1239 groups[idx] = groupEntry
1240 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001241 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001242 deviceRules := fu.NewDeviceRules()
1243 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1244 fg := fu.NewFlowsAndGroups()
1245 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1246 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001247
Esin Karaman2ea59212019-12-06 11:41:58 +00001248 log.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
1249 if err := agent.updateDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301250 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001251 return err
1252 }
1253
khenaidoo43c82122018-11-22 18:38:28 -05001254 //lDevice.FlowGroups.Items = groups
1255 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301256 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001257 return err
1258 }
1259 }
1260 return nil
1261}
1262
1263// deleteLogicalPort removes the logical port
1264func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1265 agent.lockLogicalDevice.Lock()
1266 defer agent.lockLogicalDevice.Unlock()
1267
khenaidoo6e55d9e2019-12-12 18:26:26 -05001268 logicalDevice := agent.getLogicalDeviceWithoutLock()
1269
khenaidoo92e62c52018-10-03 14:02:54 -04001270 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001271 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001272 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001273 index = i
1274 break
1275 }
1276 }
1277 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001278 copy(logicalDevice.Ports[index:], logicalDevice.Ports[index+1:])
1279 logicalDevice.Ports[len(logicalDevice.Ports)-1] = nil
1280 logicalDevice.Ports = logicalDevice.Ports[:len(logicalDevice.Ports)-1]
npujar1d86a522019-11-14 17:11:16 +05301281 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001282 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301283 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001284 return err
1285 }
1286 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001287 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001288 }
1289 return nil
khenaidoob9203542018-09-17 22:56:37 -04001290}
1291
khenaidoo0a822f92019-05-08 15:15:57 -04001292// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar1d86a522019-11-14 17:11:16 +05301293func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001294 agent.lockLogicalDevice.Lock()
1295 defer agent.lockLogicalDevice.Unlock()
1296
khenaidoo6e55d9e2019-12-12 18:26:26 -05001297 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo0a822f92019-05-08 15:15:57 -04001298 updatedLPorts := []*voltha.LogicalPort{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001299 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301300 if logicalPort.DeviceId != deviceID {
khenaidoo0a822f92019-05-08 15:15:57 -04001301 updatedLPorts = append(updatedLPorts, logicalPort)
1302 }
1303 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001304 logicalDevice.Ports = updatedLPorts
khenaidoo0a822f92019-05-08 15:15:57 -04001305 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001306 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301307 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001308 return err
1309 }
1310 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001311 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001312
1313 return nil
1314}
1315
khenaidoo19d7b632018-10-30 10:49:50 -04001316// enableLogicalPort enables the logical port
npujar1d86a522019-11-14 17:11:16 +05301317func (agent *LogicalDeviceAgent) enableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001318 agent.lockLogicalDevice.Lock()
1319 defer agent.lockLogicalDevice.Unlock()
1320
khenaidoo6e55d9e2019-12-12 18:26:26 -05001321 logicalDevice := agent.getLogicalDeviceWithoutLock()
1322
khenaidoo19d7b632018-10-30 10:49:50 -04001323 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001324 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301325 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001326 index = i
1327 break
1328 }
1329 }
1330 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001331 logicalDevice.Ports[index].OfpPort.Config = logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1332 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001333 }
npujar1d86a522019-11-14 17:11:16 +05301334 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001335}
1336
1337// disableLogicalPort disabled the logical port
npujar1d86a522019-11-14 17:11:16 +05301338func (agent *LogicalDeviceAgent) disableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001339 agent.lockLogicalDevice.Lock()
1340 defer agent.lockLogicalDevice.Unlock()
1341
1342 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001343 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001344 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001345 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301346 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001347 index = i
1348 break
1349 }
1350 }
1351 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001352 logicalDevice.Ports[index].OfpPort.Config = (logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1353 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001354 }
npujar1d86a522019-11-14 17:11:16 +05301355 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001356}
1357
khenaidoo89b0e942018-10-21 21:11:33 -04001358func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001359 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001360 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001361 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001362 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1363 return route
1364 }
1365 }
npujar1d86a522019-11-14 17:11:16 +05301366 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "ingress": ingress, "egress": egress})
khenaidoo89b0e942018-10-21 21:11:33 -04001367 return nil
1368}
1369
npujar1d86a522019-11-14 17:11:16 +05301370// GetRoute returns route
khenaidoo19d7b632018-10-30 10:49:50 -04001371func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001372 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001373 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001374
khenaidoo19d7b632018-10-30 10:49:50 -04001375 // Note: A port value of 0 is equivalent to a nil port
1376
khenaidoo89b0e942018-10-21 21:11:33 -04001377 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001378 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001379 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1380 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001381 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001382 if len(agent.deviceGraph.Routes) == 0 {
1383 // 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 -04001384 // route with same IngressHop and EgressHop
npujar1d86a522019-11-14 17:11:16 +05301385 hop := graph.RouteHop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001386 routes = append(routes, hop)
1387 routes = append(routes, hop)
1388 return routes
1389 }
khenaidoo89b0e942018-10-21 21:11:33 -04001390 //Return a 'half' route to make the flow decomposer logic happy
1391 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001392 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001393 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1394 routes = append(routes, route[1])
1395 return routes
1396 }
1397 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001398 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001399 return nil
1400 }
1401 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001402 var err error
1403 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1404 log.Warnw("no-nni-port", log.Fields{"error": err})
1405 return nil
1406 }
khenaidoo89b0e942018-10-21 21:11:33 -04001407 }
1408 //If ingress port is not specified (nil), it may be a wildcarded
1409 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1410 //in which case we need to create a half-route where only the egress
1411 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001412 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001413 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1414 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001415 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001416 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1417 routes = append(routes, route[1])
1418 return routes
1419 }
1420 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001421 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001422 return nil
1423 }
1424 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001425 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001426 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001427 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001428 routes = append(routes, route[0])
1429 routes = append(routes, graph.RouteHop{})
1430 return routes
1431 }
1432 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001433 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001434 return nil
1435 }
khenaidoo89b0e942018-10-21 21:11:33 -04001436 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001437 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001438}
1439
khenaidoo3d3b8c22019-05-22 18:10:39 -04001440//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1441//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1442//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001443func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1444 lPorts := make([]uint32, 0)
1445 var exclPort uint32
1446 if len(excludePort) == 1 {
1447 exclPort = excludePort[0]
1448 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001449 lDevice := agent.getLogicalDeviceWithoutLock()
1450 for _, port := range lDevice.Ports {
1451 if port.OfpPort.PortNo != exclPort {
1452 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001453 }
1454 }
1455 return lPorts
1456}
khenaidoo19d7b632018-10-30 10:49:50 -04001457
npujar1d86a522019-11-14 17:11:16 +05301458// GetDeviceGraph returns device graph
khenaidoo19d7b632018-10-30 10:49:50 -04001459func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1460 return agent.deviceGraph
1461}
1462
khenaidoo3306c992019-05-24 16:57:35 -04001463//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001464func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
npujar1d86a522019-11-14 17:11:16 +05301465 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001466 agent.lockLogicalDevice.Lock()
1467 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001468 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301469 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001470 }
1471 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001472 lDevice := agent.getLogicalDeviceWithoutLock()
1473
npujar1d86a522019-11-14 17:11:16 +05301474 //TODO: Find a better way to refresh only missing routes
1475 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
khenaidoo2c6a0992019-04-29 13:46:56 -04001476 agent.deviceGraph.Print()
1477 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001478}
1479
khenaidoo2c6a0992019-04-29 13:46:56 -04001480//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001481func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
npujar1d86a522019-11-14 17:11:16 +05301482 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -04001483 agent.lockLogicalDevice.Lock()
1484 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001485 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301486 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001487 }
1488 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001489 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001490}
khenaidoofdbad6e2018-11-06 22:26:38 -05001491
khenaidoo3d3b8c22019-05-22 18:10:39 -04001492//generateDeviceGraph regenerates the device graph
1493func (agent *LogicalDeviceAgent) generateDeviceGraph() {
npujar1d86a522019-11-14 17:11:16 +05301494 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001495 agent.lockLogicalDevice.Lock()
1496 defer agent.lockLogicalDevice.Unlock()
1497 // Get the latest logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001498 ld := agent.getLogicalDeviceWithoutLock()
1499 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceID, "lPorts": len(ld.Ports)})
1500 if agent.deviceGraph == nil {
1501 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001502 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001503 agent.deviceGraph.ComputeRoutes(ld.Ports)
1504 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001505}
1506
khenaidoofc1314d2019-03-14 09:34:21 -04001507// 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 -04001508func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001509 newPorts = make([]*voltha.LogicalPort, 0)
1510 changedPorts = make([]*voltha.LogicalPort, 0)
1511 deletedPorts = make([]*voltha.LogicalPort, 0)
1512 for _, o := range oldList {
1513 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001514 for _, n := range newList {
1515 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001516 found = true
1517 break
1518 }
1519 }
1520 if !found {
1521 deletedPorts = append(deletedPorts, o)
1522 }
khenaidoofc1314d2019-03-14 09:34:21 -04001523 }
1524 for _, n := range newList {
1525 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001526 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001527 for _, o := range oldList {
1528 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001529 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001530 found = true
1531 break
1532 }
1533 }
1534 if !found {
1535 newPorts = append(newPorts, n)
1536 }
khenaidoo2bc48282019-07-16 18:13:46 -04001537 if changed {
1538 changedPorts = append(changedPorts, n)
1539 }
khenaidoofc1314d2019-03-14 09:34:21 -04001540 }
1541 return
1542}
1543
1544// portUpdated is invoked when a port is updated on the logical device. Until
1545// the POST_ADD notification is fixed, we will use the logical device to
1546// update that data.
1547func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1548 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1549
1550 var oldLD *voltha.LogicalDevice
1551 var newlD *voltha.LogicalDevice
1552
1553 var ok bool
1554 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1555 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1556 return nil
1557 }
1558 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1559 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1560 return nil
1561 }
1562
1563 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1564 log.Debug("ports-have-not-changed")
1565 return nil
1566 }
1567
1568 // Get the difference between the two list
1569 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1570
1571 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001572 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301573 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001574 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001575 }
1576 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301577 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001578 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001579 }
1580 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301581 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001582 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001583 }
1584
1585 return nil
1586}
1587
khenaidoo8f474192019-04-03 17:20:44 -04001588// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1589// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1590// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1591// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001592func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001593 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001594 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1595 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1596 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001597 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001598 agent.lockLogicalDevice.RLock()
1599 if agent.portExist(device, port) {
1600 log.Debugw("port-already-exist", log.Fields{"port": port})
1601 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001602 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001603 }
1604 agent.lockLogicalDevice.RUnlock()
1605
khenaidoofc1314d2019-03-14 09:34:21 -04001606 var portCap *ic.PortCapability
1607 var err error
1608 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301609 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), device.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001610 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001611 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001612 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001613
1614 agent.lockLogicalDevice.Lock()
1615 defer agent.lockLogicalDevice.Unlock()
1616 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1617 if agent.portExist(device, port) {
1618 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001619 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001620 }
1621
khenaidoofc1314d2019-03-14 09:34:21 -04001622 portCap.Port.RootPort = true
1623 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1624 lp.DeviceId = device.Id
1625 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1626 lp.OfpPort.PortNo = port.PortNo
1627 lp.OfpPort.Name = lp.Id
1628 lp.DevicePortNo = port.PortNo
1629
khenaidoo6e55d9e2019-12-12 18:26:26 -05001630 ld := agent.getLogicalDeviceWithoutLock()
1631
khenaidoofc1314d2019-03-14 09:34:21 -04001632 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1633 if cloned.Ports == nil {
1634 cloned.Ports = make([]*voltha.LogicalPort, 0)
1635 }
1636 cloned.Ports = append(cloned.Ports, lp)
1637
1638 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1639 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001640 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001641 }
khenaidoo910204f2019-04-08 17:56:40 -04001642
1643 // Update the device graph with this new logical port
1644 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1645 go agent.updateDeviceGraph(clonedLP)
1646
khenaidoo8f474192019-04-03 17:20:44 -04001647 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001648}
1649
khenaidoo910204f2019-04-08 17:56:40 -04001650func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001651 ldevice := agent.getLogicalDeviceWithoutLock()
1652 for _, lPort := range ldevice.Ports {
1653 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1654 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001655 }
1656 }
1657 return false
1658}
1659
khenaidoo8f474192019-04-03 17:20:44 -04001660// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1661// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1662// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1663// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001664func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001665 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001666 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1667 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1668 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001669 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001670 agent.lockLogicalDevice.RLock()
1671 if agent.portExist(childDevice, port) {
1672 log.Debugw("port-already-exist", log.Fields{"port": port})
1673 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001674 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001675 }
1676 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001677 var portCap *ic.PortCapability
1678 var err error
1679 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301680 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), childDevice.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001681 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001682 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001683 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001684 agent.lockLogicalDevice.Lock()
1685 defer agent.lockLogicalDevice.Unlock()
1686 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1687 if agent.portExist(childDevice, port) {
1688 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001689 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001690 }
khenaidoofc1314d2019-03-14 09:34:21 -04001691 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001692 ldevice := agent.getLogicalDeviceWithoutLock()
1693
npujar1d86a522019-11-14 17:11:16 +05301694 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1695 portCap.Port.RootPort = false
1696 portCap.Port.Id = port.Label
1697 portCap.Port.OfpPort.PortNo = port.PortNo
1698 portCap.Port.DeviceId = childDevice.Id
1699 portCap.Port.DevicePortNo = port.PortNo
1700 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1701 if cloned.Ports == nil {
1702 cloned.Ports = make([]*voltha.LogicalPort, 0)
1703 }
1704 cloned.Ports = append(cloned.Ports, portCap.Port)
1705 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1706 return false, err
1707 }
1708 // Update the device graph with this new logical port
1709 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1710 go agent.updateDeviceGraph(clonedLP)
1711 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001712}
1713
khenaidoo43c82122018-11-22 18:38:28 -05001714func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001715 log.Debugw("packet-out", log.Fields{
1716 "packet": hex.EncodeToString(packet.Data),
1717 "inPort": packet.GetInPort(),
1718 })
khenaidoo68c930b2019-05-13 11:46:51 -04001719 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001720 //frame := packet.GetData()
1721 //TODO: Use a channel between the logical agent and the device agent
npujar1d86a522019-11-14 17:11:16 +05301722 if err := agent.deviceMgr.packetOut(agent.rootDeviceID, outPort, packet); err != nil {
1723 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001724 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001725}
1726
npujar1d86a522019-11-14 17:11:16 +05301727func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001728 log.Debugw("packet-in", log.Fields{
1729 "port": port,
1730 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301731 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001732 })
khenaidoo68c930b2019-05-13 11:46:51 -04001733 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301734 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Matteo Scandolo360605d2019-11-05 18:29:17 -08001735 log.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001736}
khenaidoo2c6a0992019-04-29 13:46:56 -04001737
1738func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1739 agent.lockLogicalPortsNo.Lock()
1740 defer agent.lockLogicalPortsNo.Unlock()
1741 if exist := agent.logicalPortsNo[portNo]; !exist {
1742 agent.logicalPortsNo[portNo] = nniPort
1743 }
1744}
1745
khenaidoo3d3b8c22019-05-22 18:10:39 -04001746func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1747 agent.lockLogicalPortsNo.Lock()
1748 defer agent.lockLogicalPortsNo.Unlock()
1749 for _, lp := range lps {
1750 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1751 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1752 }
1753 }
1754}
1755
khenaidoo2c6a0992019-04-29 13:46:56 -04001756func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1757 agent.lockLogicalPortsNo.RLock()
1758 defer agent.lockLogicalPortsNo.RUnlock()
1759 if exist := agent.logicalPortsNo[portNo]; exist {
1760 return agent.logicalPortsNo[portNo]
1761 }
1762 return false
1763}
1764
1765func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1766 agent.lockLogicalPortsNo.RLock()
1767 defer agent.lockLogicalPortsNo.RUnlock()
1768 for portNo, nni := range agent.logicalPortsNo {
1769 if nni {
1770 return portNo, nil
1771 }
1772 }
1773 return 0, status.Error(codes.NotFound, "No NNI port found")
1774}