blob: f13003b02019cae36205cc5330f4707d72bcc03d [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"
yasin sapli5458a1c2021-06-14 22:24:38 +000025 fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
26 "github.com/opencord/voltha-lib-go/v5/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 }
Maninder2195ccc2021-06-23 20:23:01 +053063
64 if !agent.proceedWithRequest(device) {
65 desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", agent.deviceID)
66 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
67 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
68 }
69
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070070 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
71 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +053072 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
73 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070074 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
75 }
Maninder2195ccc2021-06-23 20:23:01 +053076
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070077 flowsToAdd := make([]*ofp.OfpFlowStats, 0)
78 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
79 for _, flow := range newFlows {
khenaidoo7585a962021-06-10 16:15:38 -040080 flowHandle, created, err := agent.flowCache.LockOrCreate(ctx, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070081 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +053082 desc = err.Error()
83 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070084 return coreutils.DoneResponse(), err
85 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070086 if created {
87 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070088 } else {
89 flowToReplace := flowHandle.GetReadOnly()
90 if !proto.Equal(flowToReplace, flow) {
91 //Flow needs to be updated.
92 if err := flowHandle.Update(ctx, flow); err != nil {
93 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +053094 desc = fmt.Sprintf("failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
95 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -070096 return coreutils.DoneResponse(), status.Errorf(codes.Internal, "failure-updating-flow-%d-to-device-%s", flow.Id, agent.deviceID)
97 }
98 flowsToDelete = append(flowsToDelete, flowToReplace)
99 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700100 } else {
101 //No need to change the flow. It is already exist.
Himani Chawlab4c25912020-11-12 17:16:38 +0530102 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 -0700103 }
104 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700105 flowHandle.Unlock()
106 }
107
108 // Sanity check
109 if (len(flowsToAdd)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000110 logger.Debugw(ctx, "no-flows-to-update", log.Fields{"device-id": agent.deviceID, "flows": newFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700111 return coreutils.DoneResponse(), nil
112 }
113
114 // Send update to adapters
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000115 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530116 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
117
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700118 response := coreutils.NewResponse()
119 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400120
121 updatedAllFlows := agent.listDeviceFlows()
122 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700123 if err != nil {
124 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530125 desc = err.Error()
126 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700127 return coreutils.DoneResponse(), err
128 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530129 go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700130 } else {
131 flowChanges := &ofp.FlowChanges{
132 ToAdd: &voltha.Flows{Items: flowsToAdd},
133 ToRemove: &voltha.Flows{Items: flowsToDelete},
134 }
135 groupChanges := &ofp.FlowGroupChanges{
136 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
137 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
138 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
139 }
140 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
141 if err != nil {
142 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530143 desc = err.Error()
144 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700145 return coreutils.DoneResponse(), err
146 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530147 go agent.waitForAdapterFlowResponse(subCtx, cancel, "addFlowsToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700148 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530149 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
150 agent.logDeviceUpdate(ctx, "addFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700151 return response, nil
152}
153
154func (agent *Agent) deleteFlowsFromAdapter(ctx context.Context, flowsToDel []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000155 logger.Debugw(ctx, "delete-flows-from-adapter", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700156
Maninder9a1bc0d2020-10-26 11:34:02 +0530157 var desc string
158 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
159
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700160 if (len(flowsToDel)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000161 logger.Debugw(ctx, "nothing-to-delete", log.Fields{"device-id": agent.deviceID, "flows": flowsToDel})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700162 return coreutils.DoneResponse(), nil
163 }
164
Maninder9a1bc0d2020-10-26 11:34:02 +0530165 defer agent.logDeviceUpdate(ctx, "deleteFlowsFromAdapter", nil, nil, operStatus, &desc)
166
Kent Hagermancba2f302020-07-28 13:37:36 -0400167 device, err := agent.getDeviceReadOnly(ctx)
168 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530169 desc = err.Error()
Kent Hagermancba2f302020-07-28 13:37:36 -0400170 return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
171 }
Maninder2195ccc2021-06-23 20:23:01 +0530172
173 if !agent.proceedWithRequest(device) {
174 desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
175 agent.logDeviceUpdate(ctx, "deleteFlowsFromAdapter", nil, nil, operStatus, &desc)
176 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
177 }
178
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700179 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
180 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530181 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700182 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
183 }
Maninder2195ccc2021-06-23 20:23:01 +0530184
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700185 for _, flow := range flowsToDel {
khenaidoo7585a962021-06-10 16:15:38 -0400186 if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700187 // Update the store and cache
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700188 if err := flowHandle.Delete(ctx); err != nil {
189 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530190 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700191 return coreutils.DoneResponse(), err
192 }
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700193 flowHandle.Unlock()
194 }
195 }
196
197 // Send update to adapters
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000198 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530199 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
200
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700201 response := coreutils.NewResponse()
202 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400203
204 updatedAllFlows := agent.listDeviceFlows()
205 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, flowMetadata)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700206 if err != nil {
207 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530208 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700209 return coreutils.DoneResponse(), err
210 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530211 go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700212 } else {
213 flowChanges := &ofp.FlowChanges{
214 ToAdd: &voltha.Flows{Items: []*ofp.OfpFlowStats{}},
215 ToRemove: &voltha.Flows{Items: flowsToDel},
216 }
217 groupChanges := &ofp.FlowGroupChanges{
218 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
219 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
220 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
221 }
222 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
223 if err != nil {
224 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530225 desc = err.Error()
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700226 return coreutils.DoneResponse(), err
227 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530228 go agent.waitForAdapterFlowResponse(subCtx, cancel, "deleteFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700229 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530230 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700231 return response, nil
232}
233
234func (agent *Agent) updateFlowsToAdapter(ctx context.Context, updatedFlows []*ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) (coreutils.Response, error) {
Himani Chawlab4c25912020-11-12 17:16:38 +0530235 logger.Debugw(ctx, "update-flows-to-adapter", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700236
Maninder9a1bc0d2020-10-26 11:34:02 +0530237 var desc string
238 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
239
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700240 if (len(updatedFlows)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000241 logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700242 return coreutils.DoneResponse(), nil
243 }
244
Kent Hagermancba2f302020-07-28 13:37:36 -0400245 device, err := agent.getDeviceReadOnly(ctx)
246 if err != nil {
247 return coreutils.DoneResponse(), status.Errorf(codes.Aborted, "%s", err)
248 }
Maninder2195ccc2021-06-23 20:23:01 +0530249
250 if !agent.proceedWithRequest(device) {
251 desc = fmt.Sprintf("deviceId:%s, Cannot complete operation as device deletion is in progress or reconciling is in progress/failed", device.Id)
252 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
253 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "%s", desc)
254 }
255
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700256 if device.OperStatus != voltha.OperStatus_ACTIVE || device.ConnectStatus != voltha.ConnectStatus_REACHABLE || device.AdminState != voltha.AdminState_ENABLED {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300257 desc = "invalid device states"
Maninder9a1bc0d2020-10-26 11:34:02 +0530258 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700259 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "invalid device states")
260 }
Maninder2195ccc2021-06-23 20:23:01 +0530261
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700262 dType, err := agent.adapterMgr.GetDeviceType(ctx, &voltha.ID{Id: device.Type})
263 if err != nil {
Maninder9a1bc0d2020-10-26 11:34:02 +0530264 desc = fmt.Sprintf("non-existent-device-type-%s", device.Type)
265 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
266
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700267 return coreutils.DoneResponse(), status.Errorf(codes.FailedPrecondition, "non-existent-device-type-%s", device.Type)
268 }
Maninder2195ccc2021-06-23 20:23:01 +0530269
Kent Hagermana7c9d792020-07-16 17:39:01 -0400270 flowsToAdd := make([]*ofp.OfpFlowStats, 0, len(updatedFlows))
271 flowsToDelete := make([]*ofp.OfpFlowStats, 0, len(updatedFlows))
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700272 for _, flow := range updatedFlows {
khenaidoo7585a962021-06-10 16:15:38 -0400273 if flowHandle, have := agent.flowCache.Lock(flow.Id); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700274 flowToDelete := flowHandle.GetReadOnly()
275 // Update the store and cache
276 if err := flowHandle.Update(ctx, flow); err != nil {
277 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530278 desc = err.Error()
279 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700280 return coreutils.DoneResponse(), err
281 }
282
283 flowsToDelete = append(flowsToDelete, flowToDelete)
284 flowsToAdd = append(flowsToAdd, flow)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700285 flowHandle.Unlock()
286 }
287 }
288
Rohan Agrawalcf12f202020-08-03 04:42:01 +0000289 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout)
Himani Chawlab4c25912020-11-12 17:16:38 +0530290 subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx)
291
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700292 response := coreutils.NewResponse()
293 // Process bulk flow update differently than incremental update
294 if !dType.AcceptsAddRemoveFlowUpdates {
Kent Hagermana7c9d792020-07-16 17:39:01 -0400295 updatedAllFlows := agent.listDeviceFlows()
296 rpcResponse, err := agent.adapterProxy.UpdateFlowsBulk(subCtx, device, updatedAllFlows, nil, nil)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700297 if err != nil {
298 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530299 desc = err.Error()
300 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700301 return coreutils.DoneResponse(), err
302 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530303 go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700304 } else {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000305 logger.Debugw(ctx, "updating-flows-and-groups",
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700306 log.Fields{
307 "device-id": agent.deviceID,
308 "flows-to-add": flowsToAdd,
309 "flows-to-delete": flowsToDelete,
310 })
311 // Sanity check
312 if (len(flowsToAdd) | len(flowsToDelete)) == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000313 logger.Debugw(ctx, "nothing-to-update", log.Fields{"device-id": agent.deviceID, "flows": updatedFlows})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700314 cancel()
315 return coreutils.DoneResponse(), nil
316 }
317
318 flowChanges := &ofp.FlowChanges{
319 ToAdd: &voltha.Flows{Items: flowsToAdd},
320 ToRemove: &voltha.Flows{Items: flowsToDelete},
321 }
322 groupChanges := &ofp.FlowGroupChanges{
323 ToAdd: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
324 ToRemove: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
325 ToUpdate: &voltha.FlowGroups{Items: []*ofp.OfpGroupEntry{}},
326 }
327 rpcResponse, err := agent.adapterProxy.UpdateFlowsIncremental(subCtx, device, flowChanges, groupChanges, flowMetadata)
328 if err != nil {
329 cancel()
Maninder9a1bc0d2020-10-26 11:34:02 +0530330 desc = err.Error()
331 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700332 return coreutils.DoneResponse(), err
333 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530334 go agent.waitForAdapterFlowResponse(subCtx, cancel, "updateFlowToAdapter", rpcResponse, response)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700335 }
336
Maninder9a1bc0d2020-10-26 11:34:02 +0530337 operStatus.Code = common.OperationResp_OPERATION_IN_PROGRESS
338 agent.logDeviceUpdate(ctx, "updateFlowsToAdapter", nil, nil, operStatus, &desc)
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700339 return response, nil
340}
341
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700342//filterOutFlows removes flows from a device using the uni-port as filter
343func (agent *Agent) filterOutFlows(ctx context.Context, uniPort uint32, flowMetadata *voltha.FlowMetadata) error {
344 var flowsToDelete []*ofp.OfpFlowStats
345 // 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 -0400346 for flowID := range agent.flowCache.ListIDs() {
347 if flowHandle, have := agent.flowCache.Lock(flowID); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700348 flow := flowHandle.GetReadOnly()
349 if flow != nil && (fu.GetInPort(flow) == uniPort || fu.GetOutPort(flow) == uniPort || fu.GetTunnelId(flow) == uint64(uniPort)) {
350 flowsToDelete = append(flowsToDelete, flow)
351 }
352 flowHandle.Unlock()
353 }
354 }
355
Rohan Agrawal31f21802020-06-12 05:38:46 +0000356 logger.Debugw(ctx, "flows-to-delete", log.Fields{"device-id": agent.deviceID, "uni-port": uniPort, "flows": flowsToDelete})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700357 if len(flowsToDelete) == 0 {
358 return nil
359 }
360
361 response, err := agent.deleteFlowsFromAdapter(ctx, flowsToDelete, flowMetadata)
362 if err != nil {
363 return err
364 }
365 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, response); res != nil {
366 return status.Errorf(codes.Aborted, "errors-%s", res)
367 }
368 return nil
369}
370
371//deleteAllFlows deletes all flows in the device table
372func (agent *Agent) deleteAllFlows(ctx context.Context) error {
divyadesaicb8b59d2020-08-18 09:55:47 +0000373 logger.Debugw(ctx, "deleteAllFlows", log.Fields{"device-id": agent.deviceID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700374
Maninder9a1bc0d2020-10-26 11:34:02 +0530375 var error string
376 var desc string
377 operStatus := &common.OperationResp{Code: common.OperationResp_OPERATION_FAILURE}
378
379 defer agent.logDeviceUpdate(ctx, "deleteAllFlows", nil, nil, operStatus, &desc)
380
khenaidoo7585a962021-06-10 16:15:38 -0400381 for flowID := range agent.flowCache.ListIDs() {
382 if flowHandle, have := agent.flowCache.Lock(flowID); have {
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700383 // Update the store and cache
384 if err := flowHandle.Delete(ctx); err != nil {
385 flowHandle.Unlock()
Maninder9a1bc0d2020-10-26 11:34:02 +0530386 error += fmt.Sprintf("%v ", flowID)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000387 logger.Errorw(ctx, "unable-to-delete-flow", log.Fields{"device-id": agent.deviceID, "flowID": flowID})
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700388 continue
389 }
390 flowHandle.Unlock()
391 }
392 }
Maninder9a1bc0d2020-10-26 11:34:02 +0530393
394 if error != "" {
395 desc = fmt.Sprintf("Unable to delete flows : %s", error)
396 } else {
397 operStatus.Code = common.OperationResp_OPERATION_SUCCESS
398 }
399
Mahir Gunyelfa6ea272020-06-10 17:03:51 -0700400 return nil
401}