blob: 2ac9bd739eb3cbd87c05f3e171555b8d7c558f18 [file] [log] [blame]
Mahir Gunyel03de0d32020-06-03 01:36:59 -07001/*
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 */
16
17package device
18
19import (
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070020 "context"
Maninder9a1bc0d2020-10-26 11:34:02 +053021 "fmt"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070022
23 "github.com/gogo/protobuf/proto"
24 coreutils "github.com/opencord/voltha-go/rw_core/utils"
Maninderdfadc982020-10-28 14:04:33 +053025 fu "github.com/opencord/voltha-lib-go/v4/pkg/flows"
26 "github.com/opencord/voltha-lib-go/v4/pkg/log"
Maninder9a1bc0d2020-10-26 11:34:02 +053027 "github.com/opencord/voltha-protos/v4/go/common"
Maninderdfadc982020-10-28 14:04:33 +053028 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
29 "github.com/opencord/voltha-protos/v4/go/voltha"
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070030 "google.golang.org/grpc/codes"
31 "google.golang.org/grpc/status"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070032)
33
34// listDeviceFlows returns device flows
35func (agent *Agent) listDeviceFlows() map[uint64]*ofp.OfpFlowStats {
khenaidoo7585a962021-06-10 16:15:38 -040036 flowIDs := agent.flowCache.ListIDs()
Mahir Gunyel03de0d32020-06-03 01:36:59 -070037 flows := make(map[uint64]*ofp.OfpFlowStats, len(flowIDs))
38 for flowID := range flowIDs {
khenaidoo7585a962021-06-10 16:15:38 -040039 if flowHandle, have := agent.flowCache.Lock(flowID); have {
Mahir Gunyel03de0d32020-06-03 01:36:59 -070040 flows[flowID] = flowHandle.GetReadOnly()
41 flowHandle.Unlock()
42 }
43 }
44 return flows
45}
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070046
47func (agent *Agent) addFlowsToAdapter(ctx context.Context, newFlows []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +000048 logger.Debugw(ctx, "add-flows-to-adapters", log.Fields{"device-id": agent.deviceID, "flows": newFlows, "flow-metadata": flowMetadata})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070049
Maninder9a1bc0d2020-10-26 11:34:02 +053050 var desc string
51 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
52
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070053 if (len(newFlows)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +000054 logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070055 return coreutils.DoneResponse(), nil
56 }
Kent Hagermancba2f302020-07-28 13:37:36 -040057 device, err := agent.getDeviceReadOnly(ctx)
58 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +053059 desc = err.Error()
60 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Kent Hagermancba2f302020-07-28 13:37:36 -040061 return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
62 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070063 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
64 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +053065 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
66 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070067 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
68 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070069 flowsToAdd := make([]*ofp.OfpFlowStats, 0)
70 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
71 for _, flow := range newFlows {
khenaidoo7585a962021-06-10 16:15:38 -040072 flowHandle, created, err := agent.flowCache.LockOrCreate(ctx, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070073 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +053074 desc = err.Error()
75 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070076 return coreutils.DoneResponse(), err
77 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070078 if created {
79 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070080 } else {
81 flowToReplace := flowHandle.GetReadOnly()
82 if !proto.Equal(flowToReplace, flow) {
83 //Flow needs to be updated.
84 if err := flowHandle.Update(ctx, flow); err != nil {
85 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +053086 desc = fmt.Sprintf("failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
87 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070088 return coreutils.DoneResponse(), status.Errorf(codes.Internal, "failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
89 }
90 flowsToDelete = append(flowsToDelete, flowToReplace)
91 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070092 } else {
93 //No need to change the flow. It is already exist.
Himani Chawlab4c25912020-11-12 17:16:38 +053094 logger.Debugw(ctx, "no-need-to-change-already-existing-flow", log.Fields{"device-id": agent.deviceID, "flows": newFlows, "flow-metadata": flowMetadata})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070095 }
96 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070097 flowHandle.Unlock()
98 }
99
100 // Sanity check
101 if (len(flowsToAdd)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000102 logger.Debugw(ctx, "no-flows-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700103 return coreutils.DoneResponse(), nil
104 }
105
106 // Send update to adapters
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000107 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530108 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
109
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700110 response := coreutils.NewResponse()
111 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400112
113 updatedAllFlows := agent.listDeviceFlows()
114 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700115 if err != nil {
116 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530117 desc = err.Error()
118 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700119 return coreutils.DoneResponse(), err
120 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530121 go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700122 } else {
123 flowChanges := &ofp.FlowChanges{
124 ToAdd: &voltha.Flows{Items: flowsToAdd},
125 ToRemove: &voltha.Flows{Items: flowsToDelete},
126 }
127 groupChanges := &ofp.FlowGroupChanges{
128 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
129 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
130 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
131 }
132 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
133 if err != nil {
134 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530135 desc = err.Error()
136 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700137 return coreutils.DoneResponse(), err
138 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530139 go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700140 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530141 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
142 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700143 return response, nil
144}
145
146func (agent *Agent) deleteFlowsFromAdapter(ctx context.Context, flowsToDel []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000147 logger.Debugw(ctx, "delete-flows-from-adapter", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700148
Maninder9a1bc0d2020-10-26 11:34:02 +0530149 var desc string
150 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
151
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700152 if (len(flowsToDel)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000153 logger.Debugw(ctx, "nothing-to-delete", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700154 return coreutils.DoneResponse(), nil
155 }
156
Maninder9a1bc0d2020-10-26 11:34:02 +0530157 defer agent.logDeviceUpdate(ctx, "deleteFlowsFromAdapter", nil, nil, operStatus, &desc)
158
Kent Hagermancba2f302020-07-28 13:37:36 -0400159 device, err := agent.getDeviceReadOnly(ctx)
160 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530161 desc = err.Error()
Kent Hagermancba2f302020-07-28 13:37:36 -0400162 return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
163 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700164 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
165 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530166 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700167 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
168 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700169 for _, flow := range flowsToDel {
khenaidoo7585a962021-06-10 16:15:38 -0400170 if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700171 // Update the store and cache
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700172 if err := flowHandle.Delete(ctx); err != nil {
173 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530174 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700175 return coreutils.DoneResponse(), err
176 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700177 flowHandle.Unlock()
178 }
179 }
180
181 // Send update to adapters
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000182 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530183 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
184
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700185 response := coreutils.NewResponse()
186 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400187
188 updatedAllFlows := agent.listDeviceFlows()
189 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700190 if err != nil {
191 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530192 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700193 return coreutils.DoneResponse(), err
194 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530195 go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700196 } else {
197 flowChanges := &ofp.FlowChanges{
198 ToAdd: &voltha.Flows{Items: []*ofp.OfpFlowStats{}},
199 ToRemove: &voltha.Flows{Items: flowsToDel},
200 }
201 groupChanges := &ofp.FlowGroupChanges{
202 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
203 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
204 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
205 }
206 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
207 if err != nil {
208 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530209 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700210 return coreutils.DoneResponse(), err
211 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530212 go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700213 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530214 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700215 return response, nil
216}
217
218func (agent *Agent) updateFlowsToAdapter(ctx context.Context, updatedFlows []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530219 logger.Debugw(ctx, "update-flows-to-adapter", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700220
Maninder9a1bc0d2020-10-26 11:34:02 +0530221 var desc string
222 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
223
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700224 if (len(updatedFlows)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000225 logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700226 return coreutils.DoneResponse(), nil
227 }
228
Kent Hagermancba2f302020-07-28 13:37:36 -0400229 device, err := agent.getDeviceReadOnly(ctx)
230 if err != nil {
231 return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
232 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700233 if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300234 desc = "invalid device states"
Maninder9a1bc0d2020-10-26 11:34:02 +0530235 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700236 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states")
237 }
238 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
239 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530240 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
241 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
242
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700243 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
244 }
Kent Hagermana7c9d792020-07-16 17:39:01 -0400245 flowsToAdd := make([]*ofp.OfpFlowStats, 0, len(updatedFlows))
246 flowsToDelete := make([]*ofp.OfpFlowStats, 0, len(updatedFlows))
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700247 for _, flow := range updatedFlows {
khenaidoo7585a962021-06-10 16:15:38 -0400248 if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700249 flowToDelete := flowHandle.GetReadOnly()
250 // Update the store and cache
251 if err := flowHandle.Update(ctx, flow); err != nil {
252 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530253 desc = err.Error()
254 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700255 return coreutils.DoneResponse(), err
256 }
257
258 flowsToDelete = append(flowsToDelete, flowToDelete)
259 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700260 flowHandle.Unlock()
261 }
262 }
263
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000264 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530265 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
266
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700267 response := coreutils.NewResponse()
268 // Process bulk flow update differently than incremental update
269 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400270 updatedAllFlows := agent.listDeviceFlows()
271 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, nil)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700272 if err != nil {
273 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530274 desc = err.Error()
275 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700276 return coreutils.DoneResponse(), err
277 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530278 go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700279 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000280 logger.Debugw(ctx, "updating-flows-and-groups",
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700281 log.Fields{
282 "device-id": agent.deviceID,
283 "flows-to-add": flowsToAdd,
284 "flows-to-delete": flowsToDelete,
285 })
286 // Sanity check
287 if (len(flowsToAdd) | len(flowsToDelete)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000288 logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700289 cancel()
290 return coreutils.DoneResponse(), nil
291 }
292
293 flowChanges := &ofp.FlowChanges{
294 ToAdd: &voltha.Flows{Items: flowsToAdd},
295 ToRemove: &voltha.Flows{Items: flowsToDelete},
296 }
297 groupChanges := &ofp.FlowGroupChanges{
298 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
299 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
300 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
301 }
302 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
303 if err != nil {
304 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530305 desc = err.Error()
306 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700307 return coreutils.DoneResponse(), err
308 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530309 go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700310 }
311
Maninder9a1bc0d2020-10-26 11:34:02 +0530312 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
313 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700314 return response, nil
315}
316
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700317//filterOutFlows removes flows from a device using the uni-port as filter
318func (agent *Agent) filterOutFlows(ctx context.Context, uniPort uint32, flowMetadata *voltha.FlowMetadata) error {
319 var flowsToDelete []*ofp.OfpFlowStats
320 // If an existing flow has the uniPort as an InPort or OutPort or as a Tunnel ID then it needs to be removed
khenaidoo7585a962021-06-10 16:15:38 -0400321 for flowID := range agent.flowCache.ListIDs() {
322 if flowHandle, have := agent.flowCache.Lock(flowID); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700323 flow := flowHandle.GetReadOnly()
324 if flow != nil && (fu.GetInPort(flow) == uniPort || fu.GetOutPort(flow) == uniPort || fu.GetTunnelId(flow) == uint64(uniPort)) {
325 flowsToDelete = append(flowsToDelete, flow)
326 }
327 flowHandle.Unlock()
328 }
329 }
330
Rohan Agrawal31f21802020-06-12 05:38:46 +0000331 logger.Debugw(ctx, "flows-to-delete", log.Fields{"device-id": agent.deviceID, "uni-port": uniPort, "flows": flowsToDelete})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700332 if len(flowsToDelete) == 0 {
333 return nil
334 }
335
336 response, err := agent.deleteFlowsFromAdapter(ctx, flowsToDelete, flowMetadata)
337 if err != nil {
338 return err
339 }
340 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, response); res != nil {
341 return status.Errorf(codes.Aborted, "errors-%s", res)
342 }
343 return nil
344}
345
346//deleteAllFlows deletes all flows in the device table
347func (agent *Agent) deleteAllFlows(ctx context.Context) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000348 logger.Debugw(ctx, "deleteAllFlows", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700349
Maninder9a1bc0d2020-10-26 11:34:02 +0530350 var error string
351 var desc string
352 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
353
354 defer agent.logDeviceUpdate(ctx, "deleteAllFlows", nil, nil, operStatus, &desc)
355
khenaidoo7585a962021-06-10 16:15:38 -0400356 for flowID := range agent.flowCache.ListIDs() {
357 if flowHandle, have := agent.flowCache.Lock(flowID); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700358 // Update the store and cache
359 if err := flowHandle.Delete(ctx); err != nil {
360 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530361 error += fmt.Sprintf("%v ", flowID)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000362 logger.Errorw(ctx, "unable-to-delete-flow", log.Fields{"device-id": agent.deviceID, "flowID": flowID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700363 continue
364 }
365 flowHandle.Unlock()
366 }
367 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530368
369 if error != "" {
370 desc = fmt.Sprintf("Unable to delete flows : %s", error)
371 } else {
372 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
373 }
374
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700375 return nil
376}