blob: 6e11e845cd83d5dd55cf6503190ab8c84098dbc6 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar1d86a522019-11-14 17:11:16 +053016
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoob9203542018-09-17 22:56:37 -040018
19import (
20 "context"
Matteo Scandolo360605d2019-11-05 18:29:17 -080021 "encoding/hex"
David Bainbridged1afd662020-03-26 18:27:41 -070022 "sync"
23 "time"
24
khenaidoob9203542018-09-17 22:56:37 -040025 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050026 "github.com/opencord/voltha-go/db/model"
Kent Hagerman433a31a2020-05-20 19:04:48 -040027 "github.com/opencord/voltha-go/rw_core/core/device/flow"
28 "github.com/opencord/voltha-go/rw_core/core/device/group"
Kent Hagermanfa9d6d42020-05-25 11:49:40 -040029 "github.com/opencord/voltha-go/rw_core/core/device/logical_port"
Kent Hagerman433a31a2020-05-20 19:04:48 -040030 "github.com/opencord/voltha-go/rw_core/core/device/meter"
npujar1d86a522019-11-14 17:11:16 +053031 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo442e7c72020-03-10 16:13:48 -040032 "github.com/opencord/voltha-go/rw_core/route"
Scott Bakerb671a862019-10-24 10:53:40 -070033 coreutils "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080034 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
35 "github.com/opencord/voltha-lib-go/v3/pkg/log"
36 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
38 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040041)
42
Kent Hagerman2b216042020-04-03 18:28:56 -040043// LogicalAgent represent attributes of logical device agent
44type LogicalAgent struct {
Kent Hagermanfa9d6d42020-05-25 11:49:40 -040045 logicalDeviceID string
46 serialNumber string
47 rootDeviceID string
48 deviceMgr *Manager
49 ldeviceMgr *LogicalManager
50 ldProxy *model.Proxy
51 stopped bool
52 deviceRoutes *route.DeviceRoutes
53 flowDecomposer *fd.FlowDecomposer
54 defaultTimeout time.Duration
55 logicalDevice *voltha.LogicalDevice
56 requestQueue *coreutils.RequestQueue
57 orderedEvents orderedEvents
58 startOnce sync.Once
59 stopOnce sync.Once
Mahir Gunyeladdb66a2020-04-29 18:08:50 -070060
Kent Hagerman433a31a2020-05-20 19:04:48 -040061 flowLoader *flow.Loader
62 meterLoader *meter.Loader
63 groupLoader *group.Loader
Kent Hagermanfa9d6d42020-05-25 11:49:40 -040064 portLoader *port.Loader
Mahir Gunyeladdb66a2020-04-29 18:08:50 -070065}
66
Kent Hagermanf5a67352020-04-30 15:15:26 -040067func newLogicalAgent(id string, sn string, deviceID string, ldeviceMgr *LogicalManager,
68 deviceMgr *Manager, dbProxy *model.Path, ldProxy *model.Proxy, defaultTimeout time.Duration) *LogicalAgent {
Kent Hagerman433a31a2020-05-20 19:04:48 -040069 agent := &LogicalAgent{
Kent Hagermanf5a67352020-04-30 15:15:26 -040070 logicalDeviceID: id,
71 serialNumber: sn,
72 rootDeviceID: deviceID,
73 deviceMgr: deviceMgr,
74 ldProxy: ldProxy,
75 ldeviceMgr: ldeviceMgr,
76 flowDecomposer: fd.NewFlowDecomposer(deviceMgr),
Kent Hagermanf5a67352020-04-30 15:15:26 -040077 defaultTimeout: defaultTimeout,
78 requestQueue: coreutils.NewRequestQueue(),
Kent Hagerman433a31a2020-05-20 19:04:48 -040079
Kent Hagermanf5a67352020-04-30 15:15:26 -040080 flowLoader: flow.NewLoader(dbProxy.SubPath("logical_flows").Proxy(id)),
81 groupLoader: group.NewLoader(dbProxy.SubPath("logical_groups").Proxy(id)),
82 meterLoader: meter.NewLoader(dbProxy.SubPath("logical_meters").Proxy(id)),
Kent Hagermanfa9d6d42020-05-25 11:49:40 -040083 portLoader: port.NewLoader(dbProxy.SubPath("logical_ports").Proxy(id)),
Kent Hagerman433a31a2020-05-20 19:04:48 -040084 }
khenaidoo0db4c812020-05-27 15:27:30 -040085 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.getDevice)
Kent Hagerman433a31a2020-05-20 19:04:48 -040086 return agent
khenaidoob9203542018-09-17 22:56:37 -040087}
88
khenaidoo4d4802d2018-10-04 21:59:49 -040089// start creates the logical device and add it to the data model
Kent Hagerman2b216042020-04-03 18:28:56 -040090func (agent *LogicalAgent) start(ctx context.Context, loadFromDB bool) error {
khenaidoo442e7c72020-03-10 16:13:48 -040091 needToStart := false
92 if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
93 return nil
94 }
95
Girish Kumarf56a4682020-03-20 20:07:46 +000096 logger.Infow("starting-logical_device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB})
khenaidoo442e7c72020-03-10 16:13:48 -040097
98 var startSucceeded bool
99 defer func() {
100 if !startSucceeded {
101 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000102 logger.Errorw("failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400103 }
104 }
105 }()
106
khenaidoo297cd252019-02-07 22:10:23 -0500107 var ld *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -0400108 if !loadFromDB {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400109 //Build the logical device based on information retrieved from the device adapter
110 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -0500111 var err error
npujar1d86a522019-11-14 17:11:16 +0530112 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400113 return err
114 }
npujar1d86a522019-11-14 17:11:16 +0530115 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500116
117 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
118 var datapathID uint64
Kent Hagerman2b216042020-04-03 18:28:56 -0400119 if datapathID, err = coreutils.CreateDataPathID(agent.serialNumber); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500120 return err
121 }
122 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400123 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
Girish Kumarf56a4682020-03-20 20:07:46 +0000124 logger.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo7e3d8f12019-08-02 16:06:30 -0400125 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500126 ld.Flows = &ofp.Flows{Items: nil}
127 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoo49085352020-01-13 19:15:43 -0500128 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500129
khenaidoo297cd252019-02-07 22:10:23 -0500130 // Save the logical device
Kent Hagermanf5a67352020-04-30 15:15:26 -0400131 if err := agent.ldProxy.Set(ctx, ld.Id, ld); err != nil {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400132 logger.Errorw("failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530133 return err
134 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400135 logger.Debugw("logicaldevice-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500136
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400137 agent.logicalDevice = ld
khenaidoofc1314d2019-03-14 09:34:21 -0400138
khenaidoo442e7c72020-03-10 16:13:48 -0400139 // Setup the logicalports - internal processing, no need to propagate the client context
npujar1d86a522019-11-14 17:11:16 +0530140 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400141 err := agent.setupLogicalPorts(context.Background())
npujar1d86a522019-11-14 17:11:16 +0530142 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000143 logger.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530144 }
145 }()
khenaidoo297cd252019-02-07 22:10:23 -0500146 } else {
147 // load from dB - the logical may not exist at this time. On error, just return and the calling function
148 // will destroy this agent.
Kent Hagerman4f355f52020-03-30 16:01:33 -0400149 ld := &voltha.LogicalDevice{}
Kent Hagermanf5a67352020-04-30 15:15:26 -0400150 have, err := agent.ldProxy.Get(ctx, agent.logicalDeviceID, ld)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530151 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400152 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400153 } else if !have {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500154 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500155 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400156
khenaidoo8c3303d2019-02-13 14:59:39 -0500157 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530158 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400159
khenaidoo6e55d9e2019-12-12 18:26:26 -0500160 // Update the last data
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400161 agent.logicalDevice = ld
khenaidoo6e55d9e2019-12-12 18:26:26 -0500162
Mahir Gunyeladdb66a2020-04-29 18:08:50 -0700163 // load the flows, meters and groups from KV to cache
Kent Hagerman433a31a2020-05-20 19:04:48 -0400164 agent.flowLoader.Load(ctx)
165 agent.meterLoader.Load(ctx)
166 agent.groupLoader.Load(ctx)
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400167 agent.portLoader.Load(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400168 }
khenaidoofc1314d2019-03-14 09:34:21 -0400169
khenaidoo820197c2020-02-13 16:35:33 -0500170 // Setup the device routes. Building routes may fail if the pre-conditions are not satisfied (e.g. no PON ports present)
khenaidoo442e7c72020-03-10 16:13:48 -0400171 if loadFromDB {
khenaidoo820197c2020-02-13 16:35:33 -0500172 go func() {
173 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000174 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -0500175 }
176 }()
khenaidoo4c9e5592019-09-09 16:20:41 -0400177 }
khenaidoo442e7c72020-03-10 16:13:48 -0400178 startSucceeded = true
179
khenaidoob9203542018-09-17 22:56:37 -0400180 return nil
181}
182
khenaidoo442e7c72020-03-10 16:13:48 -0400183// stop stops the logical device agent. This removes the logical device from the data model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400184func (agent *LogicalAgent) stop(ctx context.Context) error {
khenaidoo442e7c72020-03-10 16:13:48 -0400185 var returnErr error
186 agent.stopOnce.Do(func() {
Girish Kumarf56a4682020-03-20 20:07:46 +0000187 logger.Info("stopping-logical_device-agent")
khenaidoo8c3303d2019-02-13 14:59:39 -0500188
khenaidoo442e7c72020-03-10 16:13:48 -0400189 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
190 // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once.
191 returnErr = err
192 return
193 }
194 defer agent.requestQueue.RequestComplete()
195
196 //Remove the logical device from the model
Kent Hagermanf5a67352020-04-30 15:15:26 -0400197 if err := agent.ldProxy.Remove(ctx, agent.logicalDeviceID); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400198 returnErr = err
khenaidoo442e7c72020-03-10 16:13:48 -0400199 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000200 logger.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400201 }
Kent Hagermanfa9d6d42020-05-25 11:49:40 -0400202 // TODO: remove all entries from all loaders
203 // TODO: don't allow any more modifications to flows/groups/meters/ports or to any logical device field
khenaidoo442e7c72020-03-10 16:13:48 -0400204
Kent Hagerman4f355f52020-03-30 16:01:33 -0400205 agent.stopped = true
khenaidoo442e7c72020-03-10 16:13:48 -0400206
Girish Kumarf56a4682020-03-20 20:07:46 +0000207 logger.Info("logical_device-agent-stopped")
khenaidoo442e7c72020-03-10 16:13:48 -0400208 })
209 return returnErr
khenaidoo4d4802d2018-10-04 21:59:49 -0400210}
211
khenaidoo6e55d9e2019-12-12 18:26:26 -0500212// GetLogicalDevice returns the latest logical device data
Kent Hagerman2b216042020-04-03 18:28:56 -0400213func (agent *LogicalAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
khenaidoo442e7c72020-03-10 16:13:48 -0400214 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
215 return nil, err
216 }
217 defer agent.requestQueue.RequestComplete()
218 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400219}
220
khenaidoo0db4c812020-05-27 15:27:30 -0400221func (agent *LogicalAgent) addFlowsAndGroupsToDevices(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000222 logger.Debugw("send-add-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400223
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500224 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530225 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500226 response := coreutils.NewResponse()
227 responses = append(responses, response)
228 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400229 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400230 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400231 start := time.Now()
232 if err := agent.deviceMgr.addFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Matteo Scandolo5bd2f6f2020-08-05 15:27:10 -0700233 logger.Errorw("flow-add-failed", log.Fields{
234 "deviceID": deviceId,
235 "error": err,
236 "wait-time": time.Since(start),
237 "flows": value.ListFlows(),
238 "groups": value.ListGroups(),
239 })
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500240 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400241 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500242 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530243 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -0400244 }
khenaidoo442e7c72020-03-10 16:13:48 -0400245 // Return responses (an array of channels) for the caller to wait for a response from the far end.
246 return responses
khenaidoo0458db62019-06-20 08:50:36 -0400247}
khenaidoo19d7b632018-10-30 10:49:50 -0400248
Matteo Scandolo367162b2020-06-22 15:07:33 -0700249func (agent *LogicalAgent) deleteFlowsAndGroupsFromDevices(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata, mod *ofp.OfpFlowMod) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000250 logger.Debugw("send-delete-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -0400251
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500252 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530253 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500254 response := coreutils.NewResponse()
255 responses = append(responses, response)
256 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400257 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400258 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400259 start := time.Now()
260 if err := agent.deviceMgr.deleteFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Matteo Scandolo367162b2020-06-22 15:07:33 -0700261 logger.Errorw("flows-and-groups-delete-failed", log.Fields{
262 "device-id": deviceId,
263 "error": err,
264 "flow-cookie": mod.Cookie,
265 "wait-time": time.Since(start),
266 })
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500267 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400268 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500269 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530270 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -0400271 }
khenaidoo442e7c72020-03-10 16:13:48 -0400272 return responses
khenaidoo0458db62019-06-20 08:50:36 -0400273}
274
khenaidoo0db4c812020-05-27 15:27:30 -0400275func (agent *LogicalAgent) updateFlowsAndGroupsOfDevice(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000276 logger.Debugw("send-update-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -0400277
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500278 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530279 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500280 response := coreutils.NewResponse()
281 responses = append(responses, response)
282 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400283 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400284 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400285 if err := agent.deviceMgr.updateFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo787224a2020-04-16 18:08:47 -0400286 logger.Errorw("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500287 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400288 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500289 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530290 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -0400291 }
khenaidoo442e7c72020-03-10 16:13:48 -0400292 return responses
khenaidoo19d7b632018-10-30 10:49:50 -0400293}
294
Matteo Scandolo367162b2020-06-22 15:07:33 -0700295func (agent *LogicalAgent) deleteFlowsFromParentDevice(flows map[uint64]*ofp.OfpFlowStats, metadata *voltha.FlowMetadata, mod *ofp.OfpFlowMod) []coreutils.Response {
khenaidoo787224a2020-04-16 18:08:47 -0400296 logger.Debugw("deleting-flows-from-parent-device", log.Fields{"logical-device-id": agent.logicalDeviceID, "flows": flows})
297 responses := make([]coreutils.Response, 0)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400298 for _, flow := range flows {
khenaidoo787224a2020-04-16 18:08:47 -0400299 response := coreutils.NewResponse()
300 responses = append(responses, response)
301 uniPort, err := agent.getUNILogicalPortNo(flow)
302 if err != nil {
303 logger.Error("no-uni-port-in-flow", log.Fields{"deviceID": agent.rootDeviceID, "flow": flow, "error": err})
304 response.Error(err)
305 response.Done()
306 continue
307 }
308 logger.Debugw("uni-port", log.Fields{"flows": flows, "uni-port": uniPort})
309 go func(uniPort uint32, metadata *voltha.FlowMetadata) {
khenaidoo0db4c812020-05-27 15:27:30 -0400310 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo787224a2020-04-16 18:08:47 -0400311 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400312 if err := agent.deviceMgr.deleteParentFlows(subCtx, agent.rootDeviceID, uniPort, metadata); err != nil {
Matteo Scandolo367162b2020-06-22 15:07:33 -0700313 logger.Error("flow-delete-failed-from-parent-device", log.Fields{
314 "device-id": agent.rootDeviceID,
315 "error": err,
316 "flow-cookie": mod.Cookie,
317 })
khenaidoo787224a2020-04-16 18:08:47 -0400318 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s %v", agent.rootDeviceID, err))
319 }
320 response.Done()
321 }(uniPort, metadata)
322 }
323 return responses
324}
325
Kent Hagerman2b216042020-04-03 18:28:56 -0400326func (agent *LogicalAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) {
Matteo Scandolo5bd2f6f2020-08-05 15:27:10 -0700327 if logger.V(log.InfoLevel) {
328 logger.Infow("packet-out", log.Fields{
329 "packet": hex.EncodeToString(packet.Data),
330 "inPort": packet.GetInPort(),
331 })
332 }
khenaidoo68c930b2019-05-13 11:46:51 -0400333 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500334 //frame := packet.GetData()
335 //TODO: Use a channel between the logical agent and the device agent
npujar467fe752020-01-16 20:17:45 +0530336 if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000337 logger.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -0500338 }
khenaidoofdbad6e2018-11-06 22:26:38 -0500339}
340
Kent Hagerman2b216042020-04-03 18:28:56 -0400341func (agent *LogicalAgent) packetIn(port uint32, transactionID string, packet []byte) {
Matteo Scandolo5bd2f6f2020-08-05 15:27:10 -0700342 if logger.V(log.InfoLevel) {
343 logger.Infow("packet-in", log.Fields{
344 "port": port,
345 "packet": hex.EncodeToString(packet),
346 "transactionId": transactionID,
347 })
348 }
khenaidoo68c930b2019-05-13 11:46:51 -0400349 packetIn := fu.MkPacketIn(port, packet)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400350 agent.ldeviceMgr.SendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Girish Kumarf56a4682020-03-20 20:07:46 +0000351 logger.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -0500352}