blob: d9b5837d21ab79bd23ca4d933dde53c0abc0551f [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"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
34 "github.com/opencord/voltha-lib-go/v3/pkg/log"
35 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
37 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
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}
khenaidoo49085352020-01-13 19:15:43 -0500114 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500115
khenaidoo297cd252019-02-07 22:10:23 -0500116 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500117 // Save the logical device
Thomas Lee Se5a44012019-11-07 20:32:24 +0530118 added, err := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, "")
119 if err != nil {
120 log.Errorw("failed-to-save-logical-devices-to-cluster-proxy", log.Fields{"error": err})
121 agent.lockLogicalDevice.Unlock()
122 return err
123 }
124 if added == nil {
npujar1d86a522019-11-14 17:11:16 +0530125 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500126 } else {
npujar1d86a522019-11-14 17:11:16 +0530127 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500128 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500129
130 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoo297cd252019-02-07 22:10:23 -0500131 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400132
khenaidoo3d3b8c22019-05-22 18:10:39 -0400133 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
npujar1d86a522019-11-14 17:11:16 +0530134 go func() {
135 err := agent.setupLogicalPorts(ctx)
136 if err != nil {
137 log.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
138 }
139 }()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400140
khenaidoo297cd252019-02-07 22:10:23 -0500141 } else {
142 // load from dB - the logical may not exist at this time. On error, just return and the calling function
143 // will destroy this agent.
khenaidoo6e55d9e2019-12-12 18:26:26 -0500144 agent.lockLogicalDevice.Lock()
Thomas Lee Se5a44012019-11-07 20:32:24 +0530145 logicalDevice, err := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, true, "")
146 if err != nil {
147 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
148 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500149 ld, ok := logicalDevice.(*voltha.LogicalDevice)
150 if !ok {
151 agent.lockLogicalDevice.Unlock()
152 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500153 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500154 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530155 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400156
khenaidoo6e55d9e2019-12-12 18:26:26 -0500157 // Update the last data
158 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
159
160 agent.lockLogicalDevice.Unlock()
161
khenaidoo3d3b8c22019-05-22 18:10:39 -0400162 // Setup the local list of logical ports
163 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400164 }
khenaidoo92e62c52018-10-03 14:02:54 -0400165 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400166 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400167
Thomas Lee Se5a44012019-11-07 20:32:24 +0530168 agent.flowProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400169 ctx,
npujar1d86a522019-11-14 17:11:16 +0530170 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400171 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530172 if err != nil {
173 log.Errorw("failed-to-create-flow-proxy", log.Fields{"error": err})
174 return err
175 }
176 agent.meterProxy, err = agent.clusterDataProxy.CreateProxy(
Manikkaraj kb1a10922019-07-29 12:10:34 -0400177 ctx,
npujar1d86a522019-11-14 17:11:16 +0530178 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400179 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530180 if err != nil {
181 log.Errorw("failed-to-create-meter-proxy", log.Fields{"error": err})
182 return err
183 }
184 agent.groupProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400185 ctx,
npujar1d86a522019-11-14 17:11:16 +0530186 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400187 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530188 if err != nil {
189 log.Errorw("failed-to-create-group-proxy", log.Fields{"error": err})
190 return err
191 }
192 agent.ldProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400193 ctx,
npujar1d86a522019-11-14 17:11:16 +0530194 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400195 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530196 if err != nil {
197 log.Errorw("failed-to-create-logical-device-proxy", log.Fields{"error": err})
198 return err
199 }
khenaidoofc1314d2019-03-14 09:34:21 -0400200 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400201 if agent.ldProxy != nil {
npujar9a30c702019-11-14 17:06:39 +0530202 agent.ldProxy.RegisterCallback(model.PostUpdate, agent.portUpdated)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400203 } else {
npujar1d86a522019-11-14 17:11:16 +0530204 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400205 return status.Error(codes.Internal, "logical-device-proxy-null")
206 }
khenaidoobcf205b2019-01-25 22:21:14 -0500207
khenaidoo4c9e5592019-09-09 16:20:41 -0400208 // Setup the device graph - run it in its own routine
209 if loadFromdB {
210 go agent.generateDeviceGraph()
211 }
khenaidoob9203542018-09-17 22:56:37 -0400212 return nil
213}
214
khenaidoo4d4802d2018-10-04 21:59:49 -0400215// stop stops the logical devuce agent. This removes the logical device from the data model.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530216func (agent *LogicalDeviceAgent) stop(ctx context.Context) error {
khenaidoo4d4802d2018-10-04 21:59:49 -0400217 log.Info("stopping-logical_device-agent")
218 agent.lockLogicalDevice.Lock()
219 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500220
khenaidoo4d4802d2018-10-04 21:59:49 -0400221 //Remove the logical device from the model
Thomas Lee Se5a44012019-11-07 20:32:24 +0530222 if removed, err := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); err != nil {
223 log.Errorw("failed-to-remove-device", log.Fields{"error": err})
224 return err
225 } else if removed == nil {
npujar1d86a522019-11-14 17:11:16 +0530226 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400227 } else {
npujar1d86a522019-11-14 17:11:16 +0530228 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400229 }
230 agent.exitChannel <- 1
231 log.Info("logical_device-agent-stopped")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530232 return nil
khenaidoo4d4802d2018-10-04 21:59:49 -0400233}
234
khenaidoo6e55d9e2019-12-12 18:26:26 -0500235// GetLogicalDevice returns the latest logical device data
236func (agent *LogicalDeviceAgent) GetLogicalDevice() *voltha.LogicalDevice {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400237 agent.lockLogicalDevice.RLock()
238 defer agent.lockLogicalDevice.RUnlock()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500239
240 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400241}
242
npujar1d86a522019-11-14 17:11:16 +0530243// ListLogicalDeviceFlows returns logical device flows
khenaidoo6e55d9e2019-12-12 18:26:26 -0500244func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() *ofp.Flows {
khenaidoodd237172019-05-27 16:37:17 -0400245 log.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500246
247 logicalDevice := agent.GetLogicalDevice()
248 if logicalDevice.Flows == nil {
249 return &ofp.Flows{}
khenaidoodd237172019-05-27 16:37:17 -0400250 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500251 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows)
khenaidoodd237172019-05-27 16:37:17 -0400252}
253
npujar1d86a522019-11-14 17:11:16 +0530254// ListLogicalDeviceMeters returns logical device meters
khenaidoo6e55d9e2019-12-12 18:26:26 -0500255func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() *ofp.Meters {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400256 log.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500257
258 logicalDevice := agent.GetLogicalDevice()
259 if logicalDevice.Meters == nil {
260 return &ofp.Meters{}
Manikkaraj kb1a10922019-07-29 12:10:34 -0400261 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500262 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400263}
264
npujar1d86a522019-11-14 17:11:16 +0530265// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoo6e55d9e2019-12-12 18:26:26 -0500266func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() *ofp.FlowGroups {
khenaidoodd237172019-05-27 16:37:17 -0400267 log.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500268
269 logicalDevice := agent.GetLogicalDevice()
270 if logicalDevice.FlowGroups == nil {
271 return &ofp.FlowGroups{}
khenaidoodd237172019-05-27 16:37:17 -0400272 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500273 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups)
khenaidoodd237172019-05-27 16:37:17 -0400274}
275
npujar1d86a522019-11-14 17:11:16 +0530276// ListLogicalDevicePorts returns logical device ports
khenaidoo6e55d9e2019-12-12 18:26:26 -0500277func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() *voltha.LogicalPorts {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400278 log.Debug("ListLogicalDevicePorts")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500279 logicalDevice := agent.GetLogicalDevice()
280 lPorts := make([]*voltha.LogicalPort, 0)
281 lPorts = append(lPorts, logicalDevice.Ports...)
282 return &voltha.LogicalPorts{Items: lPorts}
khenaidoo19d7b632018-10-30 10:49:50 -0400283}
284
khenaidoo4c9e5592019-09-09 16:20:41 -0400285//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500286func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500287 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400288
khenaidoo6e55d9e2019-12-12 18:26:26 -0500289 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
290 ld.Flows = flows
291
292 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400293 log.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
294 return err
khenaidoo43c82122018-11-22 18:38:28 -0500295 }
khenaidoo43c82122018-11-22 18:38:28 -0500296 return nil
297}
298
khenaidoo4c9e5592019-09-09 16:20:41 -0400299//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400300func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500301 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400302
khenaidoo6e55d9e2019-12-12 18:26:26 -0500303 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
304 ld.Meters = meters
305
306 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400307 log.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
308 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400309 }
310 return nil
311}
312
khenaidoo4c9e5592019-09-09 16:20:41 -0400313//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
khenaidoo43c82122018-11-22 18:38:28 -0500314func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500315 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400316
khenaidoo6e55d9e2019-12-12 18:26:26 -0500317 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
318 ld.FlowGroups = flowGroups
319
320 if err := agent.updateLogicalDeviceWithoutLock(ld); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400321 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
322 return err
khenaidoo43c82122018-11-22 18:38:28 -0500323 }
khenaidoo43c82122018-11-22 18:38:28 -0500324 return nil
325}
326
khenaidoo6e55d9e2019-12-12 18:26:26 -0500327// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
328func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
khenaidoo92e62c52018-10-03 14:02:54 -0400329 log.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500330 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400331}
332
khenaidoo2c6a0992019-04-29 13:46:56 -0400333func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
334 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
335 var err error
336 if port.Type == voltha.Port_ETHERNET_NNI {
337 if _, err = agent.addNNILogicalPort(device, port); err != nil {
338 return err
339 }
340 agent.addLogicalPortToMap(port.PortNo, true)
341 } else if port.Type == voltha.Port_ETHERNET_UNI {
342 if _, err = agent.addUNILogicalPort(device, port); err != nil {
343 return err
344 }
345 agent.addLogicalPortToMap(port.PortNo, false)
346 } else {
347 // Update the device graph to ensure all routes on the logical device have been calculated
348 if err = agent.updateRoutes(device, port); err != nil {
349 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
350 return err
351 }
352 }
353 return nil
354}
355
khenaidoo3d3b8c22019-05-22 18:10:39 -0400356// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
357// added to it. While the logical device was being created we could have received requests to add
358// NNI and UNI ports which were discarded. Now is the time to add them if needed
359func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
npujar1d86a522019-11-14 17:11:16 +0530360 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400361 // First add any NNI ports which could have been missing
npujar1d86a522019-11-14 17:11:16 +0530362 if err := agent.setupNNILogicalPorts(context.TODO(), agent.rootDeviceID); err != nil {
363 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400364 return err
365 }
366
367 // Now, set up the UNI ports if needed.
npujar1d86a522019-11-14 17:11:16 +0530368 children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceID)
369 if err != nil {
370 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400371 return err
npujar1d86a522019-11-14 17:11:16 +0530372 }
373 responses := make([]coreutils.Response, 0)
374 for _, child := range children.Items {
375 response := coreutils.NewResponse()
376 responses = append(responses, response)
377 go func(child *voltha.Device) {
378 if err = agent.setupUNILogicalPorts(context.TODO(), child); err != nil {
379 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
380 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
381 }
382 response.Done()
383 }(child)
384 }
385 // Wait for completion
386 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
387 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400388 }
389 return nil
390}
391
khenaidoofc1314d2019-03-14 09:34:21 -0400392// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530393func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
394 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400395 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400396 var err error
397
398 var device *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530399 if device, err = agent.deviceMgr.GetDevice(deviceID); err != nil {
400 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400401 return err
402 }
403
404 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400405 for _, port := range device.Ports {
406 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400407 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400408 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400409 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400410 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400411 }
412 }
khenaidoofc1314d2019-03-14 09:34:21 -0400413 return err
414}
415
khenaidoo171b98e2019-10-31 11:48:15 -0400416// updatePortState updates the port state of the device
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800417func (agent *LogicalDeviceAgent) updatePortState(deviceID string, portNo uint32, operStatus voltha.OperStatus_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530418 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo171b98e2019-10-31 11:48:15 -0400419 agent.lockLogicalDevice.Lock()
420 defer agent.lockLogicalDevice.Unlock()
421 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500422 cloned := agent.getLogicalDeviceWithoutLock()
423 for idx, lPort := range cloned.Ports {
npujar1d86a522019-11-14 17:11:16 +0530424 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530425 if operStatus == voltha.OperStatus_ACTIVE {
426 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
427 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
428 } else {
429 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
430 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
431 }
432 // Update the logical device
433 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
434 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
435 return err
436 }
437 return nil
438 }
439 }
440 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400441}
442
khenaidoo3ab34882019-05-02 21:33:30 -0400443// updatePortsState updates the ports state related to the device
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800444func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_Types) error {
npujar1d86a522019-11-14 17:11:16 +0530445 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400446 agent.lockLogicalDevice.Lock()
447 defer agent.lockLogicalDevice.Unlock()
448 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500449 cloned := agent.getLogicalDeviceWithoutLock()
npujar1d86a522019-11-14 17:11:16 +0530450 for _, lport := range cloned.Ports {
451 if lport.DeviceId == device.Id {
452 switch state {
453 case voltha.AdminState_ENABLED:
454 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
455 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
456 case voltha.AdminState_DISABLED:
457 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
458 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
459 default:
460 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
khenaidoo3ab34882019-05-02 21:33:30 -0400461 }
462 }
npujar1d86a522019-11-14 17:11:16 +0530463 }
464 // Updating the logical device will trigger the poprt change events to be populated to the controller
465 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
466 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
467 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400468 }
469 return nil
470}
471
khenaidoofc1314d2019-03-14 09:34:21 -0400472// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
473func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530474 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400475 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400476 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400477 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400478 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400479 for _, port := range childDevice.Ports {
480 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400481 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400482 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400483 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400484 if added {
485 agent.addLogicalPortToMap(port.PortNo, false)
486 }
khenaidoo19d7b632018-10-30 10:49:50 -0400487 }
488 }
khenaidoofc1314d2019-03-14 09:34:21 -0400489 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400490}
491
khenaidoo0a822f92019-05-08 15:15:57 -0400492// deleteAllLogicalPorts deletes all logical ports associated with this device
493func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530494 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400495 agent.lockLogicalDevice.Lock()
496 defer agent.lockLogicalDevice.Unlock()
497 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500498 ld := agent.getLogicalDeviceWithoutLock()
499
npujar1d86a522019-11-14 17:11:16 +0530500 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
501 updateLogicalPorts := []*voltha.LogicalPort{}
502 for _, lport := range cloned.Ports {
503 if lport.DeviceId != device.Id {
504 updateLogicalPorts = append(updateLogicalPorts, lport)
505 }
506 }
507 if len(updateLogicalPorts) < len(cloned.Ports) {
508 cloned.Ports = updateLogicalPorts
509 // Updating the logical device will trigger the poprt change events to be populated to the controller
510 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
511 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
512 return err
513 }
khenaidoo0a822f92019-05-08 15:15:57 -0400514 } else {
npujar1d86a522019-11-14 17:11:16 +0530515 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400516 }
517 return nil
518}
519
khenaidoo92e62c52018-10-03 14:02:54 -0400520//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
521func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400522 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
Thomas Lee Se5a44012019-11-07 20:32:24 +0530523 afterUpdate, err := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
524 if err != nil {
525 log.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
526 return err
527 }
khenaidoo92e62c52018-10-03 14:02:54 -0400528 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530529 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400530 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500531 agent.logicalDevice = (proto.Clone(logicalDevice)).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400532 return nil
533}
534
khenaidoo4c9e5592019-09-09 16:20:41 -0400535//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
536//that device graph was generated.
537func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500538 ld := agent.GetLogicalDevice()
npujar1d86a522019-11-14 17:11:16 +0530539 agent.lockDeviceGraph.Lock()
540 defer agent.lockDeviceGraph.Unlock()
541 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
542 return nil
543 }
544 log.Debug("Generation of device graph required")
545 agent.generateDeviceGraph()
khenaidoo4c9e5592019-09-09 16:20:41 -0400546 return nil
547}
548
khenaidoo19d7b632018-10-30 10:49:50 -0400549//updateFlowTable updates the flow table of that logical device
550func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
551 log.Debug("updateFlowTable")
552 if flow == nil {
553 return nil
554 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400555 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
556 return err
557 }
khenaidoo19d7b632018-10-30 10:49:50 -0400558 switch flow.GetCommand() {
559 case ofp.OfpFlowModCommand_OFPFC_ADD:
560 return agent.flowAdd(flow)
561 case ofp.OfpFlowModCommand_OFPFC_DELETE:
562 return agent.flowDelete(flow)
563 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
564 return agent.flowDeleteStrict(flow)
565 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
566 return agent.flowModify(flow)
567 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
568 return agent.flowModifyStrict(flow)
569 }
570 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530571 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400572}
573
574//updateGroupTable updates the group table of that logical device
575func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
576 log.Debug("updateGroupTable")
577 if groupMod == nil {
578 return nil
579 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400580 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
581 return err
582 }
khenaidoo19d7b632018-10-30 10:49:50 -0400583 switch groupMod.GetCommand() {
584 case ofp.OfpGroupModCommand_OFPGC_ADD:
585 return agent.groupAdd(groupMod)
586 case ofp.OfpGroupModCommand_OFPGC_DELETE:
587 return agent.groupDelete(groupMod)
588 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
589 return agent.groupModify(groupMod)
590 }
591 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530592 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400593}
594
Manikkaraj kb1a10922019-07-29 12:10:34 -0400595// updateMeterTable updates the meter table of that logical device
596func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
597 log.Debug("updateMeterTable")
598 if meterMod == nil {
599 return nil
600 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400601 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
602 return err
603 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400604 switch meterMod.GetCommand() {
605 case ofp.OfpMeterModCommand_OFPMC_ADD:
606 return agent.meterAdd(meterMod)
607 case ofp.OfpMeterModCommand_OFPMC_DELETE:
608 return agent.meterDelete(meterMod)
609 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
610 return agent.meterModify(meterMod)
611 }
612 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530613 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400614
615}
616
617func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
618 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
619 if meterMod == nil {
620 return nil
621 }
622 log.Debug("Waiting for logical device lock!!")
623 agent.lockLogicalDevice.Lock()
624 defer agent.lockLogicalDevice.Unlock()
625 log.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500626 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400627
628 var meters []*ofp.OfpMeterEntry
629 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
630 meters = lDevice.Meters.Items
631 }
632 log.Debugw("Available meters", log.Fields{"meters": meters})
633
634 for _, meter := range meters {
635 if meterMod.MeterId == meter.Config.MeterId {
636 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
637 return nil
638 }
639 }
640
641 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
642 meters = append(meters, meterEntry)
643 //Update model
644 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530645 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400646 return err
647 }
648 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
649 return nil
650}
651
652func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
653 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
654 if meterMod == nil {
655 return nil
656 }
657 agent.lockLogicalDevice.Lock()
658 defer agent.lockLogicalDevice.Unlock()
659
khenaidoo6e55d9e2019-12-12 18:26:26 -0500660 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400661
662 var meters []*ofp.OfpMeterEntry
663 var flows []*ofp.OfpFlowStats
664 updatedFlows := make([]*ofp.OfpFlowStats, 0)
665 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
666 meters = lDevice.Meters.Items
667 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400668
669 changedMeter := false
670 changedFow := false
671 log.Debugw("Available meters", log.Fields{"meters": meters})
672 for index, meter := range meters {
673 if meterMod.MeterId == meter.Config.MeterId {
674 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530675 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400676 meters = append(meters[:index], meters[index+1:]...)
677 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
678 changedMeter = true
679 break
680 }
681 }
682 if changedMeter {
683 //Update model
684 metersToUpdate := &ofp.Meters{}
685 if lDevice.Meters != nil {
686 metersToUpdate = &ofp.Meters{Items: meters}
687 }
688 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530689 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400690 return err
691 }
692 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
693
694 }
695 if changedFow {
696 //Update model
697 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530698 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400699 return err
700 }
701 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
702 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
703 }
704 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
705 return nil
706}
707
708func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
709 log.Debug("meterModify")
710 if meterMod == nil {
711 return nil
712 }
713 agent.lockLogicalDevice.Lock()
714 defer agent.lockLogicalDevice.Unlock()
715
khenaidoo6e55d9e2019-12-12 18:26:26 -0500716 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400717
718 var meters []*ofp.OfpMeterEntry
719 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
720 meters = lDevice.Meters.Items
721 }
722 changedMeter := false
723 for index, meter := range meters {
724 if meterMod.MeterId == meter.Config.MeterId {
725 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
726 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
727 meters[index] = newmeterEntry
728 changedMeter = true
729 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
730 break
731 }
732 }
733 if changedMeter {
734 //Update model
735 metersToUpdate := &ofp.Meters{}
736 if lDevice.Meters != nil {
737 metersToUpdate = &ofp.Meters{Items: meters}
738 }
739 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530740 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400741 return err
742 }
743 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
744 return nil
745 }
746
747 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530748 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400749
750}
751
npujar1d86a522019-11-14 17:11:16 +0530752func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
753 log.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400754 changed := false
755 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
756 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530757 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400758 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
759 flows = append(flows[:index], flows[index+1:]...)
760 changed = true
761 }
762 }
763 return changed, flows
764}
765
766func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
767
768 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530769 meterID := fu.GetMeterIdFromFlow(flow)
770 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
771 if meterID == 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400772 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
773 return false
774 }
775 if meters == nil {
776 log.Debug("No meters present in logical device")
777 return false
778 }
779 changedMeter := false
780 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530781 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400782 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530783 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400784 changedMeter = true
785 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530786 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400787 changedMeter = true
788 }
npujar1d86a522019-11-14 17:11:16 +0530789 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400790 break
791 }
792 }
793 return changedMeter
794}
795
khenaidoo19d7b632018-10-30 10:49:50 -0400796//flowAdd adds a flow to the flow table of that logical device
797func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400798 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400799 if mod == nil {
800 return nil
801 }
khenaidoo92e62c52018-10-03 14:02:54 -0400802 agent.lockLogicalDevice.Lock()
803 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400804
khenaidoo6e55d9e2019-12-12 18:26:26 -0500805 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400806
807 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400808 var meters []*ofp.OfpMeterEntry
809 var flow *ofp.OfpFlowStats
810
khenaidoo19d7b632018-10-30 10:49:50 -0400811 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
812 flows = lDevice.Flows.Items
813 }
814
Manikkaraj kb1a10922019-07-29 12:10:34 -0400815 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
816 meters = lDevice.Meters.Items
817 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400818 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400819 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400820 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400821 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
822 if checkOverlap {
823 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
824 // TODO: should this error be notified other than being logged?
npujar1d86a522019-11-14 17:11:16 +0530825 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400826 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400827 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400828 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400829 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400830 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400831 changed = true
832 }
833 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400834 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400835 idx := fu.FindFlows(flows, flow)
836 if idx >= 0 {
837 oldFlow := flows[idx]
838 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
839 flow.ByteCount = oldFlow.ByteCount
840 flow.PacketCount = oldFlow.PacketCount
841 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400842 if !reflect.DeepEqual(oldFlow, flow) {
843 flows[idx] = flow
844 updatedFlows = append(updatedFlows, flow)
845 changed = true
846 updated = true
847 }
848 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400849 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400850 updatedFlows = append(updatedFlows, flow)
851 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400852 }
khenaidoo19d7b632018-10-30 10:49:50 -0400853 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400854 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
855
khenaidoo19d7b632018-10-30 10:49:50 -0400856 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400857 var flowMetadata voltha.FlowMetadata
858 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
859 log.Error("Meter-referred-in-flows-not-present")
860 return err
861 }
khenaidoo0458db62019-06-20 08:50:36 -0400862 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
863 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
864
Manikkaraj kb1a10922019-07-29 12:10:34 -0400865 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530866 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400867 return err
868 }
869
khenaidoo19d7b632018-10-30 10:49:50 -0400870 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400871 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530872 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400873 return err
874 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400875 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400876 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
877 metersToUpdate := &ofp.Meters{}
878 if lDevice.Meters != nil {
879 metersToUpdate = &ofp.Meters{Items: meters}
880 }
881 if changedMeterStats {
882 //Update model
883 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530884 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400885 return err
886 }
887 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
888
889 }
890 }
891
khenaidoo19d7b632018-10-30 10:49:50 -0400892 }
khenaidoo19d7b632018-10-30 10:49:50 -0400893 return nil
894}
895
npujar1d86a522019-11-14 17:11:16 +0530896// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400897func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
898 m := make(map[uint32]bool)
899 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530900 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400901 foundMeter := false
902 // Meter is present in the flow , Get from logical device
903 for _, meter := range meters {
904 if flowMeterID == meter.Config.MeterId {
905 metadata.Meters = append(metadata.Meters, meter.Config)
906 log.Debugw("Found meter in logical device",
907 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
908 m[flowMeterID] = true
909 foundMeter = true
910 break
911 }
912 }
913 if !foundMeter {
914 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +0530915 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400916 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
917 }
918 }
919 }
920 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
921 return nil
922
923}
924
khenaidoo19d7b632018-10-30 10:49:50 -0400925//flowDelete deletes a flow from the flow table of that logical device
926func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
927 log.Debug("flowDelete")
928 if mod == nil {
929 return nil
930 }
931 agent.lockLogicalDevice.Lock()
932 defer agent.lockLogicalDevice.Unlock()
933
khenaidoo6e55d9e2019-12-12 18:26:26 -0500934 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400935
Manikkaraj kb1a10922019-07-29 12:10:34 -0400936 var meters []*ofp.OfpMeterEntry
937 var flows []*ofp.OfpFlowStats
938
939 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
940 flows = lDevice.Flows.Items
941 }
942
943 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
944 meters = lDevice.Meters.Items
945 }
khenaidoo19d7b632018-10-30 10:49:50 -0400946 //build a list of what to keep vs what to delete
947 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400948 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400949 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -0400950 // Check whether the flow and the flowmod matches
951 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
952 toDelete = append(toDelete, f)
953 continue
954 }
955 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -0400956 if !fu.FlowMatchesMod(f, mod) {
957 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -0400958 } else {
959 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -0400960 }
961 }
962
npujar1d86a522019-11-14 17:11:16 +0530963 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -0400964
khenaidoo19d7b632018-10-30 10:49:50 -0400965 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -0400966 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400967 var flowMetadata voltha.FlowMetadata
968 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
969 log.Error("Meter-referred-in-flows-not-present")
970 return errors.New("Meter-referred-in-flows-not-present")
971 }
khenaidoo0458db62019-06-20 08:50:36 -0400972 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
973 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
974
Manikkaraj kb1a10922019-07-29 12:10:34 -0400975 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530976 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -0400977 return err
978 }
979
khenaidoo43c82122018-11-22 18:38:28 -0500980 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530981 log.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400982 return err
983 }
984 }
985
986 //TODO: send announcement on delete
987 return nil
988}
989
Manikkaraj kb1a10922019-07-29 12:10:34 -0400990func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +0530991 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400992
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500993 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530994 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500995 response := coreutils.NewResponse()
996 responses = append(responses, response)
997 go func(deviceId string, value *fu.FlowsAndGroups) {
998 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400999 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001000 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001001 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001002 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301003 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001004 }
khenaidoo0458db62019-06-20 08:50:36 -04001005 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001006 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001007 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001008 }
khenaidoo0458db62019-06-20 08:50:36 -04001009 return nil
1010}
khenaidoo19d7b632018-10-30 10:49:50 -04001011
Manikkaraj kb1a10922019-07-29 12:10:34 -04001012func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301013 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001014
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001015 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301016 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001017 response := coreutils.NewResponse()
1018 responses = append(responses, response)
1019 go func(deviceId string, value *fu.FlowsAndGroups) {
1020 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001021 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001022 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001023 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001024 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301025 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001026 }
1027 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001028 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001029 return status.Errorf(codes.Aborted, "errors-%s", res)
1030 }
1031 return nil
1032}
1033
Manikkaraj kb1a10922019-07-29 12:10:34 -04001034func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301035 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001036
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001037 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301038 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001039 response := coreutils.NewResponse()
1040 responses = append(responses, response)
1041 go func(deviceId string, value *fu.FlowsAndGroups) {
1042 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001043 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001044 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001045 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001046 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301047 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001048 }
1049 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001050 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001051 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001052 }
1053 return nil
1054}
1055
1056//flowDeleteStrict deletes a flow from the flow table of that logical device
1057func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1058 log.Debug("flowDeleteStrict")
1059 if mod == nil {
1060 return nil
1061 }
1062 agent.lockLogicalDevice.Lock()
1063 defer agent.lockLogicalDevice.Unlock()
1064
khenaidoo6e55d9e2019-12-12 18:26:26 -05001065 lDevice := agent.getLogicalDeviceWithoutLock()
1066
Manikkaraj kb1a10922019-07-29 12:10:34 -04001067 var meters []*ofp.OfpMeterEntry
1068 var flows []*ofp.OfpFlowStats
1069 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1070 meters = lDevice.Meters.Items
1071 }
1072 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1073 flows = lDevice.Flows.Items
1074 }
1075
1076 changedFlow := false
1077 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001078 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001079 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001080 idx := fu.FindFlows(flows, flow)
1081 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001082 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001083 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001084 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001085 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001086 } else {
npujar1d86a522019-11-14 17:11:16 +05301087 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001088 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001089 if changedMeter {
1090 //Update model
1091 metersToUpdate := &ofp.Meters{}
1092 if lDevice.Meters != nil {
1093 metersToUpdate = &ofp.Meters{Items: meters}
1094 }
1095 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301096 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001097 return err
1098 }
khenaidoo19d7b632018-10-30 10:49:50 -04001099
Manikkaraj kb1a10922019-07-29 12:10:34 -04001100 }
1101 if changedFlow {
1102 var flowMetadata voltha.FlowMetadata
1103 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301104 log.Error("meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001105 return err
1106 }
1107 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001108 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1109
Manikkaraj kb1a10922019-07-29 12:10:34 -04001110 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301111 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001112 return err
1113 }
1114
khenaidoo43c82122018-11-22 18:38:28 -05001115 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301116 log.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001117 return err
1118 }
1119 }
khenaidoo19d7b632018-10-30 10:49:50 -04001120 return nil
1121}
1122
1123//flowModify modifies a flow from the flow table of that logical device
1124func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1125 return errors.New("flowModify not implemented")
1126}
1127
1128//flowModifyStrict deletes a flow from the flow table of that logical device
1129func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1130 return errors.New("flowModifyStrict not implemented")
1131}
1132
1133func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1134 log.Debug("groupAdd")
1135 if groupMod == nil {
1136 return nil
1137 }
1138 agent.lockLogicalDevice.Lock()
1139 defer agent.lockLogicalDevice.Unlock()
1140
khenaidoo6e55d9e2019-12-12 18:26:26 -05001141 lDevice := agent.getLogicalDeviceWithoutLock()
1142
khenaidoo19d7b632018-10-30 10:49:50 -04001143 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001144 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001145 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001146
Esin Karaman2ea59212019-12-06 11:41:58 +00001147 deviceRules := fu.NewDeviceRules()
1148 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1149 fg := fu.NewFlowsAndGroups()
1150 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1151 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1152
1153 log.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
1154 if err := agent.addDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301155 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001156 return err
1157 }
1158
khenaidoo43c82122018-11-22 18:38:28 -05001159 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301160 log.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001161 return err
1162 }
1163 } else {
npujar1d86a522019-11-14 17:11:16 +05301164 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001165 }
khenaidoo19d7b632018-10-30 10:49:50 -04001166 return nil
1167}
1168
1169func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1170 log.Debug("groupDelete")
1171 if groupMod == nil {
1172 return nil
1173 }
1174 agent.lockLogicalDevice.Lock()
1175 defer agent.lockLogicalDevice.Unlock()
1176
khenaidoo6e55d9e2019-12-12 18:26:26 -05001177 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001178 groups := lDevice.FlowGroups.Items
1179 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301180 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001181 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301182 groupID := groupMod.GroupId
1183 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001184 //TODO we must delete all flows that point to this group and
1185 //signal controller as requested by flow's flag
1186 groups = []*ofp.OfpGroupEntry{}
1187 groupsChanged = true
1188 } else {
npujar1d86a522019-11-14 17:11:16 +05301189 idx := fu.FindGroup(groups, groupID)
1190 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001191 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001192 }
npujar1d86a522019-11-14 17:11:16 +05301193 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1194 groups = append(groups[:idx], groups[idx+1:]...)
1195 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001196 }
khenaidoo0458db62019-06-20 08:50:36 -04001197 if flowsChanged || groupsChanged {
1198 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1199 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1200
Manikkaraj kb1a10922019-07-29 12:10:34 -04001201 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301202 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001203 return err
1204 }
1205 }
1206
khenaidoo43c82122018-11-22 18:38:28 -05001207 if groupsChanged {
1208 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301209 log.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001210 return err
1211 }
1212 }
khenaidoo43c82122018-11-22 18:38:28 -05001213 if flowsChanged {
1214 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +05301215 log.Errorw("cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo43c82122018-11-22 18:38:28 -05001216 return err
1217 }
1218 }
khenaidoo19d7b632018-10-30 10:49:50 -04001219 return nil
1220}
1221
1222func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1223 log.Debug("groupModify")
1224 if groupMod == nil {
1225 return nil
1226 }
1227 agent.lockLogicalDevice.Lock()
1228 defer agent.lockLogicalDevice.Unlock()
1229
khenaidoo6e55d9e2019-12-12 18:26:26 -05001230 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001231 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301232 var groupsChanged bool
1233 groupID := groupMod.GroupId
1234 idx := fu.FindGroup(groups, groupID)
1235 if idx == -1 {
1236 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001237 }
npujar1d86a522019-11-14 17:11:16 +05301238 //replace existing group entry with new group definition
1239 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1240 groups[idx] = groupEntry
1241 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001242 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001243 deviceRules := fu.NewDeviceRules()
1244 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1245 fg := fu.NewFlowsAndGroups()
1246 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1247 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001248
Esin Karaman2ea59212019-12-06 11:41:58 +00001249 log.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
1250 if err := agent.updateDeviceFlowsAndGroups(deviceRules, &voltha.FlowMetadata{}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301251 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001252 return err
1253 }
1254
khenaidoo43c82122018-11-22 18:38:28 -05001255 //lDevice.FlowGroups.Items = groups
1256 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301257 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001258 return err
1259 }
1260 }
1261 return nil
1262}
1263
1264// deleteLogicalPort removes the logical port
1265func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1266 agent.lockLogicalDevice.Lock()
1267 defer agent.lockLogicalDevice.Unlock()
1268
khenaidoo6e55d9e2019-12-12 18:26:26 -05001269 logicalDevice := agent.getLogicalDeviceWithoutLock()
1270
khenaidoo92e62c52018-10-03 14:02:54 -04001271 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001272 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001273 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001274 index = i
1275 break
1276 }
1277 }
1278 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001279 copy(logicalDevice.Ports[index:], logicalDevice.Ports[index+1:])
1280 logicalDevice.Ports[len(logicalDevice.Ports)-1] = nil
1281 logicalDevice.Ports = logicalDevice.Ports[:len(logicalDevice.Ports)-1]
npujar1d86a522019-11-14 17:11:16 +05301282 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001283 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301284 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001285 return err
1286 }
1287 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001288 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001289 }
1290 return nil
khenaidoob9203542018-09-17 22:56:37 -04001291}
1292
khenaidoo0a822f92019-05-08 15:15:57 -04001293// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar1d86a522019-11-14 17:11:16 +05301294func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001295 agent.lockLogicalDevice.Lock()
1296 defer agent.lockLogicalDevice.Unlock()
1297
khenaidoo6e55d9e2019-12-12 18:26:26 -05001298 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo0a822f92019-05-08 15:15:57 -04001299 updatedLPorts := []*voltha.LogicalPort{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001300 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301301 if logicalPort.DeviceId != deviceID {
khenaidoo0a822f92019-05-08 15:15:57 -04001302 updatedLPorts = append(updatedLPorts, logicalPort)
1303 }
1304 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001305 logicalDevice.Ports = updatedLPorts
khenaidoo0a822f92019-05-08 15:15:57 -04001306 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
khenaidoo6e55d9e2019-12-12 18:26:26 -05001307 if err := agent.updateLogicalDeviceWithoutLock(logicalDevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301308 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001309 return err
1310 }
1311 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001312 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001313
1314 return nil
1315}
1316
khenaidoo19d7b632018-10-30 10:49:50 -04001317// enableLogicalPort enables the logical port
npujar1d86a522019-11-14 17:11:16 +05301318func (agent *LogicalDeviceAgent) enableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001319 agent.lockLogicalDevice.Lock()
1320 defer agent.lockLogicalDevice.Unlock()
1321
khenaidoo6e55d9e2019-12-12 18:26:26 -05001322 logicalDevice := agent.getLogicalDeviceWithoutLock()
1323
khenaidoo19d7b632018-10-30 10:49:50 -04001324 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001325 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301326 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001327 index = i
1328 break
1329 }
1330 }
1331 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001332 logicalDevice.Ports[index].OfpPort.Config = logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1333 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001334 }
npujar1d86a522019-11-14 17:11:16 +05301335 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001336}
1337
1338// disableLogicalPort disabled the logical port
npujar1d86a522019-11-14 17:11:16 +05301339func (agent *LogicalDeviceAgent) disableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001340 agent.lockLogicalDevice.Lock()
1341 defer agent.lockLogicalDevice.Unlock()
1342
1343 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001344 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001345 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001346 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301347 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001348 index = i
1349 break
1350 }
1351 }
1352 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001353 logicalDevice.Ports[index].OfpPort.Config = (logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1354 return agent.updateLogicalDeviceWithoutLock(logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001355 }
npujar1d86a522019-11-14 17:11:16 +05301356 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001357}
1358
khenaidoo89b0e942018-10-21 21:11:33 -04001359func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001360 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001361 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001362 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001363 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1364 return route
1365 }
1366 }
npujar1d86a522019-11-14 17:11:16 +05301367 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "ingress": ingress, "egress": egress})
khenaidoo89b0e942018-10-21 21:11:33 -04001368 return nil
1369}
1370
npujar1d86a522019-11-14 17:11:16 +05301371// GetRoute returns route
khenaidoo19d7b632018-10-30 10:49:50 -04001372func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001373 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001374 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001375
khenaidoo19d7b632018-10-30 10:49:50 -04001376 // Note: A port value of 0 is equivalent to a nil port
1377
khenaidoo89b0e942018-10-21 21:11:33 -04001378 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001379 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001380 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1381 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001382 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001383 if len(agent.deviceGraph.Routes) == 0 {
1384 // 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 -04001385 // route with same IngressHop and EgressHop
npujar1d86a522019-11-14 17:11:16 +05301386 hop := graph.RouteHop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001387 routes = append(routes, hop)
1388 routes = append(routes, hop)
1389 return routes
1390 }
khenaidoo89b0e942018-10-21 21:11:33 -04001391 //Return a 'half' route to make the flow decomposer logic happy
1392 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001393 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001394 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1395 routes = append(routes, route[1])
1396 return routes
1397 }
1398 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001399 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001400 return nil
1401 }
1402 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001403 var err error
1404 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1405 log.Warnw("no-nni-port", log.Fields{"error": err})
1406 return nil
1407 }
khenaidoo89b0e942018-10-21 21:11:33 -04001408 }
1409 //If ingress port is not specified (nil), it may be a wildcarded
1410 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1411 //in which case we need to create a half-route where only the egress
1412 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001413 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001414 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1415 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001416 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001417 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1418 routes = append(routes, route[1])
1419 return routes
1420 }
1421 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001422 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001423 return nil
1424 }
1425 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001426 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001427 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001428 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001429 routes = append(routes, route[0])
1430 routes = append(routes, graph.RouteHop{})
1431 return routes
1432 }
1433 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001434 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001435 return nil
1436 }
khenaidoo89b0e942018-10-21 21:11:33 -04001437 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001438 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001439}
1440
khenaidoo3d3b8c22019-05-22 18:10:39 -04001441//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1442//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1443//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001444func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1445 lPorts := make([]uint32, 0)
1446 var exclPort uint32
1447 if len(excludePort) == 1 {
1448 exclPort = excludePort[0]
1449 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001450 lDevice := agent.getLogicalDeviceWithoutLock()
1451 for _, port := range lDevice.Ports {
1452 if port.OfpPort.PortNo != exclPort {
1453 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001454 }
1455 }
1456 return lPorts
1457}
khenaidoo19d7b632018-10-30 10:49:50 -04001458
npujar1d86a522019-11-14 17:11:16 +05301459// GetDeviceGraph returns device graph
khenaidoo19d7b632018-10-30 10:49:50 -04001460func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1461 return agent.deviceGraph
1462}
1463
khenaidoo3306c992019-05-24 16:57:35 -04001464//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001465func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
npujar1d86a522019-11-14 17:11:16 +05301466 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001467 agent.lockLogicalDevice.Lock()
1468 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001469 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301470 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001471 }
1472 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001473 lDevice := agent.getLogicalDeviceWithoutLock()
1474
npujar1d86a522019-11-14 17:11:16 +05301475 //TODO: Find a better way to refresh only missing routes
1476 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
khenaidoo2c6a0992019-04-29 13:46:56 -04001477 agent.deviceGraph.Print()
1478 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001479}
1480
khenaidoo2c6a0992019-04-29 13:46:56 -04001481//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001482func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
npujar1d86a522019-11-14 17:11:16 +05301483 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -04001484 agent.lockLogicalDevice.Lock()
1485 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001486 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301487 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001488 }
1489 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001490 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001491}
khenaidoofdbad6e2018-11-06 22:26:38 -05001492
khenaidoo3d3b8c22019-05-22 18:10:39 -04001493//generateDeviceGraph regenerates the device graph
1494func (agent *LogicalDeviceAgent) generateDeviceGraph() {
npujar1d86a522019-11-14 17:11:16 +05301495 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001496 agent.lockLogicalDevice.Lock()
1497 defer agent.lockLogicalDevice.Unlock()
1498 // Get the latest logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001499 ld := agent.getLogicalDeviceWithoutLock()
1500 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceID, "lPorts": len(ld.Ports)})
1501 if agent.deviceGraph == nil {
1502 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo0a822f92019-05-08 15:15:57 -04001503 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001504 agent.deviceGraph.ComputeRoutes(ld.Ports)
1505 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001506}
1507
khenaidoofc1314d2019-03-14 09:34:21 -04001508// 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 -04001509func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001510 newPorts = make([]*voltha.LogicalPort, 0)
1511 changedPorts = make([]*voltha.LogicalPort, 0)
1512 deletedPorts = make([]*voltha.LogicalPort, 0)
1513 for _, o := range oldList {
1514 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001515 for _, n := range newList {
1516 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001517 found = true
1518 break
1519 }
1520 }
1521 if !found {
1522 deletedPorts = append(deletedPorts, o)
1523 }
khenaidoofc1314d2019-03-14 09:34:21 -04001524 }
1525 for _, n := range newList {
1526 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001527 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001528 for _, o := range oldList {
1529 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001530 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001531 found = true
1532 break
1533 }
1534 }
1535 if !found {
1536 newPorts = append(newPorts, n)
1537 }
khenaidoo2bc48282019-07-16 18:13:46 -04001538 if changed {
1539 changedPorts = append(changedPorts, n)
1540 }
khenaidoofc1314d2019-03-14 09:34:21 -04001541 }
1542 return
1543}
1544
1545// portUpdated is invoked when a port is updated on the logical device. Until
1546// the POST_ADD notification is fixed, we will use the logical device to
1547// update that data.
1548func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1549 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1550
1551 var oldLD *voltha.LogicalDevice
1552 var newlD *voltha.LogicalDevice
1553
1554 var ok bool
1555 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1556 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1557 return nil
1558 }
1559 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1560 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1561 return nil
1562 }
1563
1564 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1565 log.Debug("ports-have-not-changed")
1566 return nil
1567 }
1568
1569 // Get the difference between the two list
1570 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1571
1572 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001573 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301574 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001575 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001576 }
1577 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301578 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001579 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001580 }
1581 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301582 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001583 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001584 }
1585
1586 return nil
1587}
1588
khenaidoo8f474192019-04-03 17:20:44 -04001589// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1590// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1591// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1592// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001593func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001594 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001595 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1596 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1597 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001598 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001599 agent.lockLogicalDevice.RLock()
1600 if agent.portExist(device, port) {
1601 log.Debugw("port-already-exist", log.Fields{"port": port})
1602 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001603 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001604 }
1605 agent.lockLogicalDevice.RUnlock()
1606
khenaidoofc1314d2019-03-14 09:34:21 -04001607 var portCap *ic.PortCapability
1608 var err error
1609 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301610 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), device.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001611 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001612 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001613 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001614
1615 agent.lockLogicalDevice.Lock()
1616 defer agent.lockLogicalDevice.Unlock()
1617 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1618 if agent.portExist(device, port) {
1619 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001620 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001621 }
1622
khenaidoofc1314d2019-03-14 09:34:21 -04001623 portCap.Port.RootPort = true
1624 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1625 lp.DeviceId = device.Id
1626 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1627 lp.OfpPort.PortNo = port.PortNo
1628 lp.OfpPort.Name = lp.Id
1629 lp.DevicePortNo = port.PortNo
1630
khenaidoo6e55d9e2019-12-12 18:26:26 -05001631 ld := agent.getLogicalDeviceWithoutLock()
1632
khenaidoofc1314d2019-03-14 09:34:21 -04001633 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1634 if cloned.Ports == nil {
1635 cloned.Ports = make([]*voltha.LogicalPort, 0)
1636 }
1637 cloned.Ports = append(cloned.Ports, lp)
1638
1639 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1640 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001641 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001642 }
khenaidoo910204f2019-04-08 17:56:40 -04001643
1644 // Update the device graph with this new logical port
1645 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1646 go agent.updateDeviceGraph(clonedLP)
1647
khenaidoo8f474192019-04-03 17:20:44 -04001648 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001649}
1650
khenaidoo910204f2019-04-08 17:56:40 -04001651func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001652 ldevice := agent.getLogicalDeviceWithoutLock()
1653 for _, lPort := range ldevice.Ports {
1654 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1655 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001656 }
1657 }
1658 return false
1659}
1660
khenaidoo8f474192019-04-03 17:20:44 -04001661// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1662// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1663// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1664// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001665func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001666 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001667 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1668 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1669 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001670 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001671 agent.lockLogicalDevice.RLock()
1672 if agent.portExist(childDevice, port) {
1673 log.Debugw("port-already-exist", log.Fields{"port": port})
1674 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001675 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001676 }
1677 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001678 var portCap *ic.PortCapability
1679 var err error
1680 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301681 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), childDevice.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001682 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001683 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001684 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001685 agent.lockLogicalDevice.Lock()
1686 defer agent.lockLogicalDevice.Unlock()
1687 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1688 if agent.portExist(childDevice, port) {
1689 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001690 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001691 }
khenaidoofc1314d2019-03-14 09:34:21 -04001692 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001693 ldevice := agent.getLogicalDeviceWithoutLock()
1694
npujar1d86a522019-11-14 17:11:16 +05301695 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1696 portCap.Port.RootPort = false
1697 portCap.Port.Id = port.Label
1698 portCap.Port.OfpPort.PortNo = port.PortNo
1699 portCap.Port.DeviceId = childDevice.Id
1700 portCap.Port.DevicePortNo = port.PortNo
1701 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1702 if cloned.Ports == nil {
1703 cloned.Ports = make([]*voltha.LogicalPort, 0)
1704 }
1705 cloned.Ports = append(cloned.Ports, portCap.Port)
1706 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1707 return false, err
1708 }
1709 // Update the device graph with this new logical port
1710 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1711 go agent.updateDeviceGraph(clonedLP)
1712 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001713}
1714
khenaidoo43c82122018-11-22 18:38:28 -05001715func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001716 log.Debugw("packet-out", log.Fields{
1717 "packet": hex.EncodeToString(packet.Data),
1718 "inPort": packet.GetInPort(),
1719 })
khenaidoo68c930b2019-05-13 11:46:51 -04001720 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001721 //frame := packet.GetData()
1722 //TODO: Use a channel between the logical agent and the device agent
npujar1d86a522019-11-14 17:11:16 +05301723 if err := agent.deviceMgr.packetOut(agent.rootDeviceID, outPort, packet); err != nil {
1724 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001725 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001726}
1727
npujar1d86a522019-11-14 17:11:16 +05301728func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001729 log.Debugw("packet-in", log.Fields{
1730 "port": port,
1731 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301732 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001733 })
khenaidoo68c930b2019-05-13 11:46:51 -04001734 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301735 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Matteo Scandolo360605d2019-11-05 18:29:17 -08001736 log.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001737}
khenaidoo2c6a0992019-04-29 13:46:56 -04001738
1739func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1740 agent.lockLogicalPortsNo.Lock()
1741 defer agent.lockLogicalPortsNo.Unlock()
1742 if exist := agent.logicalPortsNo[portNo]; !exist {
1743 agent.logicalPortsNo[portNo] = nniPort
1744 }
1745}
1746
khenaidoo3d3b8c22019-05-22 18:10:39 -04001747func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1748 agent.lockLogicalPortsNo.Lock()
1749 defer agent.lockLogicalPortsNo.Unlock()
1750 for _, lp := range lps {
1751 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1752 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1753 }
1754 }
1755}
1756
khenaidoo2c6a0992019-04-29 13:46:56 -04001757func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1758 agent.lockLogicalPortsNo.RLock()
1759 defer agent.lockLogicalPortsNo.RUnlock()
1760 if exist := agent.logicalPortsNo[portNo]; exist {
1761 return agent.logicalPortsNo[portNo]
1762 }
1763 return false
1764}
1765
1766func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1767 agent.lockLogicalPortsNo.RLock()
1768 defer agent.lockLogicalPortsNo.RUnlock()
1769 for portNo, nni := range agent.logicalPortsNo {
1770 if nni {
1771 return portNo, nil
1772 }
1773 }
1774 return 0, status.Error(codes.NotFound, "No NNI port found")
1775}
Esin Karaman09959ae2019-11-29 13:59:58 +00001776
1777//GetNNIPorts returns NNI ports.
1778func (agent *LogicalDeviceAgent) GetNNIPorts() []uint32 {
1779 agent.lockLogicalPortsNo.RLock()
1780 defer agent.lockLogicalPortsNo.RUnlock()
1781 nniPorts := make([]uint32, 0)
1782 for portNo, nni := range agent.logicalPortsNo {
1783 if nni {
1784 nniPorts = append(nniPorts, portNo)
1785 }
1786 }
1787 return nniPorts
1788}