blob: 1bdfc1c8c261afe2871dc73ad5a50f559dda5902 [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"
khenaidoo19d7b632018-10-30 10:49:50 -040020 "errors"
21 "fmt"
khenaidoob9203542018-09-17 22:56:37 -040022 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050023 "github.com/opencord/voltha-go/db/model"
khenaidoo89b0e942018-10-21 21:11:33 -040024 fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
25 "github.com/opencord/voltha-go/rw_core/graph"
Scott Bakerb671a862019-10-24 10:53:40 -070026 coreutils "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070027 fu "github.com/opencord/voltha-lib-go/v2/pkg/flows"
28 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker555307d2019-11-04 08:58:01 -080029 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
30 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
31 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040032 "google.golang.org/grpc/codes"
33 "google.golang.org/grpc/status"
khenaidoo19d7b632018-10-30 10:49:50 -040034 "reflect"
khenaidoo92e62c52018-10-03 14:02:54 -040035 "sync"
Stephane Barbarieef6650d2019-07-18 12:15:09 -040036 "time"
khenaidoob9203542018-09-17 22:56:37 -040037)
38
39type LogicalDeviceAgent struct {
khenaidoo3306c992019-05-24 16:57:35 -040040 logicalDeviceId string
41 rootDeviceId string
42 deviceMgr *DeviceManager
43 ldeviceMgr *LogicalDeviceManager
44 clusterDataProxy *model.Proxy
45 exitChannel chan int
46 deviceGraph *graph.DeviceGraph
47 flowProxy *model.Proxy
48 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040049 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040050 ldProxy *model.Proxy
51 portProxies map[string]*model.Proxy
52 portProxiesLock sync.RWMutex
53 lockLogicalDevice sync.RWMutex
khenaidoo4c9e5592019-09-09 16:20:41 -040054 lockDeviceGraph sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040055 logicalPortsNo map[uint32]bool //value is true for NNI port
56 lockLogicalPortsNo sync.RWMutex
57 flowDecomposer *fd.FlowDecomposer
58 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040059}
60
Stephane Barbarie1ab43272018-12-08 21:42:13 -050061func newLogicalDeviceAgent(id string, deviceId string, ldeviceMgr *LogicalDeviceManager,
62 deviceMgr *DeviceManager,
khenaidoo2c6a0992019-04-29 13:46:56 -040063 cdProxy *model.Proxy, timeout int64) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040064 var agent LogicalDeviceAgent
65 agent.exitChannel = make(chan int, 1)
66 agent.logicalDeviceId = id
Stephane Barbarie1ab43272018-12-08 21:42:13 -050067 agent.rootDeviceId = deviceId
khenaidoob9203542018-09-17 22:56:37 -040068 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040069 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040070 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040071 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040072 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoofc1314d2019-03-14 09:34:21 -040073 agent.portProxies = make(map[string]*model.Proxy)
74 agent.portProxiesLock = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040075 agent.lockLogicalPortsNo = sync.RWMutex{}
khenaidoo4c9e5592019-09-09 16:20:41 -040076 agent.lockDeviceGraph = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040077 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040078 agent.defaultTimeout = timeout
khenaidoob9203542018-09-17 22:56:37 -040079 return &agent
80}
81
khenaidoo4d4802d2018-10-04 21:59:49 -040082// start creates the logical device and add it to the data model
khenaidoo297cd252019-02-07 22:10:23 -050083func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
84 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId, "loadFromdB": loadFromdB})
85 var ld *voltha.LogicalDevice
86 if !loadFromdB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040087 //Build the logical device based on information retrieved from the device adapter
88 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -050089 var err error
khenaidoo7e3d8f12019-08-02 16:06:30 -040090 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
91 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
92 return err
93 }
khenaidoo297cd252019-02-07 22:10:23 -050094 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
95
96 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
97 var datapathID uint64
98 if datapathID, err = CreateDataPathId(agent.logicalDeviceId); err != nil {
99 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
100 return err
101 }
102 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400103 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
104 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
105 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500106 ld.Flows = &ofp.Flows{Items: nil}
107 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
108
khenaidoo297cd252019-02-07 22:10:23 -0500109 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500110 // Save the logical device
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400111 if added := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, ""); added == nil {
khenaidoo297cd252019-02-07 22:10:23 -0500112 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
113 } else {
114 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
115 }
116 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400117
khenaidoo3d3b8c22019-05-22 18:10:39 -0400118 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
119 go agent.setupLogicalPorts(ctx)
120
khenaidoo297cd252019-02-07 22:10:23 -0500121 } else {
122 // load from dB - the logical may not exist at this time. On error, just return and the calling function
123 // will destroy this agent.
124 var err error
125 if ld, err = agent.GetLogicalDevice(); err != nil {
126 log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
127 return err
128 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400129
khenaidoo8c3303d2019-02-13 14:59:39 -0500130 // Update the root device Id
131 agent.rootDeviceId = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400132
133 // Setup the local list of logical ports
134 agent.addLogicalPortsToMap(ld.Ports)
135
khenaidoob9203542018-09-17 22:56:37 -0400136 }
khenaidoo92e62c52018-10-03 14:02:54 -0400137 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400138 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400139
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400140 agent.flowProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400141 ctx,
khenaidoo19d7b632018-10-30 10:49:50 -0400142 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceId),
143 false)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400144 agent.meterProxy = agent.clusterDataProxy.CreateProxy(
145 ctx,
146 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceId),
147 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400148 agent.groupProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400149 ctx,
khenaidoo19d7b632018-10-30 10:49:50 -0400150 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceId),
151 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400152 agent.ldProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400153 ctx,
khenaidoofc1314d2019-03-14 09:34:21 -0400154 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceId),
155 false)
khenaidoo19d7b632018-10-30 10:49:50 -0400156
khenaidoofc1314d2019-03-14 09:34:21 -0400157 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400158 if agent.ldProxy != nil {
159 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
160 } else {
161 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
162 return status.Error(codes.Internal, "logical-device-proxy-null")
163 }
khenaidoobcf205b2019-01-25 22:21:14 -0500164
khenaidoo4c9e5592019-09-09 16:20:41 -0400165 // Setup the device graph - run it in its own routine
166 if loadFromdB {
167 go agent.generateDeviceGraph()
168 }
khenaidoob9203542018-09-17 22:56:37 -0400169 return nil
170}
171
khenaidoo4d4802d2018-10-04 21:59:49 -0400172// stop stops the logical devuce agent. This removes the logical device from the data model.
173func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
174 log.Info("stopping-logical_device-agent")
175 agent.lockLogicalDevice.Lock()
176 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500177
khenaidoo4d4802d2018-10-04 21:59:49 -0400178 //Remove the logical device from the model
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400179 if removed := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
khenaidoo4d4802d2018-10-04 21:59:49 -0400180 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
181 } else {
182 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
183 }
184 agent.exitChannel <- 1
185 log.Info("logical_device-agent-stopped")
186}
187
khenaidoo19d7b632018-10-30 10:49:50 -0400188// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
189func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
190 log.Debug("GetLogicalDevice")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400191 agent.lockLogicalDevice.RLock()
192 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400193 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400194 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500195 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400196 }
197 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
198}
199
khenaidoodd237172019-05-27 16:37:17 -0400200func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() (*ofp.Flows, error) {
201 log.Debug("ListLogicalDeviceFlows")
202 agent.lockLogicalDevice.RLock()
203 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400204 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400205 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
206 cFlows := (proto.Clone(lDevice.Flows)).(*ofp.Flows)
207 return cFlows, nil
208 }
209 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
210}
211
Manikkaraj kb1a10922019-07-29 12:10:34 -0400212func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() (*ofp.Meters, error) {
213 log.Debug("ListLogicalDeviceMeters")
214 agent.lockLogicalDevice.RLock()
215 defer agent.lockLogicalDevice.RUnlock()
216 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
217 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Gamze Abaka6e4ac162019-10-21 11:10:10 +0000218 if lDevice.Meters == nil {
219 return &ofp.Meters{}, nil
220 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400221 cMeters := (proto.Clone(lDevice.Meters)).(*ofp.Meters)
222 return cMeters, nil
223 }
224 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
225}
226
khenaidoodd237172019-05-27 16:37:17 -0400227func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() (*ofp.FlowGroups, error) {
228 log.Debug("ListLogicalDeviceFlowGroups")
229 agent.lockLogicalDevice.RLock()
230 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400231 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400232 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
233 cFlowGroups := (proto.Clone(lDevice.FlowGroups)).(*ofp.FlowGroups)
234 return cFlowGroups, nil
235 }
236 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
237}
238
khenaidoo19d7b632018-10-30 10:49:50 -0400239func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400240 log.Debug("ListLogicalDevicePorts")
241 agent.lockLogicalDevice.RLock()
242 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400243 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400244 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
245 lPorts := make([]*voltha.LogicalPort, 0)
246 for _, port := range lDevice.Ports {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500247 lPorts = append(lPorts, port)
khenaidoo19d7b632018-10-30 10:49:50 -0400248 }
249 return &voltha.LogicalPorts{Items: lPorts}, nil
250 }
251 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
252}
253
254// listFlows locks the logical device model and then retrieves the latest flow information
255func (agent *LogicalDeviceAgent) listFlows() []*ofp.OfpFlowStats {
256 log.Debug("listFlows")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400257 agent.lockLogicalDevice.RLock()
258 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400259 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400260 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
261 return lDevice.Flows.Items
262 }
263 return nil
264}
265
266// listFlowGroups locks the logical device model and then retrieves the latest flow groups information
267func (agent *LogicalDeviceAgent) listFlowGroups() []*ofp.OfpGroupEntry {
268 log.Debug("listFlowGroups")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400269 agent.lockLogicalDevice.RLock()
270 defer agent.lockLogicalDevice.RUnlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400271 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400272 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
273 return lDevice.FlowGroups.Items
274 }
275 return nil
276}
277
khenaidoo4c9e5592019-09-09 16:20:41 -0400278//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500279func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400280 ld, err := agent.getLogicalDeviceWithoutLock()
281 if err != nil {
282 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
283 }
284 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
285 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
286 cloned.Flows = flows
287
288 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
289 log.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
290 return err
khenaidoo43c82122018-11-22 18:38:28 -0500291 }
khenaidoo43c82122018-11-22 18:38:28 -0500292 return nil
293}
294
khenaidoo4c9e5592019-09-09 16:20:41 -0400295//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400296func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400297 ld, err := agent.getLogicalDeviceWithoutLock()
298 if err != nil {
299 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
300 }
301 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
302 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
303 cloned.Meters = meters
304
305 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
306 log.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
307 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400308 }
309 return nil
310}
311
khenaidoo4c9e5592019-09-09 16:20:41 -0400312//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
khenaidoo43c82122018-11-22 18:38:28 -0500313func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400314 ld, err := agent.getLogicalDeviceWithoutLock()
315 if err != nil {
316 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceId)
317 }
318 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
319 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
320 cloned.FlowGroups = flowGroups
321
322 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
323 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
324 return err
khenaidoo43c82122018-11-22 18:38:28 -0500325 }
khenaidoo43c82122018-11-22 18:38:28 -0500326 return nil
327}
328
khenaidoo4d4802d2018-10-04 21:59:49 -0400329// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
330// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400331func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
332 log.Debug("getLogicalDeviceWithoutLock")
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400333 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400334 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400335 //log.Debug("getLogicalDeviceWithoutLock", log.Fields{"ldevice": lDevice})
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500336 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400337 }
338 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
339}
340
khenaidoo2c6a0992019-04-29 13:46:56 -0400341func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
342 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
343 var err error
344 if port.Type == voltha.Port_ETHERNET_NNI {
345 if _, err = agent.addNNILogicalPort(device, port); err != nil {
346 return err
347 }
348 agent.addLogicalPortToMap(port.PortNo, true)
349 } else if port.Type == voltha.Port_ETHERNET_UNI {
350 if _, err = agent.addUNILogicalPort(device, port); err != nil {
351 return err
352 }
353 agent.addLogicalPortToMap(port.PortNo, false)
354 } else {
355 // Update the device graph to ensure all routes on the logical device have been calculated
356 if err = agent.updateRoutes(device, port); err != nil {
357 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
358 return err
359 }
360 }
361 return nil
362}
363
khenaidoo910204f2019-04-08 17:56:40 -0400364func (agent *LogicalDeviceAgent) addLogicalPort(device *voltha.Device, port *voltha.Port) error {
khenaidoo8f474192019-04-03 17:20:44 -0400365 log.Debugw("addLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
khenaidoo8f474192019-04-03 17:20:44 -0400366 var err error
khenaidoofc1314d2019-03-14 09:34:21 -0400367 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400368 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400369 return err
370 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400371 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400372 } else if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo910204f2019-04-08 17:56:40 -0400373 if _, err = agent.addUNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400374 return err
375 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400376 agent.addLogicalPortToMap(port.PortNo, false)
khenaidoofc1314d2019-03-14 09:34:21 -0400377 } else {
378 log.Debugw("invalid-port-type", log.Fields{"deviceId": device.Id, "port": port})
379 return nil
380 }
khenaidoofc1314d2019-03-14 09:34:21 -0400381 return nil
382}
383
khenaidoo3d3b8c22019-05-22 18:10:39 -0400384// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
385// added to it. While the logical device was being created we could have received requests to add
386// NNI and UNI ports which were discarded. Now is the time to add them if needed
387func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
388 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
389 // First add any NNI ports which could have been missing
390 if err := agent.setupNNILogicalPorts(nil, agent.rootDeviceId); err != nil {
391 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceId})
392 return err
393 }
394
395 // Now, set up the UNI ports if needed.
396 if children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceId); err != nil {
397 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceId})
398 return err
399 } else {
400 chnlsList := make([]chan interface{}, 0)
401 for _, child := range children.Items {
402 ch := make(chan interface{})
403 chnlsList = append(chnlsList, ch)
404 go func(device *voltha.Device, ch chan interface{}) {
405 if err = agent.setupUNILogicalPorts(nil, device); err != nil {
406 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": device.Id})
407 ch <- status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", device.Id)
408 }
409 ch <- nil
410 }(child, ch)
411 }
412 // Wait for completion
Scott Bakerb671a862019-10-24 10:53:40 -0700413 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400414 return status.Errorf(codes.Aborted, "errors-%s", res)
415 }
416 }
417 return nil
418}
419
khenaidoofc1314d2019-03-14 09:34:21 -0400420// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
421func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceId string) error {
422 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400423 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400424 var err error
425
426 var device *voltha.Device
427 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400428 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceId})
khenaidoofc1314d2019-03-14 09:34:21 -0400429 return err
430 }
431
432 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400433 for _, port := range device.Ports {
434 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400435 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400436 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400437 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400438 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400439 }
440 }
khenaidoofc1314d2019-03-14 09:34:21 -0400441 return err
442}
443
khenaidoo171b98e2019-10-31 11:48:15 -0400444// updatePortState updates the port state of the device
445func (agent *LogicalDeviceAgent) updatePortState(deviceId string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
446 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "portNo": portNo, "state": operStatus})
447 agent.lockLogicalDevice.Lock()
448 defer agent.lockLogicalDevice.Unlock()
449 // Get the latest logical device info
450 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
451 log.Warnw("logical-device-unknown", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
452 return err
453 } else {
454 for idx, lPort := range ld.Ports {
455 if lPort.DeviceId == deviceId && lPort.DevicePortNo == portNo {
456 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
457 if operStatus == voltha.OperStatus_ACTIVE {
458 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
459 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
460 } else {
461 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
462 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
463 }
464 // Update the logical device
465 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
466 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
467 return err
468 }
469 return nil
470 }
471 }
472 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
473 }
474}
475
khenaidoo3ab34882019-05-02 21:33:30 -0400476// updatePortsState updates the ports state related to the device
477func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
478 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
479 agent.lockLogicalDevice.Lock()
480 defer agent.lockLogicalDevice.Unlock()
481 // Get the latest logical device info
482 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
483 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
484 return err
485 } else {
486 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
487 for _, lport := range cloned.Ports {
488 if lport.DeviceId == device.Id {
489 switch state {
490 case voltha.AdminState_ENABLED:
491 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
khenaidoo0a822f92019-05-08 15:15:57 -0400492 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
khenaidoo3ab34882019-05-02 21:33:30 -0400493 case voltha.AdminState_DISABLED:
494 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
khenaidoo0a822f92019-05-08 15:15:57 -0400495 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
khenaidoo3ab34882019-05-02 21:33:30 -0400496 default:
497 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
498 }
499 }
500 }
501 // Updating the logical device will trigger the poprt change events to be populated to the controller
502 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
503 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
504 return err
505 }
506 }
507 return nil
508}
509
khenaidoofc1314d2019-03-14 09:34:21 -0400510// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
511func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400512 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoofc1314d2019-03-14 09:34:21 -0400513 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400514 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400515 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400516 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400517 for _, port := range childDevice.Ports {
518 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400519 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400520 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400521 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400522 if added {
523 agent.addLogicalPortToMap(port.PortNo, false)
524 }
khenaidoo19d7b632018-10-30 10:49:50 -0400525 }
526 }
khenaidoofc1314d2019-03-14 09:34:21 -0400527 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400528}
529
khenaidoo0a822f92019-05-08 15:15:57 -0400530// deleteAllLogicalPorts deletes all logical ports associated with this device
531func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
532 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
533 agent.lockLogicalDevice.Lock()
534 defer agent.lockLogicalDevice.Unlock()
535 // Get the latest logical device info
536 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
537 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
538 return err
539 } else {
540 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
541 updateLogicalPorts := []*voltha.LogicalPort{}
542 for _, lport := range cloned.Ports {
543 if lport.DeviceId != device.Id {
544 updateLogicalPorts = append(updateLogicalPorts, lport)
545 }
546 }
547 if len(updateLogicalPorts) < len(cloned.Ports) {
548 cloned.Ports = updateLogicalPorts
549 // Updating the logical device will trigger the poprt change events to be populated to the controller
550 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
551 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceId, "error": err})
552 return err
553 }
554 } else {
555 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
556 }
557 }
558 return nil
559}
560
khenaidoo92e62c52018-10-03 14:02:54 -0400561//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
562func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400563 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
564 afterUpdate := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400565 if afterUpdate == nil {
566 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
567 }
568 return nil
569}
570
khenaidoo4c9e5592019-09-09 16:20:41 -0400571//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
572//that device graph was generated.
573func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
574 if ld, err := agent.GetLogicalDevice(); err != nil {
575 log.Errorw("get-logical-device-error", log.Fields{"error": err})
576 return err
577 } else {
578 agent.lockDeviceGraph.Lock()
579 defer agent.lockDeviceGraph.Unlock()
580 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
581 return nil
582 }
583 log.Debug("Generation of device graph required")
584 agent.generateDeviceGraph()
585 }
586 return nil
587}
588
khenaidoo19d7b632018-10-30 10:49:50 -0400589//updateFlowTable updates the flow table of that logical device
590func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
591 log.Debug("updateFlowTable")
592 if flow == nil {
593 return nil
594 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400595 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
596 return err
597 }
khenaidoo19d7b632018-10-30 10:49:50 -0400598 switch flow.GetCommand() {
599 case ofp.OfpFlowModCommand_OFPFC_ADD:
600 return agent.flowAdd(flow)
601 case ofp.OfpFlowModCommand_OFPFC_DELETE:
602 return agent.flowDelete(flow)
603 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
604 return agent.flowDeleteStrict(flow)
605 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
606 return agent.flowModify(flow)
607 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
608 return agent.flowModifyStrict(flow)
609 }
610 return status.Errorf(codes.Internal,
611 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
612}
613
614//updateGroupTable updates the group table of that logical device
615func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
616 log.Debug("updateGroupTable")
617 if groupMod == nil {
618 return nil
619 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400620 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
621 return err
622 }
khenaidoo19d7b632018-10-30 10:49:50 -0400623 switch groupMod.GetCommand() {
624 case ofp.OfpGroupModCommand_OFPGC_ADD:
625 return agent.groupAdd(groupMod)
626 case ofp.OfpGroupModCommand_OFPGC_DELETE:
627 return agent.groupDelete(groupMod)
628 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
629 return agent.groupModify(groupMod)
630 }
631 return status.Errorf(codes.Internal,
632 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
633}
634
Manikkaraj kb1a10922019-07-29 12:10:34 -0400635// updateMeterTable updates the meter table of that logical device
636func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
637 log.Debug("updateMeterTable")
638 if meterMod == nil {
639 return nil
640 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400641 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
642 return err
643 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400644 switch meterMod.GetCommand() {
645 case ofp.OfpMeterModCommand_OFPMC_ADD:
646 return agent.meterAdd(meterMod)
647 case ofp.OfpMeterModCommand_OFPMC_DELETE:
648 return agent.meterDelete(meterMod)
649 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
650 return agent.meterModify(meterMod)
651 }
652 return status.Errorf(codes.Internal,
653 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, meterMod.GetCommand())
654
655}
656
657func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
658 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
659 if meterMod == nil {
660 return nil
661 }
662 log.Debug("Waiting for logical device lock!!")
663 agent.lockLogicalDevice.Lock()
664 defer agent.lockLogicalDevice.Unlock()
665 log.Debug("Acquired logical device lock")
666 var lDevice *voltha.LogicalDevice
667 var err error
668 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
669 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
670 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
671 }
672
673 var meters []*ofp.OfpMeterEntry
674 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
675 meters = lDevice.Meters.Items
676 }
677 log.Debugw("Available meters", log.Fields{"meters": meters})
678
679 for _, meter := range meters {
680 if meterMod.MeterId == meter.Config.MeterId {
681 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
682 return nil
683 }
684 }
685
686 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
687 meters = append(meters, meterEntry)
688 //Update model
689 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
690 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
691 return err
692 }
693 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
694 return nil
695}
696
697func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
698 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
699 if meterMod == nil {
700 return nil
701 }
702 agent.lockLogicalDevice.Lock()
703 defer agent.lockLogicalDevice.Unlock()
704
705 var lDevice *voltha.LogicalDevice
706 var err error
707 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
708 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
709 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
710 }
711
712 var meters []*ofp.OfpMeterEntry
713 var flows []*ofp.OfpFlowStats
714 updatedFlows := make([]*ofp.OfpFlowStats, 0)
715 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
716 meters = lDevice.Meters.Items
717 }
718 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
719 flows = lDevice.Flows.Items
720 }
721
722 changedMeter := false
723 changedFow := false
724 log.Debugw("Available meters", log.Fields{"meters": meters})
725 for index, meter := range meters {
726 if meterMod.MeterId == meter.Config.MeterId {
727 flows = lDevice.Flows.Items
728 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterId(flows, meterMod.MeterId)
729 meters = append(meters[:index], meters[index+1:]...)
730 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
731 changedMeter = true
732 break
733 }
734 }
735 if changedMeter {
736 //Update model
737 metersToUpdate := &ofp.Meters{}
738 if lDevice.Meters != nil {
739 metersToUpdate = &ofp.Meters{Items: meters}
740 }
741 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
742 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
743 return err
744 }
745 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
746
747 }
748 if changedFow {
749 //Update model
750 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
751 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
752 return err
753 }
754 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
755 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
756 }
757 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
758 return nil
759}
760
761func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
762 log.Debug("meterModify")
763 if meterMod == nil {
764 return nil
765 }
766 agent.lockLogicalDevice.Lock()
767 defer agent.lockLogicalDevice.Unlock()
768
769 var lDevice *voltha.LogicalDevice
770 var err error
771 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
772 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
773 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
774 }
775
776 var meters []*ofp.OfpMeterEntry
777 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
778 meters = lDevice.Meters.Items
779 }
780 changedMeter := false
781 for index, meter := range meters {
782 if meterMod.MeterId == meter.Config.MeterId {
783 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
784 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
785 meters[index] = newmeterEntry
786 changedMeter = true
787 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
788 break
789 }
790 }
791 if changedMeter {
792 //Update model
793 metersToUpdate := &ofp.Meters{}
794 if lDevice.Meters != nil {
795 metersToUpdate = &ofp.Meters{Items: meters}
796 }
797 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
798 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
799 return err
800 }
801 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
802 return nil
803 }
804
805 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
806 return errors.New(fmt.Sprintf("no-logical-device-present:%d", meterMod.MeterId))
807
808}
809
810func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterId(flows []*ofp.OfpFlowStats, meterId uint32) (bool, []*ofp.OfpFlowStats) {
811 log.Infow("Delete flows matching meter", log.Fields{"meter": meterId})
812 changed := false
813 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
814 for index := len(flows) - 1; index >= 0; index-- {
815 if mId := fu.GetMeterIdFromFlow(flows[index]); mId != 0 && mId == meterId {
816 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
817 flows = append(flows[:index], flows[index+1:]...)
818 changed = true
819 }
820 }
821 return changed, flows
822}
823
824func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
825
826 flowCommand := modCommand.GetCommand()
827 meterId := fu.GetMeterIdFromFlow(flow)
828 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterId})
829 if meterId == 0 {
830 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
831 return false
832 }
833 if meters == nil {
834 log.Debug("No meters present in logical device")
835 return false
836 }
837 changedMeter := false
838 for _, meter := range meters {
839 if meterId == meter.Config.MeterId { // Found meter in Logicaldevice
840 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
841 meter.Stats.FlowCount += 1
842 changedMeter = true
843 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
844 meter.Stats.FlowCount -= 1
845 changedMeter = true
846 }
847 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterId})
848 break
849 }
850 }
851 return changedMeter
852}
853
khenaidoo19d7b632018-10-30 10:49:50 -0400854//flowAdd adds a flow to the flow table of that logical device
855func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400856 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400857 if mod == nil {
858 return nil
859 }
khenaidoo92e62c52018-10-03 14:02:54 -0400860 agent.lockLogicalDevice.Lock()
861 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400862
863 var lDevice *voltha.LogicalDevice
864 var err error
865 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
866 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
867 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
868 }
869
870 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400871 var meters []*ofp.OfpMeterEntry
872 var flow *ofp.OfpFlowStats
873
khenaidoo19d7b632018-10-30 10:49:50 -0400874 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
875 flows = lDevice.Flows.Items
876 }
877
Manikkaraj kb1a10922019-07-29 12:10:34 -0400878 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
879 meters = lDevice.Meters.Items
880 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400881 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400882 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400883 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400884 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
885 if checkOverlap {
886 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
887 // TODO: should this error be notified other than being logged?
888 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
889 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400890 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400891 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400892 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400893 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400894 changed = true
895 }
896 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400897 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400898 idx := fu.FindFlows(flows, flow)
899 if idx >= 0 {
900 oldFlow := flows[idx]
901 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
902 flow.ByteCount = oldFlow.ByteCount
903 flow.PacketCount = oldFlow.PacketCount
904 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400905 if !reflect.DeepEqual(oldFlow, flow) {
906 flows[idx] = flow
907 updatedFlows = append(updatedFlows, flow)
908 changed = true
909 updated = true
910 }
911 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400912 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400913 updatedFlows = append(updatedFlows, flow)
914 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400915 }
khenaidoo19d7b632018-10-30 10:49:50 -0400916 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400917 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
918
khenaidoo19d7b632018-10-30 10:49:50 -0400919 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400920 var flowMetadata voltha.FlowMetadata
921 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
922 log.Error("Meter-referred-in-flows-not-present")
923 return err
924 }
khenaidoo0458db62019-06-20 08:50:36 -0400925 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
926 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
927
Manikkaraj kb1a10922019-07-29 12:10:34 -0400928 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -0400929 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400930 return err
931 }
932
khenaidoo19d7b632018-10-30 10:49:50 -0400933 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400934 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400935 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400936 return err
937 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400938 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400939 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
940 metersToUpdate := &ofp.Meters{}
941 if lDevice.Meters != nil {
942 metersToUpdate = &ofp.Meters{Items: meters}
943 }
944 if changedMeterStats {
945 //Update model
946 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
947 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
948 return err
949 }
950 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
951
952 }
953 }
954
khenaidoo19d7b632018-10-30 10:49:50 -0400955 }
khenaidoo19d7b632018-10-30 10:49:50 -0400956 return nil
957}
958
Manikkaraj kb1a10922019-07-29 12:10:34 -0400959func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
960 m := make(map[uint32]bool)
961 for _, flow := range flows {
962 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && m[flowMeterID] == false {
963 foundMeter := false
964 // Meter is present in the flow , Get from logical device
965 for _, meter := range meters {
966 if flowMeterID == meter.Config.MeterId {
967 metadata.Meters = append(metadata.Meters, meter.Config)
968 log.Debugw("Found meter in logical device",
969 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
970 m[flowMeterID] = true
971 foundMeter = true
972 break
973 }
974 }
975 if !foundMeter {
976 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
977 log.Fields{"meterID": flowMeterID, "Avaliable-meters": meters, "flow": *flow})
978 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
979 }
980 }
981 }
982 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
983 return nil
984
985}
986
khenaidoo19d7b632018-10-30 10:49:50 -0400987//flowDelete deletes a flow from the flow table of that logical device
988func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
989 log.Debug("flowDelete")
990 if mod == nil {
991 return nil
992 }
993 agent.lockLogicalDevice.Lock()
994 defer agent.lockLogicalDevice.Unlock()
995
996 var lDevice *voltha.LogicalDevice
997 var err error
998 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
999 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1000 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1001 }
khenaidoo19d7b632018-10-30 10:49:50 -04001002
Manikkaraj kb1a10922019-07-29 12:10:34 -04001003 var meters []*ofp.OfpMeterEntry
1004 var flows []*ofp.OfpFlowStats
1005
1006 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1007 flows = lDevice.Flows.Items
1008 }
1009
1010 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1011 meters = lDevice.Meters.Items
1012 }
khenaidoo19d7b632018-10-30 10:49:50 -04001013 //build a list of what to keep vs what to delete
1014 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001015 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001016 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -04001017 // Check whether the flow and the flowmod matches
1018 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
1019 toDelete = append(toDelete, f)
1020 continue
1021 }
1022 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -04001023 if !fu.FlowMatchesMod(f, mod) {
1024 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -04001025 } else {
1026 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -04001027 }
1028 }
1029
khenaidoo0458db62019-06-20 08:50:36 -04001030 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "toKeep": len(toKeep), "toDelete": toDelete})
1031
khenaidoo19d7b632018-10-30 10:49:50 -04001032 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -04001033 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001034 var flowMetadata voltha.FlowMetadata
1035 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
1036 log.Error("Meter-referred-in-flows-not-present")
1037 return errors.New("Meter-referred-in-flows-not-present")
1038 }
khenaidoo0458db62019-06-20 08:50:36 -04001039 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
1040 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1041
Manikkaraj kb1a10922019-07-29 12:10:34 -04001042 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001043 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1044 return err
1045 }
1046
khenaidoo43c82122018-11-22 18:38:28 -05001047 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
1048 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001049 return err
1050 }
1051 }
1052
1053 //TODO: send announcement on delete
1054 return nil
1055}
1056
Manikkaraj kb1a10922019-07-29 12:10:34 -04001057func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
1058 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001059
khenaidoo0458db62019-06-20 08:50:36 -04001060 chnlsList := make([]chan interface{}, 0)
1061 for deviceId, value := range deviceRules.GetRules() {
1062 ch := make(chan interface{})
1063 chnlsList = append(chnlsList, ch)
1064 go func(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001065 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, flows, groups, flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001066 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
1067 ch <- status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId)
1068 }
1069 ch <- nil
1070 }(deviceId, value.ListFlows(), value.ListGroups())
khenaidoo19d7b632018-10-30 10:49:50 -04001071 }
khenaidoo0458db62019-06-20 08:50:36 -04001072 // Wait for completion
Scott Bakerb671a862019-10-24 10:53:40 -07001073 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001074 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001075 }
khenaidoo0458db62019-06-20 08:50:36 -04001076 return nil
1077}
khenaidoo19d7b632018-10-30 10:49:50 -04001078
Manikkaraj kb1a10922019-07-29 12:10:34 -04001079func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -04001080 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId})
1081
1082 chnlsList := make([]chan interface{}, 0)
1083 for deviceId, value := range deviceRules.GetRules() {
1084 ch := make(chan interface{})
1085 chnlsList = append(chnlsList, ch)
1086 go func(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001087 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, flows, groups, flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001088 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
1089 ch <- status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId)
1090 }
1091 ch <- nil
1092 }(deviceId, value.ListFlows(), value.ListGroups())
1093 }
1094 // Wait for completion
Scott Bakerb671a862019-10-24 10:53:40 -07001095 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001096 return status.Errorf(codes.Aborted, "errors-%s", res)
1097 }
1098 return nil
1099}
1100
Manikkaraj kb1a10922019-07-29 12:10:34 -04001101func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
khenaidoo0458db62019-06-20 08:50:36 -04001102 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceId})
1103
1104 chnlsList := make([]chan interface{}, 0)
1105 for deviceId, value := range deviceRules.GetRules() {
1106 ch := make(chan interface{})
1107 chnlsList = append(chnlsList, ch)
1108 go func(deviceId string, flows []*ofp.OfpFlowStats, groups []*ofp.OfpGroupEntry) {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001109 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, flows, groups, flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001110 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
1111 ch <- status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId)
1112 }
1113 ch <- nil
1114 }(deviceId, value.ListFlows(), value.ListGroups())
1115 }
1116 // Wait for completion
Scott Bakerb671a862019-10-24 10:53:40 -07001117 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, chnlsList...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001118 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001119 }
1120 return nil
1121}
1122
1123//flowDeleteStrict deletes a flow from the flow table of that logical device
1124func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1125 log.Debug("flowDeleteStrict")
1126 if mod == nil {
1127 return nil
1128 }
1129 agent.lockLogicalDevice.Lock()
1130 defer agent.lockLogicalDevice.Unlock()
1131
1132 var lDevice *voltha.LogicalDevice
1133 var err error
1134 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1135 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1136 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1137 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001138 var meters []*ofp.OfpMeterEntry
1139 var flows []*ofp.OfpFlowStats
1140 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1141 meters = lDevice.Meters.Items
1142 }
1143 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1144 flows = lDevice.Flows.Items
1145 }
1146
1147 changedFlow := false
1148 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001149 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001150 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001151 idx := fu.FindFlows(flows, flow)
1152 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001153 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001154 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001155 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001156 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001157 } else {
1158 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
1159 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001160 if changedMeter {
1161 //Update model
1162 metersToUpdate := &ofp.Meters{}
1163 if lDevice.Meters != nil {
1164 metersToUpdate = &ofp.Meters{Items: meters}
1165 }
1166 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
1167 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1168 return err
1169 }
khenaidoo19d7b632018-10-30 10:49:50 -04001170
Manikkaraj kb1a10922019-07-29 12:10:34 -04001171 }
1172 if changedFlow {
1173 var flowMetadata voltha.FlowMetadata
1174 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
1175 log.Error("Meter-referred-in-flows-not-present")
1176 return err
1177 }
1178 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001179 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1180
Manikkaraj kb1a10922019-07-29 12:10:34 -04001181 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001182 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1183 return err
1184 }
1185
khenaidoo43c82122018-11-22 18:38:28 -05001186 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001187 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001188 return err
1189 }
1190 }
khenaidoo19d7b632018-10-30 10:49:50 -04001191 return nil
1192}
1193
1194//flowModify modifies a flow from the flow table of that logical device
1195func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1196 return errors.New("flowModify not implemented")
1197}
1198
1199//flowModifyStrict deletes a flow from the flow table of that logical device
1200func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1201 return errors.New("flowModifyStrict not implemented")
1202}
1203
1204func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1205 log.Debug("groupAdd")
1206 if groupMod == nil {
1207 return nil
1208 }
1209 agent.lockLogicalDevice.Lock()
1210 defer agent.lockLogicalDevice.Unlock()
1211
1212 var lDevice *voltha.LogicalDevice
1213 var err error
1214 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1215 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1216 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1217 }
1218 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001219 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001220 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001221
1222 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *lDevice.Flows, ofp.FlowGroups{Items: groups})
1223 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001224 if err := agent.addDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001225 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1226 return err
1227 }
1228
khenaidoo43c82122018-11-22 18:38:28 -05001229 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
1230 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001231 return err
1232 }
1233 } else {
1234 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
1235 }
khenaidoo19d7b632018-10-30 10:49:50 -04001236 return nil
1237}
1238
1239func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1240 log.Debug("groupDelete")
1241 if groupMod == nil {
1242 return nil
1243 }
1244 agent.lockLogicalDevice.Lock()
1245 defer agent.lockLogicalDevice.Unlock()
1246
1247 var lDevice *voltha.LogicalDevice
1248 var err error
1249 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1250 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1251 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1252 }
1253 groups := lDevice.FlowGroups.Items
1254 flows := lDevice.Flows.Items
1255 groupsChanged := false
1256 flowsChanged := false
1257 groupId := groupMod.GroupId
1258 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
1259 //TODO we must delete all flows that point to this group and
1260 //signal controller as requested by flow's flag
1261 groups = []*ofp.OfpGroupEntry{}
1262 groupsChanged = true
1263 } else {
1264 if idx := fu.FindGroup(groups, groupId); idx == -1 {
1265 return nil // Valid case
1266 } else {
1267 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
1268 groups = append(groups[:idx], groups[idx+1:]...)
1269 groupsChanged = true
1270 }
1271 }
khenaidoo0458db62019-06-20 08:50:36 -04001272 if flowsChanged || groupsChanged {
1273 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1274 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1275
Manikkaraj kb1a10922019-07-29 12:10:34 -04001276 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001277 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1278 return err
1279 }
1280 }
1281
khenaidoo43c82122018-11-22 18:38:28 -05001282 if groupsChanged {
1283 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
1284 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -04001285 return err
1286 }
1287 }
khenaidoo43c82122018-11-22 18:38:28 -05001288 if flowsChanged {
1289 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
1290 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1291 return err
1292 }
1293 }
khenaidoo19d7b632018-10-30 10:49:50 -04001294 return nil
1295}
1296
1297func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1298 log.Debug("groupModify")
1299 if groupMod == nil {
1300 return nil
1301 }
1302 agent.lockLogicalDevice.Lock()
1303 defer agent.lockLogicalDevice.Unlock()
1304
1305 var lDevice *voltha.LogicalDevice
1306 var err error
1307 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1308 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1309 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
1310 }
1311 groups := lDevice.FlowGroups.Items
1312 groupsChanged := false
1313 groupId := groupMod.GroupId
1314 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -05001315 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -04001316 } else {
1317 //replace existing group entry with new group definition
khenaidoo68c930b2019-05-13 11:46:51 -04001318 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -04001319 groups[idx] = groupEntry
1320 groupsChanged = true
1321 }
1322 if groupsChanged {
khenaidoo0458db62019-06-20 08:50:36 -04001323 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: lDevice.Flows.Items}, ofp.FlowGroups{Items: groups})
1324 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1325
Manikkaraj kb1a10922019-07-29 12:10:34 -04001326 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001327 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1328 return err
1329 }
1330
khenaidoo43c82122018-11-22 18:38:28 -05001331 //lDevice.FlowGroups.Items = groups
1332 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001333 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1334 return err
1335 }
1336 }
1337 return nil
1338}
1339
1340// deleteLogicalPort removes the logical port
1341func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1342 agent.lockLogicalDevice.Lock()
1343 defer agent.lockLogicalDevice.Unlock()
1344
khenaidoo92e62c52018-10-03 14:02:54 -04001345 // Get the most up to date logical device
1346 var logicaldevice *voltha.LogicalDevice
1347 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -04001348 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -04001349 return nil
1350 }
khenaidoo92e62c52018-10-03 14:02:54 -04001351 index := -1
1352 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001353 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001354 index = i
1355 break
1356 }
1357 }
1358 if index >= 0 {
1359 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
1360 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
1361 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
1362 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo0a822f92019-05-08 15:15:57 -04001363 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
1364 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1365 return err
1366 }
1367 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001368 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001369 }
1370 return nil
khenaidoob9203542018-09-17 22:56:37 -04001371}
1372
khenaidoo0a822f92019-05-08 15:15:57 -04001373// deleteLogicalPorts removes the logical ports associated with that deviceId
1374func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceId string) error {
1375 agent.lockLogicalDevice.Lock()
1376 defer agent.lockLogicalDevice.Unlock()
1377
1378 // Get the most up to date logical device
1379 var logicaldevice *voltha.LogicalDevice
1380 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
1381 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1382 return nil
1383 }
1384 updatedLPorts := []*voltha.LogicalPort{}
1385 for _, logicalPort := range logicaldevice.Ports {
1386 if logicalPort.DeviceId != deviceId {
1387 updatedLPorts = append(updatedLPorts, logicalPort)
1388 }
1389 }
1390 logicaldevice.Ports = updatedLPorts
1391 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
1392 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
1393 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1394 return err
1395 }
1396 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001397 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001398
1399 return nil
1400}
1401
khenaidoo19d7b632018-10-30 10:49:50 -04001402// enableLogicalPort enables the logical port
Girish Kumar0d4597e2019-10-24 18:13:14 +00001403func (agent *LogicalDeviceAgent) enableLogicalPort(lPortId string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001404 agent.lockLogicalDevice.Lock()
1405 defer agent.lockLogicalDevice.Unlock()
1406
1407 // Get the most up to date logical device
1408 var logicaldevice *voltha.LogicalDevice
1409 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001410 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPortId})
khenaidoo19d7b632018-10-30 10:49:50 -04001411 return nil
1412 }
1413 index := -1
1414 for i, logicalPort := range logicaldevice.Ports {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001415 if logicalPort.Id == lPortId {
khenaidoo19d7b632018-10-30 10:49:50 -04001416 index = i
1417 break
1418 }
1419 }
1420 if index >= 0 {
1421 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1422 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
Girish Kumar0d4597e2019-10-24 18:13:14 +00001423 } else {
1424 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortId, agent.logicalDeviceId)
khenaidoo19d7b632018-10-30 10:49:50 -04001425 }
khenaidoo19d7b632018-10-30 10:49:50 -04001426}
1427
1428// disableLogicalPort disabled the logical port
Girish Kumar0d4597e2019-10-24 18:13:14 +00001429func (agent *LogicalDeviceAgent) disableLogicalPort(lPortId string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001430 agent.lockLogicalDevice.Lock()
1431 defer agent.lockLogicalDevice.Unlock()
1432
1433 // Get the most up to date logical device
1434 var logicaldevice *voltha.LogicalDevice
1435 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001436 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPortId})
khenaidoo19d7b632018-10-30 10:49:50 -04001437 return nil
1438 }
1439 index := -1
1440 for i, logicalPort := range logicaldevice.Ports {
Girish Kumar0d4597e2019-10-24 18:13:14 +00001441 if logicalPort.Id == lPortId {
khenaidoo19d7b632018-10-30 10:49:50 -04001442 index = i
1443 break
1444 }
1445 }
1446 if index >= 0 {
1447 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1448 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
Girish Kumar0d4597e2019-10-24 18:13:14 +00001449 } else {
1450 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortId, agent.logicalDeviceId)
khenaidoo19d7b632018-10-30 10:49:50 -04001451 }
khenaidoo19d7b632018-10-30 10:49:50 -04001452}
1453
khenaidoo89b0e942018-10-21 21:11:33 -04001454func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001455 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001456 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001457 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001458 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1459 return route
1460 }
1461 }
1462 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
1463 return nil
1464}
1465
khenaidoo19d7b632018-10-30 10:49:50 -04001466func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001467 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001468 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001469
khenaidoo19d7b632018-10-30 10:49:50 -04001470 // Note: A port value of 0 is equivalent to a nil port
1471
khenaidoo89b0e942018-10-21 21:11:33 -04001472 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001473 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001474 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1475 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001476 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001477 if len(agent.deviceGraph.Routes) == 0 {
1478 // 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 -04001479 // route with same IngressHop and EgressHop
1480 hop := graph.RouteHop{DeviceID: agent.rootDeviceId, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001481 routes = append(routes, hop)
1482 routes = append(routes, hop)
1483 return routes
1484 }
khenaidoo89b0e942018-10-21 21:11:33 -04001485 //Return a 'half' route to make the flow decomposer logic happy
1486 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001487 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001488 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1489 routes = append(routes, route[1])
1490 return routes
1491 }
1492 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001493 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001494 return nil
1495 }
1496 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001497 var err error
1498 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1499 log.Warnw("no-nni-port", log.Fields{"error": err})
1500 return nil
1501 }
khenaidoo89b0e942018-10-21 21:11:33 -04001502 }
1503 //If ingress port is not specified (nil), it may be a wildcarded
1504 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1505 //in which case we need to create a half-route where only the egress
1506 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001507 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001508 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1509 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001510 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001511 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1512 routes = append(routes, route[1])
1513 return routes
1514 }
1515 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001516 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001517 return nil
1518 }
1519 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001520 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001521 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001522 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001523 routes = append(routes, route[0])
1524 routes = append(routes, graph.RouteHop{})
1525 return routes
1526 }
1527 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001528 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001529 return nil
1530 }
khenaidoo89b0e942018-10-21 21:11:33 -04001531 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001532 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001533}
1534
khenaidoo3d3b8c22019-05-22 18:10:39 -04001535//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1536//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1537//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001538func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1539 lPorts := make([]uint32, 0)
1540 var exclPort uint32
1541 if len(excludePort) == 1 {
1542 exclPort = excludePort[0]
1543 }
khenaidoo3d3b8c22019-05-22 18:10:39 -04001544 if lDevice, _ := agent.getLogicalDeviceWithoutLock(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -04001545 for _, port := range lDevice.Ports {
1546 if port.OfpPort.PortNo != exclPort {
1547 lPorts = append(lPorts, port.OfpPort.PortNo)
1548 }
1549 }
1550 }
1551 return lPorts
1552}
khenaidoo19d7b632018-10-30 10:49:50 -04001553
1554func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1555 return agent.deviceGraph
1556}
1557
khenaidoo3306c992019-05-24 16:57:35 -04001558//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001559func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
1560 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001561 agent.lockLogicalDevice.Lock()
1562 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001563 if agent.deviceGraph == nil {
khenaidoo910204f2019-04-08 17:56:40 -04001564 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001565 }
1566 // Get all the logical ports on that logical device
1567 if lDevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
manikkaraj k259a6f72019-05-06 09:55:44 -04001568 log.Errorw("unknown-logical-device", log.Fields{"error": err, "logicalDeviceId": agent.logicalDeviceId})
khenaidoo2c6a0992019-04-29 13:46:56 -04001569 return err
1570 } else {
1571 //TODO: Find a better way to refresh only missing routes
1572 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
1573 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001574 agent.deviceGraph.Print()
1575 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001576}
1577
khenaidoo2c6a0992019-04-29 13:46:56 -04001578//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001579func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001580 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
1581 agent.lockLogicalDevice.Lock()
1582 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001583 if agent.deviceGraph == nil {
1584 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
1585 }
1586 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001587 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001588}
khenaidoofdbad6e2018-11-06 22:26:38 -05001589
khenaidoo3d3b8c22019-05-22 18:10:39 -04001590//generateDeviceGraph regenerates the device graph
1591func (agent *LogicalDeviceAgent) generateDeviceGraph() {
khenaidoo4c9e5592019-09-09 16:20:41 -04001592 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo0a822f92019-05-08 15:15:57 -04001593 agent.lockLogicalDevice.Lock()
1594 defer agent.lockLogicalDevice.Unlock()
1595 // Get the latest logical device
1596 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
1597 log.Errorw("logical-device-not-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
1598 } else {
khenaidoo4c9e5592019-09-09 16:20:41 -04001599 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceId, "lPorts": len(ld.Ports)})
khenaidoo3d3b8c22019-05-22 18:10:39 -04001600 if agent.deviceGraph == nil {
1601 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceId, agent.deviceMgr.GetDevice)
1602 }
khenaidoo0a822f92019-05-08 15:15:57 -04001603 agent.deviceGraph.ComputeRoutes(ld.Ports)
khenaidoo3d3b8c22019-05-22 18:10:39 -04001604 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001605 }
1606}
1607
khenaidoofc1314d2019-03-14 09:34:21 -04001608// portAdded is a callback invoked when a port is added to the logical device.
1609// TODO: To use when POST_ADD is fixed.
1610func (agent *LogicalDeviceAgent) portAdded(args ...interface{}) interface{} {
1611 log.Debugw("portAdded-callback", log.Fields{"argsLen": len(args)})
1612
1613 var port *voltha.LogicalPort
1614
1615 // Sanity check
1616 if args[0] != nil {
1617 log.Warnw("previous-data-not-nil", log.Fields{"args0": args[0]})
1618 }
1619 var ok bool
1620 if port, ok = args[1].(*voltha.LogicalPort); !ok {
1621 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1622 return nil
1623 }
1624
1625 // Set the proxy and callback for that port
1626 agent.portProxiesLock.Lock()
Stephane Barbarie40fd3b22019-04-23 21:50:47 -04001627 agent.portProxies[port.Id] = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -04001628 context.Background(),
khenaidoofc1314d2019-03-14 09:34:21 -04001629 fmt.Sprintf("/logical_devices/%s/ports/%s", agent.logicalDeviceId, port.Id),
1630 false)
1631 agent.portProxies[port.Id].RegisterCallback(model.POST_UPDATE, agent.portUpdated)
1632 agent.portProxiesLock.Unlock()
1633
1634 // Send the port change event to the OF controller
1635 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001636 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: port.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001637
1638 return nil
1639}
1640
1641// portRemoved is a callback invoked when a port is removed from the logical device.
1642// TODO: To use when POST_ADD is fixed.
1643func (agent *LogicalDeviceAgent) portRemoved(args ...interface{}) interface{} {
1644 log.Debugw("portRemoved-callback", log.Fields{"argsLen": len(args)})
1645
1646 var port *voltha.LogicalPort
1647
1648 // Sanity check
1649 if args[1] != nil {
1650 log.Warnw("data-not-nil", log.Fields{"args1": args[1]})
1651 }
1652 var ok bool
1653 if port, ok = args[0].(*voltha.LogicalPort); !ok {
1654 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1655 return nil
1656 }
1657
1658 // Remove the proxy and callback for that port
1659 agent.portProxiesLock.Lock()
1660 agent.portProxies[port.Id].UnregisterCallback(model.POST_UPDATE, agent.portUpdated)
1661 delete(agent.portProxies, port.Id)
1662 agent.portProxiesLock.Unlock()
1663
1664 // Send the port change event to the OF controller
1665 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001666 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: port.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001667
1668 return nil
1669}
1670
1671// 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 -04001672func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001673 newPorts = make([]*voltha.LogicalPort, 0)
1674 changedPorts = make([]*voltha.LogicalPort, 0)
1675 deletedPorts = make([]*voltha.LogicalPort, 0)
1676 for _, o := range oldList {
1677 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001678 for _, n := range newList {
1679 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001680 found = true
1681 break
1682 }
1683 }
1684 if !found {
1685 deletedPorts = append(deletedPorts, o)
1686 }
khenaidoofc1314d2019-03-14 09:34:21 -04001687 }
1688 for _, n := range newList {
1689 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001690 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001691 for _, o := range oldList {
1692 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001693 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001694 found = true
1695 break
1696 }
1697 }
1698 if !found {
1699 newPorts = append(newPorts, n)
1700 }
khenaidoo2bc48282019-07-16 18:13:46 -04001701 if changed {
1702 changedPorts = append(changedPorts, n)
1703 }
khenaidoofc1314d2019-03-14 09:34:21 -04001704 }
1705 return
1706}
1707
1708// portUpdated is invoked when a port is updated on the logical device. Until
1709// the POST_ADD notification is fixed, we will use the logical device to
1710// update that data.
1711func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1712 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1713
1714 var oldLD *voltha.LogicalDevice
1715 var newlD *voltha.LogicalDevice
1716
1717 var ok bool
1718 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1719 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1720 return nil
1721 }
1722 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1723 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1724 return nil
1725 }
1726
1727 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1728 log.Debug("ports-have-not-changed")
1729 return nil
1730 }
1731
1732 // Get the difference between the two list
1733 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1734
1735 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001736 for _, newP := range newPorts {
khenaidoofc1314d2019-03-14 09:34:21 -04001737 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo2c6a0992019-04-29 13:46:56 -04001738 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001739 }
1740 for _, change := range changedPorts {
1741 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001742 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001743 }
1744 for _, del := range deletedPorts {
1745 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
khenaidoo910204f2019-04-08 17:56:40 -04001746 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001747 }
1748
1749 return nil
1750}
1751
khenaidoo8f474192019-04-03 17:20:44 -04001752// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1753// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1754// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1755// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001756func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001757 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001758 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1759 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1760 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001761 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001762 agent.lockLogicalDevice.RLock()
1763 if agent.portExist(device, port) {
1764 log.Debugw("port-already-exist", log.Fields{"port": port})
1765 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001766 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001767 }
1768 agent.lockLogicalDevice.RUnlock()
1769
khenaidoofc1314d2019-03-14 09:34:21 -04001770 var portCap *ic.PortCapability
1771 var err error
1772 // First get the port capability
1773 if portCap, err = agent.deviceMgr.getPortCapability(nil, device.Id, port.PortNo); err != nil {
1774 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001775 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001776 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001777
1778 agent.lockLogicalDevice.Lock()
1779 defer agent.lockLogicalDevice.Unlock()
1780 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1781 if agent.portExist(device, port) {
1782 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001783 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001784 }
1785
khenaidoofc1314d2019-03-14 09:34:21 -04001786 portCap.Port.RootPort = true
1787 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1788 lp.DeviceId = device.Id
1789 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1790 lp.OfpPort.PortNo = port.PortNo
1791 lp.OfpPort.Name = lp.Id
1792 lp.DevicePortNo = port.PortNo
1793
khenaidoofc1314d2019-03-14 09:34:21 -04001794 var ld *voltha.LogicalDevice
1795 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1796 log.Errorw("error-retrieving-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001797 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001798 }
1799 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1800 if cloned.Ports == nil {
1801 cloned.Ports = make([]*voltha.LogicalPort, 0)
1802 }
1803 cloned.Ports = append(cloned.Ports, lp)
1804
1805 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1806 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001807 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001808 }
khenaidoo910204f2019-04-08 17:56:40 -04001809
1810 // Update the device graph with this new logical port
1811 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1812 go agent.updateDeviceGraph(clonedLP)
1813
khenaidoo8f474192019-04-03 17:20:44 -04001814 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001815}
1816
khenaidoo910204f2019-04-08 17:56:40 -04001817func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo54544ae2019-03-18 13:22:39 -04001818 if ldevice, _ := agent.getLogicalDeviceWithoutLock(); ldevice != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001819 for _, lPort := range ldevice.Ports {
khenaidoo54544ae2019-03-18 13:22:39 -04001820 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
khenaidoofc1314d2019-03-14 09:34:21 -04001821 return true
1822 }
1823 }
1824 }
1825 return false
1826}
1827
khenaidoo8f474192019-04-03 17:20:44 -04001828// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1829// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1830// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1831// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001832func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001833 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001834 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1835 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1836 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001837 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001838 agent.lockLogicalDevice.RLock()
1839 if agent.portExist(childDevice, port) {
1840 log.Debugw("port-already-exist", log.Fields{"port": port})
1841 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001842 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001843 }
1844 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001845 var portCap *ic.PortCapability
1846 var err error
1847 // First get the port capability
1848 if portCap, err = agent.deviceMgr.getPortCapability(nil, childDevice.Id, port.PortNo); err != nil {
1849 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001850 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001851 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001852 agent.lockLogicalDevice.Lock()
1853 defer agent.lockLogicalDevice.Unlock()
1854 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1855 if agent.portExist(childDevice, port) {
1856 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001857 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001858 }
khenaidoofc1314d2019-03-14 09:34:21 -04001859 // Get stored logical device
1860 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
khenaidoo8f474192019-04-03 17:20:44 -04001861 return false, status.Error(codes.NotFound, agent.logicalDeviceId)
khenaidoofc1314d2019-03-14 09:34:21 -04001862 } else {
1863 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1864 portCap.Port.RootPort = false
Matt Jeanneret3815e322019-03-12 19:15:49 -04001865 portCap.Port.Id = port.Label
1866 portCap.Port.OfpPort.PortNo = port.PortNo
khenaidoofc1314d2019-03-14 09:34:21 -04001867 portCap.Port.DeviceId = childDevice.Id
1868 portCap.Port.DevicePortNo = port.PortNo
1869 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1870 if cloned.Ports == nil {
1871 cloned.Ports = make([]*voltha.LogicalPort, 0)
1872 }
1873 cloned.Ports = append(cloned.Ports, portCap.Port)
khenaidoo910204f2019-04-08 17:56:40 -04001874 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1875 return false, err
1876 }
khenaidoo910204f2019-04-08 17:56:40 -04001877 // Update the device graph with this new logical port
1878 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1879 go agent.updateDeviceGraph(clonedLP)
1880 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001881 }
1882}
1883
khenaidoo43c82122018-11-22 18:38:28 -05001884func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
khenaidoofdbad6e2018-11-06 22:26:38 -05001885 log.Debugw("packet-out", log.Fields{"packet": packet.GetInPort()})
khenaidoo68c930b2019-05-13 11:46:51 -04001886 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001887 //frame := packet.GetData()
1888 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001889 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
khenaidoo910204f2019-04-08 17:56:40 -04001890 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceId})
khenaidooca301322019-01-09 23:06:32 -05001891 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001892}
1893
khenaidoo297cd252019-02-07 22:10:23 -05001894func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionId string, packet []byte) {
1895 log.Debugw("packet-in", log.Fields{"port": port, "packet": packet, "transactionId": transactionId})
khenaidoo68c930b2019-05-13 11:46:51 -04001896 packetIn := fu.MkPacketIn(port, packet)
khenaidoo297cd252019-02-07 22:10:23 -05001897 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, transactionId, packetIn)
khenaidooca301322019-01-09 23:06:32 -05001898 log.Debugw("sending-packet-in", log.Fields{"packet-in": packetIn})
khenaidoofdbad6e2018-11-06 22:26:38 -05001899}
khenaidoo2c6a0992019-04-29 13:46:56 -04001900
1901func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1902 agent.lockLogicalPortsNo.Lock()
1903 defer agent.lockLogicalPortsNo.Unlock()
1904 if exist := agent.logicalPortsNo[portNo]; !exist {
1905 agent.logicalPortsNo[portNo] = nniPort
1906 }
1907}
1908
khenaidoo3d3b8c22019-05-22 18:10:39 -04001909func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1910 agent.lockLogicalPortsNo.Lock()
1911 defer agent.lockLogicalPortsNo.Unlock()
1912 for _, lp := range lps {
1913 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1914 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1915 }
1916 }
1917}
1918
khenaidoo2c6a0992019-04-29 13:46:56 -04001919func (agent *LogicalDeviceAgent) deleteLogicalPortFromMap(portNo uint32) {
1920 agent.lockLogicalPortsNo.Lock()
1921 defer agent.lockLogicalPortsNo.Unlock()
1922 if exist := agent.logicalPortsNo[portNo]; exist {
1923 delete(agent.logicalPortsNo, portNo)
1924 }
1925}
1926
1927func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1928 agent.lockLogicalPortsNo.RLock()
1929 defer agent.lockLogicalPortsNo.RUnlock()
1930 if exist := agent.logicalPortsNo[portNo]; exist {
1931 return agent.logicalPortsNo[portNo]
1932 }
1933 return false
1934}
1935
1936func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1937 agent.lockLogicalPortsNo.RLock()
1938 defer agent.lockLogicalPortsNo.RUnlock()
1939 for portNo, nni := range agent.logicalPortsNo {
1940 if nni {
1941 return portNo, nil
1942 }
1943 }
1944 return 0, status.Error(codes.NotFound, "No NNI port found")
1945}