blob: 7723b74531ab9d540fa21eb6a032765465c2af67 [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"
khenaidoo19d7b632018-10-30 10:49:50 -040022 "fmt"
David Bainbridged1afd662020-03-26 18:27:41 -070023 "sync"
24 "time"
25
khenaidoob9203542018-09-17 22:56:37 -040026 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050027 "github.com/opencord/voltha-go/db/model"
npujar1d86a522019-11-14 17:11:16 +053028 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo442e7c72020-03-10 16:13:48 -040029 "github.com/opencord/voltha-go/rw_core/route"
Scott Bakerb671a862019-10-24 10:53:40 -070030 coreutils "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080031 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
34 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
35 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040036 "google.golang.org/grpc/codes"
37 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040038)
39
Kent Hagerman2b216042020-04-03 18:28:56 -040040// LogicalAgent represent attributes of logical device agent
41type LogicalAgent struct {
npujar1d86a522019-11-14 17:11:16 +053042 logicalDeviceID string
David Bainbridged1afd662020-03-26 18:27:41 -070043 serialNumber string
npujar1d86a522019-11-14 17:11:16 +053044 rootDeviceID string
Kent Hagerman2b216042020-04-03 18:28:56 -040045 deviceMgr *Manager
46 ldeviceMgr *LogicalManager
khenaidoo3306c992019-05-24 16:57:35 -040047 clusterDataProxy *model.Proxy
Kent Hagerman4f355f52020-03-30 16:01:33 -040048 stopped bool
khenaidoo820197c2020-02-13 16:35:33 -050049 deviceRoutes *route.DeviceRoutes
khenaidoo3306c992019-05-24 16:57:35 -040050 logicalPortsNo map[uint32]bool //value is true for NNI port
51 lockLogicalPortsNo sync.RWMutex
52 flowDecomposer *fd.FlowDecomposer
khenaidoo442e7c72020-03-10 16:13:48 -040053 defaultTimeout time.Duration
khenaidoo6e55d9e2019-12-12 18:26:26 -050054 logicalDevice *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -040055 requestQueue *coreutils.RequestQueue
56 startOnce sync.Once
57 stopOnce sync.Once
Mahir Gunyeladdb66a2020-04-29 18:08:50 -070058
59 meters map[uint32]*MeterChunk
60 meterLock sync.RWMutex
61 flows map[uint64]*FlowChunk
62 flowLock sync.RWMutex
63 groups map[uint32]*GroupChunk
64 groupLock sync.RWMutex
65}
66
Kent Hagerman2b216042020-04-03 18:28:56 -040067func newLogicalDeviceAgent(id string, sn string, deviceID string, ldeviceMgr *LogicalManager,
khenaidoo0db4c812020-05-27 15:27:30 -040068 deviceMgr *Manager, cdProxy *model.Proxy, defaultTimeout time.Duration) *LogicalAgent {
Kent Hagerman2b216042020-04-03 18:28:56 -040069 var agent LogicalAgent
npujar1d86a522019-11-14 17:11:16 +053070 agent.logicalDeviceID = id
David Bainbridged1afd662020-03-26 18:27:41 -070071 agent.serialNumber = sn
npujar1d86a522019-11-14 17:11:16 +053072 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040073 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040074 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040075 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040076 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo2c6a0992019-04-29 13:46:56 -040077 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo0db4c812020-05-27 15:27:30 -040078 agent.defaultTimeout = defaultTimeout
Kent Hagerman730cbdf2020-03-31 12:22:08 -040079 agent.requestQueue = coreutils.NewRequestQueue()
Mahir Gunyeladdb66a2020-04-29 18:08:50 -070080 agent.meters = make(map[uint32]*MeterChunk)
81 agent.flows = make(map[uint64]*FlowChunk)
82 agent.groups = make(map[uint32]*GroupChunk)
khenaidoo0db4c812020-05-27 15:27:30 -040083 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.getDevice)
khenaidoob9203542018-09-17 22:56:37 -040084 return &agent
85}
86
khenaidoo4d4802d2018-10-04 21:59:49 -040087// start creates the logical device and add it to the data model
Kent Hagerman2b216042020-04-03 18:28:56 -040088func (agent *LogicalAgent) start(ctx context.Context, loadFromDB bool) error {
khenaidoo442e7c72020-03-10 16:13:48 -040089 needToStart := false
90 if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
91 return nil
92 }
93
Girish Kumarf56a4682020-03-20 20:07:46 +000094 logger.Infow("starting-logical_device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB})
khenaidoo442e7c72020-03-10 16:13:48 -040095
96 var startSucceeded bool
97 defer func() {
98 if !startSucceeded {
99 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000100 logger.Errorw("failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400101 }
102 }
103 }()
104
khenaidoo297cd252019-02-07 22:10:23 -0500105 var ld *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -0400106 if !loadFromDB {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400107 //Build the logical device based on information retrieved from the device adapter
108 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -0500109 var err error
npujar1d86a522019-11-14 17:11:16 +0530110 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400111 return err
112 }
npujar1d86a522019-11-14 17:11:16 +0530113 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500114
115 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
116 var datapathID uint64
Kent Hagerman2b216042020-04-03 18:28:56 -0400117 if datapathID, err = coreutils.CreateDataPathID(agent.serialNumber); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500118 return err
119 }
120 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400121 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
Girish Kumarf56a4682020-03-20 20:07:46 +0000122 logger.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo7e3d8f12019-08-02 16:06:30 -0400123 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500124 ld.Flows = &ofp.Flows{Items: nil}
125 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoo49085352020-01-13 19:15:43 -0500126 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500127
khenaidoo297cd252019-02-07 22:10:23 -0500128 // Save the logical device
Kent Hagerman4f355f52020-03-30 16:01:33 -0400129 if err := agent.clusterDataProxy.AddWithID(ctx, "logical_devices", ld.Id, ld); err != nil {
130 logger.Errorw("failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530131 return err
132 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400133 logger.Debugw("logicaldevice-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500134
135 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoofc1314d2019-03-14 09:34:21 -0400136
khenaidoo442e7c72020-03-10 16:13:48 -0400137 // Setup the logicalports - internal processing, no need to propagate the client context
npujar1d86a522019-11-14 17:11:16 +0530138 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400139 err := agent.setupLogicalPorts(context.Background())
npujar1d86a522019-11-14 17:11:16 +0530140 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000141 logger.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530142 }
143 }()
khenaidoo297cd252019-02-07 22:10:23 -0500144 } else {
145 // load from dB - the logical may not exist at this time. On error, just return and the calling function
146 // will destroy this agent.
Kent Hagerman4f355f52020-03-30 16:01:33 -0400147 ld := &voltha.LogicalDevice{}
148 have, err := agent.clusterDataProxy.Get(ctx, "logical_devices/"+agent.logicalDeviceID, ld)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530149 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400150 return err
Kent Hagerman4f355f52020-03-30 16:01:33 -0400151 } else if !have {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500152 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500153 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400154
khenaidoo8c3303d2019-02-13 14:59:39 -0500155 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530156 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400157
khenaidoo6e55d9e2019-12-12 18:26:26 -0500158 // Update the last data
159 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
160
khenaidoo3d3b8c22019-05-22 18:10:39 -0400161 // Setup the local list of logical ports
162 agent.addLogicalPortsToMap(ld.Ports)
Mahir Gunyeladdb66a2020-04-29 18:08:50 -0700163 // load the flows, meters and groups from KV to cache
164 agent.loadFlows(ctx)
165 agent.loadMeters(ctx)
166 agent.loadGroups(ctx)
khenaidoob9203542018-09-17 22:56:37 -0400167 }
khenaidoofc1314d2019-03-14 09:34:21 -0400168
khenaidoo820197c2020-02-13 16:35:33 -0500169 // 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 -0400170 if loadFromDB {
khenaidoo820197c2020-02-13 16:35:33 -0500171 go func() {
172 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000173 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -0500174 }
175 }()
khenaidoo4c9e5592019-09-09 16:20:41 -0400176 }
khenaidoo442e7c72020-03-10 16:13:48 -0400177 startSucceeded = true
178
khenaidoob9203542018-09-17 22:56:37 -0400179 return nil
180}
181
khenaidoo442e7c72020-03-10 16:13:48 -0400182// stop stops the logical device agent. This removes the logical device from the data model.
Kent Hagerman2b216042020-04-03 18:28:56 -0400183func (agent *LogicalAgent) stop(ctx context.Context) error {
khenaidoo442e7c72020-03-10 16:13:48 -0400184 var returnErr error
185 agent.stopOnce.Do(func() {
Girish Kumarf56a4682020-03-20 20:07:46 +0000186 logger.Info("stopping-logical_device-agent")
khenaidoo8c3303d2019-02-13 14:59:39 -0500187
khenaidoo442e7c72020-03-10 16:13:48 -0400188 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
189 // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once.
190 returnErr = err
191 return
192 }
193 defer agent.requestQueue.RequestComplete()
194
195 //Remove the logical device from the model
Kent Hagerman4f355f52020-03-30 16:01:33 -0400196 if err := agent.clusterDataProxy.Remove(ctx, "logical_devices/"+agent.logicalDeviceID); err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400197 returnErr = err
khenaidoo442e7c72020-03-10 16:13:48 -0400198 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000199 logger.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400200 }
201
Kent Hagerman4f355f52020-03-30 16:01:33 -0400202 agent.stopped = true
khenaidoo442e7c72020-03-10 16:13:48 -0400203
Girish Kumarf56a4682020-03-20 20:07:46 +0000204 logger.Info("logical_device-agent-stopped")
khenaidoo442e7c72020-03-10 16:13:48 -0400205 })
206 return returnErr
khenaidoo4d4802d2018-10-04 21:59:49 -0400207}
208
khenaidoo6e55d9e2019-12-12 18:26:26 -0500209// GetLogicalDevice returns the latest logical device data
Kent Hagerman2b216042020-04-03 18:28:56 -0400210func (agent *LogicalAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
khenaidoo442e7c72020-03-10 16:13:48 -0400211 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
212 return nil, err
213 }
214 defer agent.requestQueue.RequestComplete()
215 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400216}
217
khenaidoo6e55d9e2019-12-12 18:26:26 -0500218// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
Kent Hagerman2b216042020-04-03 18:28:56 -0400219func (agent *LogicalAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
Girish Kumarf56a4682020-03-20 20:07:46 +0000220 logger.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500221 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400222}
223
khenaidoo92e62c52018-10-03 14:02:54 -0400224//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
Kent Hagerman2b216042020-04-03 18:28:56 -0400225func (agent *LogicalAgent) updateLogicalDeviceWithoutLock(ctx context.Context, logicalDevice *voltha.LogicalDevice) error {
Kent Hagerman4f355f52020-03-30 16:01:33 -0400226 if agent.stopped {
Mahir Gunyeladdb66a2020-04-29 18:08:50 -0700227 return fmt.Errorf("logical device agent stopped-%s", logicalDevice.Id)
Kent Hagerman4f355f52020-03-30 16:01:33 -0400228 }
229
npujar467fe752020-01-16 20:17:45 +0530230 updateCtx := context.WithValue(ctx, model.RequestTimestamp, time.Now().UnixNano())
Kent Hagerman4f355f52020-03-30 16:01:33 -0400231 if err := agent.clusterDataProxy.Update(updateCtx, "logical_devices/"+agent.logicalDeviceID, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000232 logger.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530233 return err
234 }
Kent Hagerman4f355f52020-03-30 16:01:33 -0400235
khenaidoo442e7c72020-03-10 16:13:48 -0400236 agent.logicalDevice = logicalDevice
237
khenaidoo92e62c52018-10-03 14:02:54 -0400238 return nil
239}
240
Mahir Gunyeladdb66a2020-04-29 18:08:50 -0700241func (agent *LogicalAgent) deleteFlowAndUpdateMeterStats(ctx context.Context, mod *ofp.OfpFlowMod, chunk *FlowChunk) error {
242 chunk.lock.Lock()
243 defer chunk.lock.Unlock()
244 if changedMeter := agent.updateFlowCountOfMeterStats(ctx, mod, chunk.flow, false); !changedMeter {
245 return fmt.Errorf("Cannot-delete-flow-%s. Meter-update-failed", chunk.flow)
246 }
247 // Update store and cache
248 if err := agent.removeLogicalDeviceFlow(ctx, chunk.flow.Id); err != nil {
249 return fmt.Errorf("Cannot-delete-flows-%s. Delete-from-store-failed", chunk.flow)
250 }
251 return nil
252}
253
khenaidoo0db4c812020-05-27 15:27:30 -0400254func (agent *LogicalAgent) addFlowsAndGroupsToDevices(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000255 logger.Debugw("send-add-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -0400256
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500257 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530258 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500259 response := coreutils.NewResponse()
260 responses = append(responses, response)
261 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400262 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400263 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400264 start := time.Now()
265 if err := agent.deviceMgr.addFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
266 logger.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err, "wait-time": time.Since(start)})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500267 response.Error(status.Errorf(codes.Internal, "flow-add-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)
khenaidoo19d7b632018-10-30 10:49:50 -0400271 }
khenaidoo442e7c72020-03-10 16:13:48 -0400272 // Return responses (an array of channels) for the caller to wait for a response from the far end.
273 return responses
khenaidoo0458db62019-06-20 08:50:36 -0400274}
khenaidoo19d7b632018-10-30 10:49:50 -0400275
khenaidoo0db4c812020-05-27 15:27:30 -0400276func (agent *LogicalAgent) deleteFlowsAndGroupsFromDevices(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000277 logger.Debugw("send-delete-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -0400278
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500279 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530280 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500281 response := coreutils.NewResponse()
282 responses = append(responses, response)
283 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400284 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400285 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400286 start := time.Now()
287 if err := agent.deviceMgr.deleteFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
288 logger.Errorw("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err, "wait-time": time.Since(start)})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500289 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400290 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500291 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530292 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -0400293 }
khenaidoo442e7c72020-03-10 16:13:48 -0400294 return responses
khenaidoo0458db62019-06-20 08:50:36 -0400295}
296
khenaidoo0db4c812020-05-27 15:27:30 -0400297func (agent *LogicalAgent) updateFlowsAndGroupsOfDevice(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +0000298 logger.Debugw("send-update-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -0400299
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500300 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +0530301 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500302 response := coreutils.NewResponse()
303 responses = append(responses, response)
304 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo0db4c812020-05-27 15:27:30 -0400305 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo442e7c72020-03-10 16:13:48 -0400306 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400307 if err := agent.deviceMgr.updateFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo787224a2020-04-16 18:08:47 -0400308 logger.Errorw("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500309 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -0400310 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500311 response.Done()
npujar1d86a522019-11-14 17:11:16 +0530312 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -0400313 }
khenaidoo442e7c72020-03-10 16:13:48 -0400314 return responses
khenaidoo19d7b632018-10-30 10:49:50 -0400315}
316
khenaidoo0db4c812020-05-27 15:27:30 -0400317func (agent *LogicalAgent) deleteFlowsFromParentDevice(flows ofp.Flows, metadata *voltha.FlowMetadata) []coreutils.Response {
khenaidoo787224a2020-04-16 18:08:47 -0400318 logger.Debugw("deleting-flows-from-parent-device", log.Fields{"logical-device-id": agent.logicalDeviceID, "flows": flows})
319 responses := make([]coreutils.Response, 0)
320 for _, flow := range flows.Items {
321 response := coreutils.NewResponse()
322 responses = append(responses, response)
323 uniPort, err := agent.getUNILogicalPortNo(flow)
324 if err != nil {
325 logger.Error("no-uni-port-in-flow", log.Fields{"deviceID": agent.rootDeviceID, "flow": flow, "error": err})
326 response.Error(err)
327 response.Done()
328 continue
329 }
330 logger.Debugw("uni-port", log.Fields{"flows": flows, "uni-port": uniPort})
331 go func(uniPort uint32, metadata *voltha.FlowMetadata) {
khenaidoo0db4c812020-05-27 15:27:30 -0400332 subCtx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
khenaidoo787224a2020-04-16 18:08:47 -0400333 defer cancel()
khenaidoo0db4c812020-05-27 15:27:30 -0400334 if err := agent.deviceMgr.deleteParentFlows(subCtx, agent.rootDeviceID, uniPort, metadata); err != nil {
khenaidoo787224a2020-04-16 18:08:47 -0400335 logger.Error("flow-delete-failed", log.Fields{"device-id": agent.rootDeviceID, "error": err})
336 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s %v", agent.rootDeviceID, err))
337 }
338 response.Done()
339 }(uniPort, metadata)
340 }
341 return responses
342}
343
Kent Hagerman2b216042020-04-03 18:28:56 -0400344func (agent *LogicalAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000345 logger.Debugw("packet-out", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -0800346 "packet": hex.EncodeToString(packet.Data),
347 "inPort": packet.GetInPort(),
348 })
khenaidoo68c930b2019-05-13 11:46:51 -0400349 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -0500350 //frame := packet.GetData()
351 //TODO: Use a channel between the logical agent and the device agent
npujar467fe752020-01-16 20:17:45 +0530352 if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000353 logger.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -0500354 }
khenaidoofdbad6e2018-11-06 22:26:38 -0500355}
356
Kent Hagerman2b216042020-04-03 18:28:56 -0400357func (agent *LogicalAgent) packetIn(port uint32, transactionID string, packet []byte) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000358 logger.Debugw("packet-in", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -0800359 "port": port,
360 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +0530361 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -0800362 })
khenaidoo68c930b2019-05-13 11:46:51 -0400363 packetIn := fu.MkPacketIn(port, packet)
Kent Hagerman45a13e42020-04-13 12:23:50 -0400364 agent.ldeviceMgr.SendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Girish Kumarf56a4682020-03-20 20:07:46 +0000365 logger.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -0500366}