blob: 3dbc2df7e95169be6fcac438e8f4fa0eabd3efd5 [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 */
16package core
17
18import (
19 "context"
Matteo Scandolo360605d2019-11-05 18:29:17 -080020 "encoding/hex"
khenaidoo19d7b632018-10-30 10:49:50 -040021 "errors"
22 "fmt"
khenaidoob9203542018-09-17 22:56:37 -040023 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050024 "github.com/opencord/voltha-go/db/model"
khenaidoo89b0e942018-10-21 21:11:33 -040025 fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
26 "github.com/opencord/voltha-go/rw_core/graph"
Scott Bakerb671a862019-10-24 10:53:40 -070027 coreutils "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070028 fu "github.com/opencord/voltha-lib-go/v2/pkg/flows"
29 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker555307d2019-11-04 08:58:01 -080030 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
31 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
32 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040033 "google.golang.org/grpc/codes"
34 "google.golang.org/grpc/status"
khenaidoo19d7b632018-10-30 10:49:50 -040035 "reflect"
khenaidoo92e62c52018-10-03 14:02:54 -040036 "sync"
Stephane Barbarieef6650d2019-07-18 12:15:09 -040037 "time"
khenaidoob9203542018-09-17 22:56:37 -040038)
39
40type LogicalDeviceAgent struct {
khenaidoo3306c992019-05-24 16:57:35 -040041 logicalDeviceId string
42 rootDeviceId string
43 deviceMgr *DeviceManager
44 ldeviceMgr *LogicalDeviceManager
45 clusterDataProxy *model.Proxy
46 exitChannel chan int
47 deviceGraph *graph.DeviceGraph
48 flowProxy *model.Proxy
49 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040050 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040051 ldProxy *model.Proxy
52 portProxies map[string]*model.Proxy
53 portProxiesLock sync.RWMutex
54 lockLogicalDevice sync.RWMutex
khenaidoo4c9e5592019-09-09 16:20:41 -040055 lockDeviceGraph sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040056 logicalPortsNo map[uint32]bool //value is true for NNI port
57 lockLogicalPortsNo sync.RWMutex
58 flowDecomposer *fd.FlowDecomposer
59 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040060}
61
Stephane Barbarie1ab43272018-12-08 21:42:13 -050062func newLogicalDeviceAgent(id string, deviceId string, ldeviceMgr *LogicalDeviceManager,
63 deviceMgr *DeviceManager,
khenaidoo2c6a0992019-04-29 13:46:56 -040064 cdProxy *model.Proxy, timeout int64) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040065 var agent LogicalDeviceAgent
66 agent.exitChannel = make(chan int, 1)
67 agent.logicalDeviceId = id
Stephane Barbarie1ab43272018-12-08 21:42:13 -050068 agent.rootDeviceId = deviceId
khenaidoob9203542018-09-17 22:56:37 -040069 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040070 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040071 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040072 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040073 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoofc1314d2019-03-14 09:34:21 -040074 agent.portProxies = make(map[string]*model.Proxy)
75 agent.portProxiesLock = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040076 agent.lockLogicalPortsNo = sync.RWMutex{}
khenaidoo4c9e5592019-09-09 16:20:41 -040077 agent.lockDeviceGraph = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040078 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040079 agent.defaultTimeout = timeout
khenaidoob9203542018-09-17 22:56:37 -040080 return &agent
81}
82
khenaidoo4d4802d2018-10-04 21:59:49 -040083// start creates the logical device and add it to the data model
khenaidoo297cd252019-02-07 22:10:23 -050084func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
85 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId, "loadFromdB": loadFromdB})
86 var ld *voltha.LogicalDevice
87 if !loadFromdB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040088 //Build the logical device based on information retrieved from the device adapter
89 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -050090 var err error
khenaidoo7e3d8f12019-08-02 16:06:30 -040091 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
92 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
93 return err
94 }
khenaidoo297cd252019-02-07 22:10:23 -050095 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
96
97 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
98 var datapathID uint64
99 if datapathID, err = CreateDataPathId(agent.logicalDeviceId); err != nil {
100 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
101 return err
102 }
103 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400104 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
105 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
106 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500107 ld.Flows = &ofp.Flows{Items: nil}
108 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
109
khenaidoo297cd252019-02-07 22:10:23 -0500110 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500111 // Save the logical device
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400112 if added := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, ""); added == nil {
khenaidoo297cd252019-02-07 22:10:23 -0500113 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
114 } else {
115 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
116 }
117 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400118
khenaidoo3d3b8c22019-05-22 18:10:39 -0400119 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
120 go agent.setupLogicalPorts(ctx)
121
khenaidoo297cd252019-02-07 22:10:23 -0500122 } else {
123 // load from dB - the logical may not exist at this time. On error, just return and the calling function
124 // will destroy this agent.
125 var err error
126 if ld, err = agent.GetLogicalDevice(); err != nil {
127 log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
128 return err
129 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400130
khenaidoo8c3303d2019-02-13 14:59:39 -0500131 // Update the root device Id
132 agent.rootDeviceId = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400133
134 // Setup the local list of logical ports
135 agent.addLogicalPortsToMap(ld.Ports)
136
khenaidoob9203542018-09-17 22:56:37 -0400137 }
khenaidoo92e62c52018-10-03 14:02:54 -0400138 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400139 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400140
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400141 agent.flowProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400142 ctx,
khenaidoo19d7b632018-10-30 10:49:50 -0400143 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceId),
144 false)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400145 agent.meterProxy = agent.clusterDataProxy.CreateProxy(
146 ctx,
147 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceId),
148 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400149 agent.groupProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400150 ctx,
khenaidoo19d7b632018-10-30 10:49:50 -0400151 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceId),
152 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400153 agent.ldProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400154 ctx,
khenaidoofc1314d2019-03-14 09:34:21 -0400155 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceId),
156 false)
khenaidoo19d7b632018-10-30 10:49:50 -0400157
khenaidoofc1314d2019-03-14 09:34:21 -0400158 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400159 if agent.ldProxy != nil {
160 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
161 } else {
162 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
163 return status.Error(codes.Internal, "logical-device-proxy-null")
164 }
khenaidoobcf205b2019-01-25 22:21:14 -0500165
khenaidoo4c9e5592019-09-09 16:20:41 -0400166 // Setup the device graph - run it in its own routine
167 if loadFromdB {
168 go agent.generateDeviceGraph()
169 }
khenaidoob9203542018-09-17 22:56:37 -0400170 return nil
171}
172
khenaidoo4d4802d2018-10-04 21:59:49 -0400173// stop stops the logical devuce agent. This removes the logical device from the data model.
174func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
175 log.Info("stopping-logical_device-agent")
176 agent.lockLogicalDevice.Lock()
177 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500178
khenaidoo4d4802d2018-10-04 21:59:49 -0400179 //Remove the logical device from the model
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400180 if removed := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400181 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
182 } else {
183 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
184 }
185 agent.exitChannel <- 1
186 log.Info("logical_device-agent-stopped")
187}
188
khenaidoo19d7b632018-10-30 10:49:50 -0400189// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
190func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
191 log.Debug("GetLogicalDevice")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400192 agent.lockLogicalDevice.RLock()
193 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400194 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400195 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500196 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400197 }
198 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
199}
200
khenaidoodd237172019-05-27 16:37:17 -0400201func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() (*ofp.Flows, error) {
202 log.Debug("ListLogicalDeviceFlows")
203 agent.lockLogicalDevice.RLock()
204 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400205 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400206 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
207 cFlows := (proto.Clone(lDevice.Flows)).(*ofp.Flows)
208 return cFlows, nil
209 }
210 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
211}
212
Manikkaraj kb1a10922019-07-29 12:10:34 -0400213func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() (*ofp.Meters, error) {
214 log.Debug("ListLogicalDeviceMeters")
215 agent.lockLogicalDevice.RLock()
216 defer agent.lockLogicalDevice.RUnlock()
217 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
218 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Gamze Abaka6e4ac162019-10-21 11:10:10 +0000219 if lDevice.Meters == nil {
220 return &ofp.Meters{}, nil
221 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400222 cMeters := (proto.Clone(lDevice.Meters)).(*ofp.Meters)
223 return cMeters, nil
224 }
225 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
226}
227
khenaidoodd237172019-05-27 16:37:17 -0400228func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() (*ofp.FlowGroups, error) {
229 log.Debug("ListLogicalDeviceFlowGroups")
230 agent.lockLogicalDevice.RLock()
231 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400232 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400233 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
234 cFlowGroups := (proto.Clone(lDevice.FlowGroups)).(*ofp.FlowGroups)
235 return cFlowGroups, nil
236 }
237 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
238}
239
khenaidoo19d7b632018-10-30 10:49:50 -0400240func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400241 log.Debug("ListLogicalDevicePorts")
242 agent.lockLogicalDevice.RLock()
243 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400244 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400245 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
246 lPorts := make([]*voltha.LogicalPort, 0)
247 for _, port := range lDevice.Ports {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500248 lPorts = append(lPorts, port)
khenaidoo19d7b632018-10-30 10:49:50 -0400249 }
250 return &voltha.LogicalPorts{Items: lPorts}, nil
251 }
252 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
253}
254
255// listFlows locks the logical device model and then retrieves the latest flow information
256func (agent *LogicalDeviceAgent) listFlows() []*ofp.OfpFlowStats {
257 log.Debug("listFlows")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400258 agent.lockLogicalDevice.RLock()
259 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400260 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400261 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
262 return lDevice.Flows.Items
263 }
264 return nil
265}
266
267// listFlowGroups locks the logical device model and then retrieves the latest flow groups information
268func (agent *LogicalDeviceAgent) listFlowGroups() []*ofp.OfpGroupEntry {
269 log.Debug("listFlowGroups")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400270 agent.lockLogicalDevice.RLock()
271 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400272 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400273 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
274 return lDevice.FlowGroups.Items
275 }
276 return nil
277}
278
khenaidoo4c9e5592019-09-09 16:20:41 -0400279//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500280func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400281 ld, err := agent.getLogicalDeviceWithoutLock()
282 if err != nil {
283 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
284 }
285 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
286 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
287 cloned.Flows = flows
288
289 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
290 log.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
291 return err
khenaidoo43c82122018-11-22 18:38:28 -0500292 }
khenaidoo43c82122018-11-22 18:38:28 -0500293 return nil
294}
295
khenaidoo4c9e5592019-09-09 16:20:41 -0400296//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400297func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400298 ld, err := agent.getLogicalDeviceWithoutLock()
299 if err != nil {
300 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
301 }
302 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
303 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
304 cloned.Meters = meters
305
306 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
307 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 {
khenaidoo4c9e5592019-09-09 16:20:41 -0400315 ld, err := agent.getLogicalDeviceWithoutLock()
316 if err != nil {
317 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
318 }
319 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
320 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
321 cloned.FlowGroups = flowGroups
322
323 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
324 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
325 return err
khenaidoo43c82122018-11-22 18:38:28 -0500326 }
khenaidoo43c82122018-11-22 18:38:28 -0500327 return nil
328}
329
khenaidoo4d4802d2018-10-04 21:59:49 -0400330// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
331// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400332func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
333 log.Debug("getLogicalDeviceWithoutLock")
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400334 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400335 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400336 //log.Debug("getLogicalDeviceWithoutLock", log.Fields{"ldevice": lDevice})
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500337 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400338 }
339 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
340}
341
khenaidoo2c6a0992019-04-29 13:46:56 -0400342func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
343 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
344 var err error
345 if port.Type == voltha.Port_ETHERNET_NNI {
346 if _, err = agent.addNNILogicalPort(device, port); err != nil {
347 return err
348 }
349 agent.addLogicalPortToMap(port.PortNo, true)
350 } else if port.Type == voltha.Port_ETHERNET_UNI {
351 if _, err = agent.addUNILogicalPort(device, port); err != nil {
352 return err
353 }
354 agent.addLogicalPortToMap(port.PortNo, false)
355 } else {
356 // Update the device graph to ensure all routes on the logical device have been calculated
357 if err = agent.updateRoutes(device, port); err != nil {
358 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
359 return err
360 }
361 }
362 return nil
363}
364
khenaidoo910204f2019-04-08 17:56:40 -0400365func (agent *LogicalDeviceAgent) addLogicalPort(device *voltha.Device, port *voltha.Port) error {
khenaidoo8f474192019-04-03 17:20:44 -0400366 log.Debugw("addLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
khenaidoo8f474192019-04-03 17:20:44 -0400367 var err error
khenaidoofc1314d2019-03-14 09:34:21 -0400368 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400369 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400370 return err
371 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400372 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400373 } else if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo910204f2019-04-08 17:56:40 -0400374 if _, err = agent.addUNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400375 return err
376 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400377 agent.addLogicalPortToMap(port.PortNo, false)
khenaidoofc1314d2019-03-14 09:34:21 -0400378 } else {
379 log.Debugw("invalid-port-type", log.Fields{"deviceId": device.Id, "port": port})
380 return nil
381 }
khenaidoofc1314d2019-03-14 09:34:21 -0400382 return nil
383}
384
khenaidoo3d3b8c22019-05-22 18:10:39 -0400385// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
386// added to it. While the logical device was being created we could have received requests to add
387// NNI and UNI ports which were discarded. Now is the time to add them if needed
388func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
389 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
390 // First add any NNI ports which could have been missing
391 if err := agent.setupNNILogicalPorts(nil, agent.rootDeviceId); err != nil {
392 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceId})
393 return err
394 }
395
396 // Now, set up the UNI ports if needed.
397 if children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceId); err != nil {
398 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceId})
399 return err
400 } else {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500401 responses := make([]coreutils.Response, 0)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400402 for _, child := range children.Items {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500403 response := coreutils.NewResponse()
404 responses = append(responses, response)
405 go func(child *voltha.Device) {
406 if err = agent.setupUNILogicalPorts(nil, child); err != nil {
407 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
408 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
khenaidoo3d3b8c22019-05-22 18:10:39 -0400409 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500410 response.Done()
411 }(child)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400412 }
413 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500414 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400415 return status.Errorf(codes.Aborted, "errors-%s", res)
416 }
417 }
418 return nil
419}
420
khenaidoofc1314d2019-03-14 09:34:21 -0400421// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
422func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceId string) error {
423 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400424 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400425 var err error
426
427 var device *voltha.Device
428 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400429 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceId})
khenaidoofc1314d2019-03-14 09:34:21 -0400430 return err
431 }
432
433 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400434 for _, port := range device.Ports {
435 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400436 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400437 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400438 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400439 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400440 }
441 }
khenaidoofc1314d2019-03-14 09:34:21 -0400442 return err
443}
444
khenaidoo171b98e2019-10-31 11:48:15 -0400445// updatePortState updates the port state of the device
446func (agent *LogicalDeviceAgent) updatePortState(deviceId string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
447 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "portNo": portNo, "state": operStatus})
448 agent.lockLogicalDevice.Lock()
449 defer agent.lockLogicalDevice.Unlock()
450 // Get the latest logical device info
451 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
452 log.Warnw("logical-device-unknown", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
453 return err
454 } else {
455 for idx, lPort := range ld.Ports {
456 if lPort.DeviceId == deviceId && lPort.DevicePortNo == portNo {
457 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
458 if operStatus == voltha.OperStatus_ACTIVE {
459 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
460 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
461 } else {
462 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
463 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
464 }
465 // Update the logical device
466 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
467 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
468 return err
469 }
470 return nil
471 }
472 }
473 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
474 }
475}
476
khenaidoo3ab34882019-05-02 21:33:30 -0400477// updatePortsState updates the ports state related to the device
478func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
479 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
480 agent.lockLogicalDevice.Lock()
481 defer agent.lockLogicalDevice.Unlock()
482 // Get the latest logical device info
483 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
484 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
485 return err
486 } else {
487 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
488 for _, lport := range cloned.Ports {
489 if lport.DeviceId == device.Id {
490 switch state {
491 case voltha.AdminState_ENABLED:
492 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
khenaidoo0a822f92019-05-08 15:15:57 -0400493 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
khenaidoo3ab34882019-05-02 21:33:30 -0400494 case voltha.AdminState_DISABLED:
495 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
khenaidoo0a822f92019-05-08 15:15:57 -0400496 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
khenaidoo3ab34882019-05-02 21:33:30 -0400497 default:
498 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
499 }
500 }
501 }
502 // Updating the logical device will trigger the poprt change events to be populated to the controller
503 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
504 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
505 return err
506 }
507 }
508 return nil
509}
510
khenaidoofc1314d2019-03-14 09:34:21 -0400511// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
512func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400513 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoofc1314d2019-03-14 09:34:21 -0400514 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400515 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400516 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400517 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400518 for _, port := range childDevice.Ports {
519 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400520 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400521 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400522 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400523 if added {
524 agent.addLogicalPortToMap(port.PortNo, false)
525 }
khenaidoo19d7b632018-10-30 10:49:50 -0400526 }
527 }
khenaidoofc1314d2019-03-14 09:34:21 -0400528 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400529}
530
khenaidoo0a822f92019-05-08 15:15:57 -0400531// deleteAllLogicalPorts deletes all logical ports associated with this device
532func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
533 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
534 agent.lockLogicalDevice.Lock()
535 defer agent.lockLogicalDevice.Unlock()
536 // Get the latest logical device info
537 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
538 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
539 return err
540 } else {
541 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
542 updateLogicalPorts := []*voltha.LogicalPort{}
543 for _, lport := range cloned.Ports {
544 if lport.DeviceId != device.Id {
545 updateLogicalPorts = append(updateLogicalPorts, lport)
546 }
547 }
548 if len(updateLogicalPorts) < len(cloned.Ports) {
549 cloned.Ports = updateLogicalPorts
550 // Updating the logical device will trigger the poprt change events to be populated to the controller
551 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
552 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
553 return err
554 }
555 } else {
556 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
557 }
558 }
559 return nil
560}
561
khenaidoo92e62c52018-10-03 14:02:54 -0400562//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
563func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400564 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
565 afterUpdate := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400566 if afterUpdate == nil {
567 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
568 }
569 return nil
570}
571
khenaidoo4c9e5592019-09-09 16:20:41 -0400572//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
573//that device graph was generated.
574func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
575 if ld, err := agent.GetLogicalDevice(); err != nil {
576 log.Errorw("get-logical-device-error", log.Fields{"error": err})
577 return err
578 } else {
579 agent.lockDeviceGraph.Lock()
580 defer agent.lockDeviceGraph.Unlock()
581 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
582 return nil
583 }
584 log.Debug("Generation of device graph required")
585 agent.generateDeviceGraph()
586 }
587 return nil
588}
589
khenaidoo19d7b632018-10-30 10:49:50 -0400590//updateFlowTable updates the flow table of that logical device
591func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
592 log.Debug("updateFlowTable")
593 if flow == nil {
594 return nil
595 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400596 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
597 return err
598 }
khenaidoo19d7b632018-10-30 10:49:50 -0400599 switch flow.GetCommand() {
600 case ofp.OfpFlowModCommand_OFPFC_ADD:
601 return agent.flowAdd(flow)
602 case ofp.OfpFlowModCommand_OFPFC_DELETE:
603 return agent.flowDelete(flow)
604 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
605 return agent.flowDeleteStrict(flow)
606 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
607 return agent.flowModify(flow)
608 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
609 return agent.flowModifyStrict(flow)
610 }
611 return status.Errorf(codes.Internal,
612 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
613}
614
615//updateGroupTable updates the group table of that logical device
616func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
617 log.Debug("updateGroupTable")
618 if groupMod == nil {
619 return nil
620 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400621 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
622 return err
623 }
khenaidoo19d7b632018-10-30 10:49:50 -0400624 switch groupMod.GetCommand() {
625 case ofp.OfpGroupModCommand_OFPGC_ADD:
626 return agent.groupAdd(groupMod)
627 case ofp.OfpGroupModCommand_OFPGC_DELETE:
628 return agent.groupDelete(groupMod)
629 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
630 return agent.groupModify(groupMod)
631 }
632 return status.Errorf(codes.Internal,
633 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
634}
635
Manikkaraj kb1a10922019-07-29 12:10:34 -0400636// updateMeterTable updates the meter table of that logical device
637func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
638 log.Debug("updateMeterTable")
639 if meterMod == nil {
640 return nil
641 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400642 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
643 return err
644 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400645 switch meterMod.GetCommand() {
646 case ofp.OfpMeterModCommand_OFPMC_ADD:
647 return agent.meterAdd(meterMod)
648 case ofp.OfpMeterModCommand_OFPMC_DELETE:
649 return agent.meterDelete(meterMod)
650 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
651 return agent.meterModify(meterMod)
652 }
653 return status.Errorf(codes.Internal,
654 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, meterMod.GetCommand())
655
656}
657
658func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
659 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
660 if meterMod == nil {
661 return nil
662 }
663 log.Debug("Waiting for logical device lock!!")
664 agent.lockLogicalDevice.Lock()
665 defer agent.lockLogicalDevice.Unlock()
666 log.Debug("Acquired logical device lock")
667 var lDevice *voltha.LogicalDevice
668 var err error
669 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
670 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
671 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
672 }
673
674 var meters []*ofp.OfpMeterEntry
675 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
676 meters = lDevice.Meters.Items
677 }
678 log.Debugw("Available meters", log.Fields{"meters": meters})
679
680 for _, meter := range meters {
681 if meterMod.MeterId == meter.Config.MeterId {
682 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
683 return nil
684 }
685 }
686
687 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
688 meters = append(meters, meterEntry)
689 //Update model
690 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
691 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
692 return err
693 }
694 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
695 return nil
696}
697
698func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
699 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
700 if meterMod == nil {
701 return nil
702 }
703 agent.lockLogicalDevice.Lock()
704 defer agent.lockLogicalDevice.Unlock()
705
706 var lDevice *voltha.LogicalDevice
707 var err error
708 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
709 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
710 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
711 }
712
713 var meters []*ofp.OfpMeterEntry
714 var flows []*ofp.OfpFlowStats
715 updatedFlows := make([]*ofp.OfpFlowStats, 0)
716 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
717 meters = lDevice.Meters.Items
718 }
719 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
720 flows = lDevice.Flows.Items
721 }
722
723 changedMeter := false
724 changedFow := false
725 log.Debugw("Available meters", log.Fields{"meters": meters})
726 for index, meter := range meters {
727 if meterMod.MeterId == meter.Config.MeterId {
728 flows = lDevice.Flows.Items
729 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterId(flows, meterMod.MeterId)
730 meters = append(meters[:index], meters[index+1:]...)
731 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
732 changedMeter = true
733 break
734 }
735 }
736 if changedMeter {
737 //Update model
738 metersToUpdate := &ofp.Meters{}
739 if lDevice.Meters != nil {
740 metersToUpdate = &ofp.Meters{Items: meters}
741 }
742 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
743 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
744 return err
745 }
746 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
747
748 }
749 if changedFow {
750 //Update model
751 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
752 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
753 return err
754 }
755 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
756 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
757 }
758 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
759 return nil
760}
761
762func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
763 log.Debug("meterModify")
764 if meterMod == nil {
765 return nil
766 }
767 agent.lockLogicalDevice.Lock()
768 defer agent.lockLogicalDevice.Unlock()
769
770 var lDevice *voltha.LogicalDevice
771 var err error
772 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
773 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
774 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
775 }
776
777 var meters []*ofp.OfpMeterEntry
778 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
779 meters = lDevice.Meters.Items
780 }
781 changedMeter := false
782 for index, meter := range meters {
783 if meterMod.MeterId == meter.Config.MeterId {
784 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
785 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
786 meters[index] = newmeterEntry
787 changedMeter = true
788 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
789 break
790 }
791 }
792 if changedMeter {
793 //Update model
794 metersToUpdate := &ofp.Meters{}
795 if lDevice.Meters != nil {
796 metersToUpdate = &ofp.Meters{Items: meters}
797 }
798 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
799 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
800 return err
801 }
802 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
803 return nil
804 }
805
806 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
807 return errors.New(fmt.Sprintf("no-logical-device-present:%d", meterMod.MeterId))
808
809}
810
811func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterId(flows []*ofp.OfpFlowStats, meterId uint32) (bool, []*ofp.OfpFlowStats) {
812 log.Infow("Delete flows matching meter", log.Fields{"meter": meterId})
813 changed := false
814 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
815 for index := len(flows) - 1; index >= 0; index-- {
816 if mId := fu.GetMeterIdFromFlow(flows[index]); mId != 0 && mId == meterId {
817 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
818 flows = append(flows[:index], flows[index+1:]...)
819 changed = true
820 }
821 }
822 return changed, flows
823}
824
825func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
826
827 flowCommand := modCommand.GetCommand()
828 meterId := fu.GetMeterIdFromFlow(flow)
829 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterId})
830 if meterId == 0 {
831 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
832 return false
833 }
834 if meters == nil {
835 log.Debug("No meters present in logical device")
836 return false
837 }
838 changedMeter := false
839 for _, meter := range meters {
840 if meterId == meter.Config.MeterId { // Found meter in Logicaldevice
841 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
842 meter.Stats.FlowCount += 1
843 changedMeter = true
844 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
845 meter.Stats.FlowCount -= 1
846 changedMeter = true
847 }
848 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterId})
849 break
850 }
851 }
852 return changedMeter
853}
854
khenaidoo19d7b632018-10-30 10:49:50 -0400855//flowAdd adds a flow to the flow table of that logical device
856func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400857 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400858 if mod == nil {
859 return nil
860 }
khenaidoo92e62c52018-10-03 14:02:54 -0400861 agent.lockLogicalDevice.Lock()
862 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400863
864 var lDevice *voltha.LogicalDevice
865 var err error
866 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
867 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
868 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
869 }
870
871 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400872 var meters []*ofp.OfpMeterEntry
873 var flow *ofp.OfpFlowStats
874
khenaidoo19d7b632018-10-30 10:49:50 -0400875 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
876 flows = lDevice.Flows.Items
877 }
878
Manikkaraj kb1a10922019-07-29 12:10:34 -0400879 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
880 meters = lDevice.Meters.Items
881 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400882 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400883 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400884 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400885 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
886 if checkOverlap {
887 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
888 // TODO: should this error be notified other than being logged?
889 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
890 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400891 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400892 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400893 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400894 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400895 changed = true
896 }
897 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400898 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400899 idx := fu.FindFlows(flows, flow)
900 if idx >= 0 {
901 oldFlow := flows[idx]
902 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
903 flow.ByteCount = oldFlow.ByteCount
904 flow.PacketCount = oldFlow.PacketCount
905 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400906 if !reflect.DeepEqual(oldFlow, flow) {
907 flows[idx] = flow
908 updatedFlows = append(updatedFlows, flow)
909 changed = true
910 updated = true
911 }
912 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400913 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400914 updatedFlows = append(updatedFlows, flow)
915 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400916 }
khenaidoo19d7b632018-10-30 10:49:50 -0400917 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400918 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
919
khenaidoo19d7b632018-10-30 10:49:50 -0400920 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400921 var flowMetadata voltha.FlowMetadata
922 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
923 log.Error("Meter-referred-in-flows-not-present")
924 return err
925 }
khenaidoo0458db62019-06-20 08:50:36 -0400926 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
927 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
928
Manikkaraj kb1a10922019-07-29 12:10:34 -0400929 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400930 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400931 return err
932 }
933
khenaidoo19d7b632018-10-30 10:49:50 -0400934 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400935 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400936 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400937 return err
938 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400939 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400940 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
941 metersToUpdate := &ofp.Meters{}
942 if lDevice.Meters != nil {
943 metersToUpdate = &ofp.Meters{Items: meters}
944 }
945 if changedMeterStats {
946 //Update model
947 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
948 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
949 return err
950 }
951 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
952
953 }
954 }
955
khenaidoo19d7b632018-10-30 10:49:50 -0400956 }
khenaidoo19d7b632018-10-30 10:49:50 -0400957 return nil
958}
959
Manikkaraj kb1a10922019-07-29 12:10:34 -0400960func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
961 m := make(map[uint32]bool)
962 for _, flow := range flows {
963 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && m[flowMeterID] == false {
964 foundMeter := false
965 // Meter is present in the flow , Get from logical device
966 for _, meter := range meters {
967 if flowMeterID == meter.Config.MeterId {
968 metadata.Meters = append(metadata.Meters, meter.Config)
969 log.Debugw("Found meter in logical device",
970 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
971 m[flowMeterID] = true
972 foundMeter = true
973 break
974 }
975 }
976 if !foundMeter {
977 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
978 log.Fields{"meterID": flowMeterID, "Avaliable-meters": meters, "flow": *flow})
979 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
980 }
981 }
982 }
983 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
984 return nil
985
986}
987
khenaidoo19d7b632018-10-30 10:49:50 -0400988//flowDelete deletes a flow from the flow table of that logical device
989func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
990 log.Debug("flowDelete")
991 if mod == nil {
992 return nil
993 }
994 agent.lockLogicalDevice.Lock()
995 defer agent.lockLogicalDevice.Unlock()
996
997 var lDevice *voltha.LogicalDevice
998 var err error
999 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1000 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1001 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1002 }
khenaidoo19d7b632018-10-30 10:49:50 -04001003
Manikkaraj kb1a10922019-07-29 12:10:34 -04001004 var meters []*ofp.OfpMeterEntry
1005 var flows []*ofp.OfpFlowStats
1006
1007 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1008 flows = lDevice.Flows.Items
1009 }
1010
1011 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1012 meters = lDevice.Meters.Items
1013 }
khenaidoo19d7b632018-10-30 10:49:50 -04001014 //build a list of what to keep vs what to delete
1015 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001016 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001017 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -04001018 // Check whether the flow and the flowmod matches
1019 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
1020 toDelete = append(toDelete, f)
1021 continue
1022 }
1023 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -04001024 if !fu.FlowMatchesMod(f, mod) {
1025 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -04001026 } else {
1027 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -04001028 }
1029 }
1030
khenaidoo0458db62019-06-20 08:50:36 -04001031 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "toKeep": len(toKeep), "toDelete": toDelete})
1032
khenaidoo19d7b632018-10-30 10:49:50 -04001033 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -04001034 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001035 var flowMetadata voltha.FlowMetadata
1036 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
1037 log.Error("Meter-referred-in-flows-not-present")
1038 return errors.New("Meter-referred-in-flows-not-present")
1039 }
khenaidoo0458db62019-06-20 08:50:36 -04001040 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
1041 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1042
Manikkaraj kb1a10922019-07-29 12:10:34 -04001043 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001044 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1045 return err
1046 }
1047
khenaidoo43c82122018-11-22 18:38:28 -05001048 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
1049 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001050 return err
1051 }
1052 }
1053
1054 //TODO: send announcement on delete
1055 return nil
1056}
1057
Manikkaraj kb1a10922019-07-29 12:10:34 -04001058func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
1059 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001060
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001061 responses := make([]coreutils.Response, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001062 for deviceId, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001063 response := coreutils.NewResponse()
1064 responses = append(responses, response)
1065 go func(deviceId string, value *fu.FlowsAndGroups) {
1066 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001067 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001068 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001069 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001070 response.Done()
1071 }(deviceId, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001072 }
khenaidoo0458db62019-06-20 08:50:36 -04001073 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001074 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001075 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001076 }
khenaidoo0458db62019-06-20 08:50:36 -04001077 return nil
1078}
khenaidoo19d7b632018-10-30 10:49:50 -04001079
Manikkaraj kb1a10922019-07-29 12:10:34 -04001080func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -04001081 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId})
1082
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001083 responses := make([]coreutils.Response, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001084 for deviceId, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001085 response := coreutils.NewResponse()
1086 responses = append(responses, response)
1087 go func(deviceId string, value *fu.FlowsAndGroups) {
1088 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001089 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001090 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001091 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001092 response.Done()
1093 }(deviceId, value)
khenaidoo0458db62019-06-20 08:50:36 -04001094 }
1095 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001096 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001097 return status.Errorf(codes.Aborted, "errors-%s", res)
1098 }
1099 return nil
1100}
1101
Manikkaraj kb1a10922019-07-29 12:10:34 -04001102func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -04001103 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId})
1104
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001105 responses := make([]coreutils.Response, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001106 for deviceId, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001107 response := coreutils.NewResponse()
1108 responses = append(responses, response)
1109 go func(deviceId string, value *fu.FlowsAndGroups) {
1110 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001111 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001112 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001113 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001114 response.Done()
1115 }(deviceId, value)
khenaidoo0458db62019-06-20 08:50:36 -04001116 }
1117 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001118 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001119 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001120 }
1121 return nil
1122}
1123
1124//flowDeleteStrict deletes a flow from the flow table of that logical device
1125func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1126 log.Debug("flowDeleteStrict")
1127 if mod == nil {
1128 return nil
1129 }
1130 agent.lockLogicalDevice.Lock()
1131 defer agent.lockLogicalDevice.Unlock()
1132
1133 var lDevice *voltha.LogicalDevice
1134 var err error
1135 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1136 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1137 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1138 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001139 var meters []*ofp.OfpMeterEntry
1140 var flows []*ofp.OfpFlowStats
1141 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1142 meters = lDevice.Meters.Items
1143 }
1144 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1145 flows = lDevice.Flows.Items
1146 }
1147
1148 changedFlow := false
1149 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001150 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001151 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001152 idx := fu.FindFlows(flows, flow)
1153 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001154 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001155 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001156 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001157 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001158 } else {
1159 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
1160 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001161 if changedMeter {
1162 //Update model
1163 metersToUpdate := &ofp.Meters{}
1164 if lDevice.Meters != nil {
1165 metersToUpdate = &ofp.Meters{Items: meters}
1166 }
1167 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
1168 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1169 return err
1170 }
khenaidoo19d7b632018-10-30 10:49:50 -04001171
Manikkaraj kb1a10922019-07-29 12:10:34 -04001172 }
1173 if changedFlow {
1174 var flowMetadata voltha.FlowMetadata
1175 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
1176 log.Error("Meter-referred-in-flows-not-present")
1177 return err
1178 }
1179 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001180 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1181
Manikkaraj kb1a10922019-07-29 12:10:34 -04001182 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001183 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1184 return err
1185 }
1186
khenaidoo43c82122018-11-22 18:38:28 -05001187 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001188 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001189 return err
1190 }
1191 }
khenaidoo19d7b632018-10-30 10:49:50 -04001192 return nil
1193}
1194
1195//flowModify modifies a flow from the flow table of that logical device
1196func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1197 return errors.New("flowModify not implemented")
1198}
1199
1200//flowModifyStrict deletes a flow from the flow table of that logical device
1201func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1202 return errors.New("flowModifyStrict not implemented")
1203}
1204
1205func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1206 log.Debug("groupAdd")
1207 if groupMod == nil {
1208 return nil
1209 }
1210 agent.lockLogicalDevice.Lock()
1211 defer agent.lockLogicalDevice.Unlock()
1212
1213 var lDevice *voltha.LogicalDevice
1214 var err error
1215 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1216 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1217 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1218 }
1219 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001220 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001221 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001222
1223 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *lDevice.Flows, ofp.FlowGroups{Items: groups})
1224 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001225 if err := agent.addDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001226 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1227 return err
1228 }
1229
khenaidoo43c82122018-11-22 18:38:28 -05001230 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
1231 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001232 return err
1233 }
1234 } else {
1235 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
1236 }
khenaidoo19d7b632018-10-30 10:49:50 -04001237 return nil
1238}
1239
1240func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1241 log.Debug("groupDelete")
1242 if groupMod == nil {
1243 return nil
1244 }
1245 agent.lockLogicalDevice.Lock()
1246 defer agent.lockLogicalDevice.Unlock()
1247
1248 var lDevice *voltha.LogicalDevice
1249 var err error
1250 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1251 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1252 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1253 }
1254 groups := lDevice.FlowGroups.Items
1255 flows := lDevice.Flows.Items
1256 groupsChanged := false
1257 flowsChanged := false
1258 groupId := groupMod.GroupId
1259 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
1260 //TODO we must delete all flows that point to this group and
1261 //signal controller as requested by flow's flag
1262 groups = []*ofp.OfpGroupEntry{}
1263 groupsChanged = true
1264 } else {
1265 if idx := fu.FindGroup(groups, groupId); idx == -1 {
1266 return nil // Valid case
1267 } else {
1268 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
1269 groups = append(groups[:idx], groups[idx+1:]...)
1270 groupsChanged = true
1271 }
1272 }
khenaidoo0458db62019-06-20 08:50:36 -04001273 if flowsChanged || groupsChanged {
1274 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1275 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1276
Manikkaraj kb1a10922019-07-29 12:10:34 -04001277 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001278 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1279 return err
1280 }
1281 }
1282
khenaidoo43c82122018-11-22 18:38:28 -05001283 if groupsChanged {
1284 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
1285 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001286 return err
1287 }
1288 }
khenaidoo43c82122018-11-22 18:38:28 -05001289 if flowsChanged {
1290 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
1291 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1292 return err
1293 }
1294 }
khenaidoo19d7b632018-10-30 10:49:50 -04001295 return nil
1296}
1297
1298func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1299 log.Debug("groupModify")
1300 if groupMod == nil {
1301 return nil
1302 }
1303 agent.lockLogicalDevice.Lock()
1304 defer agent.lockLogicalDevice.Unlock()
1305
1306 var lDevice *voltha.LogicalDevice
1307 var err error
1308 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1309 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1310 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1311 }
1312 groups := lDevice.FlowGroups.Items
1313 groupsChanged := false
1314 groupId := groupMod.GroupId
1315 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -05001316 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -04001317 } else {
1318 //replace existing group entry with new group definition
khenaidoo68c930b2019-05-13 11:46:51 -04001319 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -04001320 groups[idx] = groupEntry
1321 groupsChanged = true
1322 }
1323 if groupsChanged {
khenaidoo0458db62019-06-20 08:50:36 -04001324 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: lDevice.Flows.Items}, ofp.FlowGroups{Items: groups})
1325 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1326
Manikkaraj kb1a10922019-07-29 12:10:34 -04001327 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001328 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1329 return err
1330 }
1331
khenaidoo43c82122018-11-22 18:38:28 -05001332 //lDevice.FlowGroups.Items = groups
1333 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001334 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1335 return err
1336 }
1337 }
1338 return nil
1339}
1340
1341// deleteLogicalPort removes the logical port
1342func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1343 agent.lockLogicalDevice.Lock()
1344 defer agent.lockLogicalDevice.Unlock()
1345
khenaidoo92e62c52018-10-03 14:02:54 -04001346 // Get the most up to date logical device
1347 var logicaldevice *voltha.LogicalDevice
1348 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001349 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -04001350 return nil
1351 }
khenaidoo92e62c52018-10-03 14:02:54 -04001352 index := -1
1353 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001354 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001355 index = i
1356 break
1357 }
1358 }
1359 if index >= 0 {
1360 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
1361 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
1362 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
1363 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo0a822f92019-05-08 15:15:57 -04001364 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
1365 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1366 return err
1367 }
1368 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001369 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001370 }
1371 return nil
khenaidoob9203542018-09-17 22:56:37 -04001372}
1373
khenaidoo0a822f92019-05-08 15:15:57 -04001374// deleteLogicalPorts removes the logical ports associated with that deviceId
1375func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceId string) error {
1376 agent.lockLogicalDevice.Lock()
1377 defer agent.lockLogicalDevice.Unlock()
1378
1379 // Get the most up to date logical device
1380 var logicaldevice *voltha.LogicalDevice
1381 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
1382 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1383 return nil
1384 }
1385 updatedLPorts := []*voltha.LogicalPort{}
1386 for _, logicalPort := range logicaldevice.Ports {
1387 if logicalPort.DeviceId != deviceId {
1388 updatedLPorts = append(updatedLPorts, logicalPort)
1389 }
1390 }
1391 logicaldevice.Ports = updatedLPorts
1392 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
1393 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
1394 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1395 return err
1396 }
1397 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001398 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001399
1400 return nil
1401}
1402
khenaidoo19d7b632018-10-30 10:49:50 -04001403// enableLogicalPort enables the logical port
Girish Kumar0d4597e2019-10-24 18:13:14 +00001404func (agent *LogicalDeviceAgent) enableLogicalPort(lPortId string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001405 agent.lockLogicalDevice.Lock()
1406 defer agent.lockLogicalDevice.Unlock()
1407
1408 // Get the most up to date logical device
1409 var logicaldevice *voltha.LogicalDevice
1410 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001411 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPortId})
khenaidoo19d7b632018-10-30 10:49:50 -04001412 return nil
1413 }
1414 index := -1
1415 for i, logicalPort := range logicaldevice.Ports {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001416 if logicalPort.Id == lPortId {
khenaidoo19d7b632018-10-30 10:49:50 -04001417 index = i
1418 break
1419 }
1420 }
1421 if index >= 0 {
1422 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1423 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
Girish Kumar0d4597e2019-10-24 18:13:14 +00001424 } else {
1425 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortId, agent.logicalDeviceId)
khenaidoo19d7b632018-10-30 10:49:50 -04001426 }
khenaidoo19d7b632018-10-30 10:49:50 -04001427}
1428
1429// disableLogicalPort disabled the logical port
Girish Kumar0d4597e2019-10-24 18:13:14 +00001430func (agent *LogicalDeviceAgent) disableLogicalPort(lPortId string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001431 agent.lockLogicalDevice.Lock()
1432 defer agent.lockLogicalDevice.Unlock()
1433
1434 // Get the most up to date logical device
1435 var logicaldevice *voltha.LogicalDevice
1436 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001437 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPortId})
khenaidoo19d7b632018-10-30 10:49:50 -04001438 return nil
1439 }
1440 index := -1
1441 for i, logicalPort := range logicaldevice.Ports {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001442 if logicalPort.Id == lPortId {
khenaidoo19d7b632018-10-30 10:49:50 -04001443 index = i
1444 break
1445 }
1446 }
1447 if index >= 0 {
1448 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1449 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
Girish Kumar0d4597e2019-10-24 18:13:14 +00001450 } else {
1451 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortId, agent.logicalDeviceId)
khenaidoo19d7b632018-10-30 10:49:50 -04001452 }
khenaidoo19d7b632018-10-30 10:49:50 -04001453}
1454
khenaidoo89b0e942018-10-21 21:11:33 -04001455func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001456 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001457 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001458 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001459 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1460 return route
1461 }
1462 }
1463 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
1464 return nil
1465}
1466
khenaidoo19d7b632018-10-30 10:49:50 -04001467func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001468 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001469 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001470
khenaidoo19d7b632018-10-30 10:49:50 -04001471 // Note: A port value of 0 is equivalent to a nil port
1472
khenaidoo89b0e942018-10-21 21:11:33 -04001473 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001474 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001475 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1476 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001477 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001478 if len(agent.deviceGraph.Routes) == 0 {
1479 // 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 -04001480 // route with same IngressHop and EgressHop
1481 hop := graph.RouteHop{DeviceID: agent.rootDeviceId, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001482 routes = append(routes, hop)
1483 routes = append(routes, hop)
1484 return routes
1485 }
khenaidoo89b0e942018-10-21 21:11:33 -04001486 //Return a 'half' route to make the flow decomposer logic happy
1487 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001488 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001489 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1490 routes = append(routes, route[1])
1491 return routes
1492 }
1493 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001494 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001495 return nil
1496 }
1497 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001498 var err error
1499 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1500 log.Warnw("no-nni-port", log.Fields{"error": err})
1501 return nil
1502 }
khenaidoo89b0e942018-10-21 21:11:33 -04001503 }
1504 //If ingress port is not specified (nil), it may be a wildcarded
1505 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1506 //in which case we need to create a half-route where only the egress
1507 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001508 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001509 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1510 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001511 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001512 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1513 routes = append(routes, route[1])
1514 return routes
1515 }
1516 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001517 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001518 return nil
1519 }
1520 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001521 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001522 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001523 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001524 routes = append(routes, route[0])
1525 routes = append(routes, graph.RouteHop{})
1526 return routes
1527 }
1528 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001529 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001530 return nil
1531 }
khenaidoo89b0e942018-10-21 21:11:33 -04001532 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001533 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001534}
1535
khenaidoo3d3b8c22019-05-22 18:10:39 -04001536//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1537//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1538//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001539func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1540 lPorts := make([]uint32, 0)
1541 var exclPort uint32
1542 if len(excludePort) == 1 {
1543 exclPort = excludePort[0]
1544 }
khenaidoo3d3b8c22019-05-22 18:10:39 -04001545 if lDevice, _ := agent.getLogicalDeviceWithoutLock(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -04001546 for _, port := range lDevice.Ports {
1547 if port.OfpPort.PortNo != exclPort {
1548 lPorts = append(lPorts, port.OfpPort.PortNo)
1549 }
1550 }
1551 }
1552 return lPorts
1553}
khenaidoo19d7b632018-10-30 10:49:50 -04001554
1555func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1556 return agent.deviceGraph
1557}
1558
khenaidoo3306c992019-05-24 16:57:35 -04001559//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001560func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
1561 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001562 agent.lockLogicalDevice.Lock()
1563 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001564 if agent.deviceGraph == nil {
khenaidoo910204f2019-04-08 17:56:40 -04001565 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001566 }
1567 // Get all the logical ports on that logical device
1568 if lDevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
manikkaraj k259a6f72019-05-06 09:55:44 -04001569 log.Errorw("unknown-logical-device", log.Fields{"error": err, "logicalDeviceId": agent.logicalDeviceId})
khenaidoo2c6a0992019-04-29 13:46:56 -04001570 return err
1571 } else {
1572 //TODO: Find a better way to refresh only missing routes
1573 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
1574 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001575 agent.deviceGraph.Print()
1576 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001577}
1578
khenaidoo2c6a0992019-04-29 13:46:56 -04001579//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001580func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001581 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1582 agent.lockLogicalDevice.Lock()
1583 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001584 if agent.deviceGraph == nil {
1585 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
1586 }
1587 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001588 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001589}
khenaidoofdbad6e2018-11-06 22:26:38 -05001590
khenaidoo3d3b8c22019-05-22 18:10:39 -04001591//generateDeviceGraph regenerates the device graph
1592func (agent *LogicalDeviceAgent) generateDeviceGraph() {
khenaidoo4c9e5592019-09-09 16:20:41 -04001593 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo0a822f92019-05-08 15:15:57 -04001594 agent.lockLogicalDevice.Lock()
1595 defer agent.lockLogicalDevice.Unlock()
1596 // Get the latest logical device
1597 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
1598 log.Errorw("logical-device-not-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1599 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -04001600 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceId, "lPorts": len(ld.Ports)})
khenaidoo3d3b8c22019-05-22 18:10:39 -04001601 if agent.deviceGraph == nil {
1602 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
1603 }
khenaidoo0a822f92019-05-08 15:15:57 -04001604 agent.deviceGraph.ComputeRoutes(ld.Ports)
khenaidoo3d3b8c22019-05-22 18:10:39 -04001605 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001606 }
1607}
1608
khenaidoofc1314d2019-03-14 09:34:21 -04001609// portAdded is a callback invoked when a port is added to the logical device.
1610// TODO: To use when POST_ADD is fixed.
1611func (agent *LogicalDeviceAgent) portAdded(args ...interface{}) interface{} {
1612 log.Debugw("portAdded-callback", log.Fields{"argsLen": len(args)})
1613
1614 var port *voltha.LogicalPort
1615
1616 // Sanity check
1617 if args[0] != nil {
1618 log.Warnw("previous-data-not-nil", log.Fields{"args0": args[0]})
1619 }
1620 var ok bool
1621 if port, ok = args[1].(*voltha.LogicalPort); !ok {
1622 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1623 return nil
1624 }
1625
1626 // Set the proxy and callback for that port
1627 agent.portProxiesLock.Lock()
Stephane Barbarie40fd3b22019-04-23 21:50:47 -04001628 agent.portProxies[port.Id] = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001629 context.Background(),
khenaidoofc1314d2019-03-14 09:34:21 -04001630 fmt.Sprintf("/logical_devices/%s/ports/%s", agent.logicalDeviceId, port.Id),
1631 false)
1632 agent.portProxies[port.Id].RegisterCallback(model.POST_UPDATE, agent.portUpdated)
1633 agent.portProxiesLock.Unlock()
1634
1635 // Send the port change event to the OF controller
1636 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001637 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: port.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001638
1639 return nil
1640}
1641
1642// portRemoved is a callback invoked when a port is removed from the logical device.
1643// TODO: To use when POST_ADD is fixed.
1644func (agent *LogicalDeviceAgent) portRemoved(args ...interface{}) interface{} {
1645 log.Debugw("portRemoved-callback", log.Fields{"argsLen": len(args)})
1646
1647 var port *voltha.LogicalPort
1648
1649 // Sanity check
1650 if args[1] != nil {
1651 log.Warnw("data-not-nil", log.Fields{"args1": args[1]})
1652 }
1653 var ok bool
1654 if port, ok = args[0].(*voltha.LogicalPort); !ok {
1655 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1656 return nil
1657 }
1658
1659 // Remove the proxy and callback for that port
1660 agent.portProxiesLock.Lock()
1661 agent.portProxies[port.Id].UnregisterCallback(model.POST_UPDATE, agent.portUpdated)
1662 delete(agent.portProxies, port.Id)
1663 agent.portProxiesLock.Unlock()
1664
1665 // Send the port change event to the OF controller
1666 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001667 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: port.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001668
1669 return nil
1670}
1671
1672// 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 -04001673func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001674 newPorts = make([]*voltha.LogicalPort, 0)
1675 changedPorts = make([]*voltha.LogicalPort, 0)
1676 deletedPorts = make([]*voltha.LogicalPort, 0)
1677 for _, o := range oldList {
1678 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001679 for _, n := range newList {
1680 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001681 found = true
1682 break
1683 }
1684 }
1685 if !found {
1686 deletedPorts = append(deletedPorts, o)
1687 }
khenaidoofc1314d2019-03-14 09:34:21 -04001688 }
1689 for _, n := range newList {
1690 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001691 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001692 for _, o := range oldList {
1693 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001694 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001695 found = true
1696 break
1697 }
1698 }
1699 if !found {
1700 newPorts = append(newPorts, n)
1701 }
khenaidoo2bc48282019-07-16 18:13:46 -04001702 if changed {
1703 changedPorts = append(changedPorts, n)
1704 }
khenaidoofc1314d2019-03-14 09:34:21 -04001705 }
1706 return
1707}
1708
1709// portUpdated is invoked when a port is updated on the logical device. Until
1710// the POST_ADD notification is fixed, we will use the logical device to
1711// update that data.
1712func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1713 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1714
1715 var oldLD *voltha.LogicalDevice
1716 var newlD *voltha.LogicalDevice
1717
1718 var ok bool
1719 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1720 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1721 return nil
1722 }
1723 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1724 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1725 return nil
1726 }
1727
1728 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1729 log.Debug("ports-have-not-changed")
1730 return nil
1731 }
1732
1733 // Get the difference between the two list
1734 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1735
1736 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001737 for _, newP := range newPorts {
khenaidoofc1314d2019-03-14 09:34:21 -04001738 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo2c6a0992019-04-29 13:46:56 -04001739 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001740 }
1741 for _, change := range changedPorts {
1742 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001743 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001744 }
1745 for _, del := range deletedPorts {
1746 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001747 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001748 }
1749
1750 return nil
1751}
1752
khenaidoo8f474192019-04-03 17:20:44 -04001753// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1754// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1755// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1756// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001757func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001758 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001759 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1760 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1761 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001762 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001763 agent.lockLogicalDevice.RLock()
1764 if agent.portExist(device, port) {
1765 log.Debugw("port-already-exist", log.Fields{"port": port})
1766 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001767 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001768 }
1769 agent.lockLogicalDevice.RUnlock()
1770
khenaidoofc1314d2019-03-14 09:34:21 -04001771 var portCap *ic.PortCapability
1772 var err error
1773 // First get the port capability
1774 if portCap, err = agent.deviceMgr.getPortCapability(nil, device.Id, port.PortNo); err != nil {
1775 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001776 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001777 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001778
1779 agent.lockLogicalDevice.Lock()
1780 defer agent.lockLogicalDevice.Unlock()
1781 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1782 if agent.portExist(device, port) {
1783 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001784 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001785 }
1786
khenaidoofc1314d2019-03-14 09:34:21 -04001787 portCap.Port.RootPort = true
1788 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1789 lp.DeviceId = device.Id
1790 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1791 lp.OfpPort.PortNo = port.PortNo
1792 lp.OfpPort.Name = lp.Id
1793 lp.DevicePortNo = port.PortNo
1794
khenaidoofc1314d2019-03-14 09:34:21 -04001795 var ld *voltha.LogicalDevice
1796 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1797 log.Errorw("error-retrieving-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001798 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001799 }
1800 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1801 if cloned.Ports == nil {
1802 cloned.Ports = make([]*voltha.LogicalPort, 0)
1803 }
1804 cloned.Ports = append(cloned.Ports, lp)
1805
1806 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1807 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001808 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001809 }
khenaidoo910204f2019-04-08 17:56:40 -04001810
1811 // Update the device graph with this new logical port
1812 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1813 go agent.updateDeviceGraph(clonedLP)
1814
khenaidoo8f474192019-04-03 17:20:44 -04001815 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001816}
1817
khenaidoo910204f2019-04-08 17:56:40 -04001818func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo54544ae2019-03-18 13:22:39 -04001819 if ldevice, _ := agent.getLogicalDeviceWithoutLock(); ldevice != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001820 for _, lPort := range ldevice.Ports {
khenaidoo54544ae2019-03-18 13:22:39 -04001821 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
khenaidoofc1314d2019-03-14 09:34:21 -04001822 return true
1823 }
1824 }
1825 }
1826 return false
1827}
1828
khenaidoo8f474192019-04-03 17:20:44 -04001829// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1830// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1831// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1832// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001833func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001834 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001835 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1836 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1837 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001838 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001839 agent.lockLogicalDevice.RLock()
1840 if agent.portExist(childDevice, port) {
1841 log.Debugw("port-already-exist", log.Fields{"port": port})
1842 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001843 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001844 }
1845 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001846 var portCap *ic.PortCapability
1847 var err error
1848 // First get the port capability
1849 if portCap, err = agent.deviceMgr.getPortCapability(nil, childDevice.Id, port.PortNo); err != nil {
1850 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001851 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001852 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001853 agent.lockLogicalDevice.Lock()
1854 defer agent.lockLogicalDevice.Unlock()
1855 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1856 if agent.portExist(childDevice, port) {
1857 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001858 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001859 }
khenaidoofc1314d2019-03-14 09:34:21 -04001860 // Get stored logical device
1861 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
khenaidoo8f474192019-04-03 17:20:44 -04001862 return false, status.Error(codes.NotFound, agent.logicalDeviceId)
khenaidoofc1314d2019-03-14 09:34:21 -04001863 } else {
1864 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1865 portCap.Port.RootPort = false
Matt Jeanneret3815e322019-03-12 19:15:49 -04001866 portCap.Port.Id = port.Label
1867 portCap.Port.OfpPort.PortNo = port.PortNo
khenaidoofc1314d2019-03-14 09:34:21 -04001868 portCap.Port.DeviceId = childDevice.Id
1869 portCap.Port.DevicePortNo = port.PortNo
1870 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1871 if cloned.Ports == nil {
1872 cloned.Ports = make([]*voltha.LogicalPort, 0)
1873 }
1874 cloned.Ports = append(cloned.Ports, portCap.Port)
khenaidoo910204f2019-04-08 17:56:40 -04001875 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1876 return false, err
1877 }
khenaidoo910204f2019-04-08 17:56:40 -04001878 // Update the device graph with this new logical port
1879 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1880 go agent.updateDeviceGraph(clonedLP)
1881 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001882 }
1883}
1884
khenaidoo43c82122018-11-22 18:38:28 -05001885func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001886 log.Debugw("packet-out", log.Fields{
1887 "packet": hex.EncodeToString(packet.Data),
1888 "inPort": packet.GetInPort(),
1889 })
khenaidoo68c930b2019-05-13 11:46:51 -04001890 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001891 //frame := packet.GetData()
1892 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001893 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
khenaidoo910204f2019-04-08 17:56:40 -04001894 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceId})
khenaidooca301322019-01-09 23:06:32 -05001895 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001896}
1897
khenaidoo297cd252019-02-07 22:10:23 -05001898func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionId string, packet []byte) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001899 log.Debugw("packet-in", log.Fields{
1900 "port": port,
1901 "packet": hex.EncodeToString(packet),
1902 "transactionId": transactionId,
1903 })
khenaidoo68c930b2019-05-13 11:46:51 -04001904 packetIn := fu.MkPacketIn(port, packet)
khenaidoo297cd252019-02-07 22:10:23 -05001905 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, transactionId, packetIn)
Matteo Scandolo360605d2019-11-05 18:29:17 -08001906 log.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001907}
khenaidoo2c6a0992019-04-29 13:46:56 -04001908
1909func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1910 agent.lockLogicalPortsNo.Lock()
1911 defer agent.lockLogicalPortsNo.Unlock()
1912 if exist := agent.logicalPortsNo[portNo]; !exist {
1913 agent.logicalPortsNo[portNo] = nniPort
1914 }
1915}
1916
khenaidoo3d3b8c22019-05-22 18:10:39 -04001917func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1918 agent.lockLogicalPortsNo.Lock()
1919 defer agent.lockLogicalPortsNo.Unlock()
1920 for _, lp := range lps {
1921 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1922 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1923 }
1924 }
1925}
1926
khenaidoo2c6a0992019-04-29 13:46:56 -04001927func (agent *LogicalDeviceAgent) deleteLogicalPortFromMap(portNo uint32) {
1928 agent.lockLogicalPortsNo.Lock()
1929 defer agent.lockLogicalPortsNo.Unlock()
1930 if exist := agent.logicalPortsNo[portNo]; exist {
1931 delete(agent.logicalPortsNo, portNo)
1932 }
1933}
1934
1935func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1936 agent.lockLogicalPortsNo.RLock()
1937 defer agent.lockLogicalPortsNo.RUnlock()
1938 if exist := agent.logicalPortsNo[portNo]; exist {
1939 return agent.logicalPortsNo[portNo]
1940 }
1941 return false
1942}
1943
1944func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1945 agent.lockLogicalPortsNo.RLock()
1946 defer agent.lockLogicalPortsNo.RUnlock()
1947 for portNo, nni := range agent.logicalPortsNo {
1948 if nni {
1949 return portNo, nil
1950 }
1951 }
1952 return 0, status.Error(codes.NotFound, "No NNI port found")
1953}