khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 1 | /* |
| 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 | */ |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 16 | |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 17 | package device |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 18 | |
| 19 | import ( |
| 20 | "context" |
Matteo Scandolo | 360605d | 2019-11-05 18:29:17 -0800 | [diff] [blame] | 21 | "encoding/hex" |
David Bainbridge | d1afd66 | 2020-03-26 18:27:41 -0700 | [diff] [blame] | 22 | "sync" |
| 23 | "time" |
| 24 | |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 25 | "github.com/gogo/protobuf/proto" |
sbarbari | 17d7e22 | 2019-11-05 10:02:29 -0500 | [diff] [blame] | 26 | "github.com/opencord/voltha-go/db/model" |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 27 | "github.com/opencord/voltha-go/rw_core/core/device/flow" |
| 28 | "github.com/opencord/voltha-go/rw_core/core/device/group" |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 29 | "github.com/opencord/voltha-go/rw_core/core/device/logical_port" |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 30 | "github.com/opencord/voltha-go/rw_core/core/device/meter" |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 31 | fd "github.com/opencord/voltha-go/rw_core/flowdecomposition" |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 32 | "github.com/opencord/voltha-go/rw_core/route" |
Scott Baker | b671a86 | 2019-10-24 10:53:40 -0700 | [diff] [blame] | 33 | coreutils "github.com/opencord/voltha-go/rw_core/utils" |
Maninder | dfadc98 | 2020-10-28 14:04:33 +0530 | [diff] [blame] | 34 | fu "github.com/opencord/voltha-lib-go/v4/pkg/flows" |
| 35 | "github.com/opencord/voltha-lib-go/v4/pkg/log" |
| 36 | ic "github.com/opencord/voltha-protos/v4/go/inter_container" |
| 37 | ofp "github.com/opencord/voltha-protos/v4/go/openflow_13" |
| 38 | "github.com/opencord/voltha-protos/v4/go/voltha" |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 39 | "google.golang.org/grpc/codes" |
| 40 | "google.golang.org/grpc/status" |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 41 | ) |
| 42 | |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 43 | // LogicalAgent represent attributes of logical device agent |
| 44 | type LogicalAgent struct { |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 45 | 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 Gunyel | addb66a | 2020-04-29 18:08:50 -0700 | [diff] [blame] | 60 | |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 61 | flowLoader *flow.Loader |
| 62 | meterLoader *meter.Loader |
| 63 | groupLoader *group.Loader |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 64 | portLoader *port.Loader |
Mahir Gunyel | addb66a | 2020-04-29 18:08:50 -0700 | [diff] [blame] | 65 | } |
| 66 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 67 | func newLogicalAgent(ctx context.Context, id string, sn string, deviceID string, ldeviceMgr *LogicalManager, |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 68 | deviceMgr *Manager, dbProxy *model.Path, ldProxy *model.Proxy, defaultTimeout time.Duration) *LogicalAgent { |
Kent Hagerman | 2a07b86 | 2020-06-19 15:23:07 -0400 | [diff] [blame] | 69 | return &LogicalAgent{ |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 70 | logicalDeviceID: id, |
| 71 | serialNumber: sn, |
| 72 | rootDeviceID: deviceID, |
| 73 | deviceMgr: deviceMgr, |
| 74 | ldProxy: ldProxy, |
| 75 | ldeviceMgr: ldeviceMgr, |
Kent Hagerman | 2a07b86 | 2020-06-19 15:23:07 -0400 | [diff] [blame] | 76 | deviceRoutes: route.NewDeviceRoutes(id, deviceID, deviceMgr.listDevicePorts), |
Kent Hagerman | 6031aad | 2020-07-29 16:36:33 -0400 | [diff] [blame] | 77 | flowDecomposer: fd.NewFlowDecomposer(deviceMgr.getDeviceReadOnly), |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 78 | defaultTimeout: defaultTimeout, |
| 79 | requestQueue: coreutils.NewRequestQueue(), |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 80 | |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 81 | flowLoader: flow.NewLoader(dbProxy.SubPath("logical_flows").Proxy(id)), |
| 82 | groupLoader: group.NewLoader(dbProxy.SubPath("logical_groups").Proxy(id)), |
| 83 | meterLoader: meter.NewLoader(dbProxy.SubPath("logical_meters").Proxy(id)), |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 84 | portLoader: port.NewLoader(dbProxy.SubPath("logical_ports").Proxy(id)), |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 85 | } |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 86 | } |
| 87 | |
khenaidoo | 4d4802d | 2018-10-04 21:59:49 -0400 | [diff] [blame] | 88 | // start creates the logical device and add it to the data model |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 89 | func (agent *LogicalAgent) start(ctx context.Context, loadFromDB bool) error { |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 90 | needToStart := false |
| 91 | if agent.startOnce.Do(func() { needToStart = true }); !needToStart { |
| 92 | return nil |
| 93 | } |
| 94 | |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 95 | logger.Infow(ctx, "starting-logical-device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB}) |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 96 | |
| 97 | var startSucceeded bool |
| 98 | defer func() { |
| 99 | if !startSucceeded { |
| 100 | if err := agent.stop(ctx); err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 101 | logger.Errorw(ctx, "failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err}) |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 102 | } |
| 103 | } |
| 104 | }() |
| 105 | |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 106 | var ld *voltha.LogicalDevice |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 107 | if !loadFromDB { |
khenaidoo | 7e3d8f1 | 2019-08-02 16:06:30 -0400 | [diff] [blame] | 108 | //Build the logical device based on information retrieved from the device adapter |
| 109 | var switchCap *ic.SwitchCapability |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 110 | var err error |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 111 | if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil { |
khenaidoo | 7e3d8f1 | 2019-08-02 16:06:30 -0400 | [diff] [blame] | 112 | return err |
| 113 | } |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 114 | ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID} |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 115 | |
| 116 | // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address) |
| 117 | var datapathID uint64 |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 118 | if datapathID, err = coreutils.CreateDataPathID(agent.serialNumber); err != nil { |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 119 | return err |
| 120 | } |
| 121 | ld.DatapathId = datapathID |
khenaidoo | 7e3d8f1 | 2019-08-02 16:06:30 -0400 | [diff] [blame] | 122 | ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc) |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 123 | logger.Debugw(ctx, "Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc}) |
khenaidoo | 7e3d8f1 | 2019-08-02 16:06:30 -0400 | [diff] [blame] | 124 | ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures) |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 125 | |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 126 | // Save the logical device |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 127 | if err := agent.ldProxy.Set(ctx, ld.Id, ld); err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 128 | logger.Errorw(ctx, "failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID}) |
Thomas Lee S | e5a4401 | 2019-11-07 20:32:24 +0530 | [diff] [blame] | 129 | return err |
| 130 | } |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 131 | logger.Debugw(ctx, "logical-device-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId}) |
khenaidoo | 6e55d9e | 2019-12-12 18:26:26 -0500 | [diff] [blame] | 132 | |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 133 | agent.logicalDevice = ld |
khenaidoo | fc1314d | 2019-03-14 09:34:21 -0400 | [diff] [blame] | 134 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 135 | // Setup the logicalports - internal processing, no need to propagate the client context |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 136 | go func() { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 137 | subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx) |
| 138 | err := agent.setupLogicalPorts(subCtx) |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 139 | if err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 140 | logger.Errorw(ctx, "unable-to-setup-logical-ports", log.Fields{"error": err}) |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 141 | } |
| 142 | }() |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 143 | } else { |
| 144 | // load from dB - the logical may not exist at this time. On error, just return and the calling function |
| 145 | // will destroy this agent. |
Kent Hagerman | 4f355f5 | 2020-03-30 16:01:33 -0400 | [diff] [blame] | 146 | ld := &voltha.LogicalDevice{} |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 147 | have, err := agent.ldProxy.Get(ctx, agent.logicalDeviceID, ld) |
Thomas Lee S | e5a4401 | 2019-11-07 20:32:24 +0530 | [diff] [blame] | 148 | if err != nil { |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 149 | return err |
Kent Hagerman | 4f355f5 | 2020-03-30 16:01:33 -0400 | [diff] [blame] | 150 | } else if !have { |
khenaidoo | 6e55d9e | 2019-12-12 18:26:26 -0500 | [diff] [blame] | 151 | return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID) |
khenaidoo | 297cd25 | 2019-02-07 22:10:23 -0500 | [diff] [blame] | 152 | } |
Kent Hagerman | 4f355f5 | 2020-03-30 16:01:33 -0400 | [diff] [blame] | 153 | |
khenaidoo | 8c3303d | 2019-02-13 14:59:39 -0500 | [diff] [blame] | 154 | // Update the root device Id |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 155 | agent.rootDeviceID = ld.RootDeviceId |
khenaidoo | 3d3b8c2 | 2019-05-22 18:10:39 -0400 | [diff] [blame] | 156 | |
khenaidoo | 6e55d9e | 2019-12-12 18:26:26 -0500 | [diff] [blame] | 157 | // Update the last data |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 158 | agent.logicalDevice = ld |
khenaidoo | 6e55d9e | 2019-12-12 18:26:26 -0500 | [diff] [blame] | 159 | |
Kent Hagerman | 2a07b86 | 2020-06-19 15:23:07 -0400 | [diff] [blame] | 160 | // now that the root device is known, create DeviceRoutes with it |
| 161 | agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.rootDeviceID, agent.deviceMgr.listDevicePorts) |
| 162 | |
Mahir Gunyel | addb66a | 2020-04-29 18:08:50 -0700 | [diff] [blame] | 163 | // load the flows, meters and groups from KV to cache |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 164 | agent.flowLoader.Load(ctx) |
| 165 | agent.meterLoader.Load(ctx) |
| 166 | agent.groupLoader.Load(ctx) |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 167 | agent.portLoader.Load(ctx) |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 168 | } |
khenaidoo | fc1314d | 2019-03-14 09:34:21 -0400 | [diff] [blame] | 169 | |
khenaidoo | 820197c | 2020-02-13 16:35:33 -0500 | [diff] [blame] | 170 | // Setup the device routes. Building routes may fail if the pre-conditions are not satisfied (e.g. no PON ports present) |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 171 | if loadFromDB { |
khenaidoo | 820197c | 2020-02-13 16:35:33 -0500 | [diff] [blame] | 172 | go func() { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 173 | subCtx := coreutils.WithSpanAndRPCMetadataFromContext(ctx) |
| 174 | if err := agent.buildRoutes(subCtx); err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 175 | logger.Warn(ctx, "routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err}) |
khenaidoo | 820197c | 2020-02-13 16:35:33 -0500 | [diff] [blame] | 176 | } |
| 177 | }() |
khenaidoo | 4c9e559 | 2019-09-09 16:20:41 -0400 | [diff] [blame] | 178 | } |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 179 | startSucceeded = true |
| 180 | |
khenaidoo | b920354 | 2018-09-17 22:56:37 -0400 | [diff] [blame] | 181 | return nil |
| 182 | } |
| 183 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 184 | // stop stops the logical device agent. This removes the logical device from the data model. |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 185 | func (agent *LogicalAgent) stop(ctx context.Context) error { |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 186 | var returnErr error |
| 187 | agent.stopOnce.Do(func() { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 188 | logger.Info(ctx, "stopping-logical-device-agent") |
khenaidoo | 8c3303d | 2019-02-13 14:59:39 -0500 | [diff] [blame] | 189 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 190 | if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil { |
| 191 | // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once. |
| 192 | returnErr = err |
| 193 | return |
| 194 | } |
| 195 | defer agent.requestQueue.RequestComplete() |
Himani Chawla | 40af270 | 2021-01-27 15:06:30 +0530 | [diff] [blame] | 196 | subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout) |
| 197 | // Before deletion of the logical agent, make sure all events for ldagent are sent to avoid race conditions |
| 198 | if err := agent.orderedEvents.waitForAllEventsToBeSent(subCtx, cancel); err != nil { |
| 199 | //Log the error here |
| 200 | logger.Errorw(ctx, "failed-to-send-all-events-on-the-logical-device-before-deletion", |
| 201 | log.Fields{"error": err, "logical-device-id": agent.logicalDeviceID}) |
| 202 | } |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 203 | //Remove the logical device from the model |
Kent Hagerman | f5a6735 | 2020-04-30 15:15:26 -0400 | [diff] [blame] | 204 | if err := agent.ldProxy.Remove(ctx, agent.logicalDeviceID); err != nil { |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 205 | returnErr = err |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 206 | } else { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 207 | logger.Debugw(ctx, "logical-device-removed", log.Fields{"logical-device-id": agent.logicalDeviceID}) |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 208 | } |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 209 | // TODO: remove all entries from all loaders |
| 210 | // TODO: don't allow any more modifications to flows/groups/meters/ports or to any logical device field |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 211 | |
Kent Hagerman | 4f355f5 | 2020-03-30 16:01:33 -0400 | [diff] [blame] | 212 | agent.stopped = true |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 213 | |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 214 | logger.Info(ctx, "logical-device-agent-stopped") |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 215 | }) |
| 216 | return returnErr |
khenaidoo | 4d4802d | 2018-10-04 21:59:49 -0400 | [diff] [blame] | 217 | } |
| 218 | |
Kent Hagerman | cba2f30 | 2020-07-28 13:37:36 -0400 | [diff] [blame] | 219 | // GetLogicalDeviceReadOnly returns the latest logical device data |
| 220 | func (agent *LogicalAgent) GetLogicalDeviceReadOnly(ctx context.Context) (*voltha.LogicalDevice, error) { |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 221 | if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil { |
| 222 | return nil, err |
| 223 | } |
| 224 | defer agent.requestQueue.RequestComplete() |
Kent Hagerman | cba2f30 | 2020-07-28 13:37:36 -0400 | [diff] [blame] | 225 | return agent.logicalDevice, nil |
khenaidoo | 92e62c5 | 2018-10-03 14:02:54 -0400 | [diff] [blame] | 226 | } |
| 227 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 228 | func (agent *LogicalAgent) addFlowsAndGroupsToDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 229 | logger.Debugw(ctx, "send-add-flows-to-device-manager", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-rules": deviceRules, "flow-metadata": flowMetadata}) |
khenaidoo | 19d7b63 | 2018-10-30 10:49:50 -0400 | [diff] [blame] | 230 | |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 231 | responses := make([]coreutils.Response, 0) |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 232 | for deviceID, value := range deviceRules.GetRules() { |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 233 | response := coreutils.NewResponse() |
| 234 | responses = append(responses, response) |
| 235 | go func(deviceId string, value *fu.FlowsAndGroups) { |
Rohan Agrawal | cf12f20 | 2020-08-03 04:42:01 +0000 | [diff] [blame] | 236 | subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout) |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 237 | subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx) |
| 238 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 239 | defer cancel() |
khenaidoo | 0db4c81 | 2020-05-27 15:27:30 -0400 | [diff] [blame] | 240 | start := time.Now() |
| 241 | if err := agent.deviceMgr.addFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil { |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 242 | logger.Errorw(ctx, "flow-add-failed", log.Fields{ |
divyadesai | cb8b59d | 2020-08-18 09:55:47 +0000 | [diff] [blame] | 243 | "device-id": deviceId, |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 244 | "error": err, |
| 245 | "wait-time": time.Since(start), |
| 246 | "flows": value.ListFlows(), |
| 247 | "groups": value.ListGroups(), |
| 248 | }) |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 249 | response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId)) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 250 | } |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 251 | response.Done() |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 252 | }(deviceID, value) |
khenaidoo | 19d7b63 | 2018-10-30 10:49:50 -0400 | [diff] [blame] | 253 | } |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 254 | // Return responses (an array of channels) for the caller to wait for a response from the far end. |
| 255 | return responses |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 256 | } |
khenaidoo | 19d7b63 | 2018-10-30 10:49:50 -0400 | [diff] [blame] | 257 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 258 | func (agent *LogicalAgent) deleteFlowsAndGroupsFromDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata, mod *ofp.OfpFlowMod) []coreutils.Response { |
divyadesai | cb8b59d | 2020-08-18 09:55:47 +0000 | [diff] [blame] | 259 | logger.Debugw(ctx, "send-delete-flows-to-device-manager", log.Fields{"logical-device-id": agent.logicalDeviceID}) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 260 | |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 261 | responses := make([]coreutils.Response, 0) |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 262 | for deviceID, value := range deviceRules.GetRules() { |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 263 | response := coreutils.NewResponse() |
| 264 | responses = append(responses, response) |
| 265 | go func(deviceId string, value *fu.FlowsAndGroups) { |
Rohan Agrawal | cf12f20 | 2020-08-03 04:42:01 +0000 | [diff] [blame] | 266 | subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout) |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 267 | subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx) |
| 268 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 269 | defer cancel() |
khenaidoo | 0db4c81 | 2020-05-27 15:27:30 -0400 | [diff] [blame] | 270 | start := time.Now() |
| 271 | if err := agent.deviceMgr.deleteFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 272 | logger.Errorw(ctx, "flows-and-groups-delete-failed", log.Fields{ |
Matteo Scandolo | 367162b | 2020-06-22 15:07:33 -0700 | [diff] [blame] | 273 | "device-id": deviceId, |
| 274 | "error": err, |
| 275 | "flow-cookie": mod.Cookie, |
| 276 | "wait-time": time.Since(start), |
| 277 | }) |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 278 | response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId)) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 279 | } |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 280 | response.Done() |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 281 | }(deviceID, value) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 282 | } |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 283 | return responses |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 284 | } |
| 285 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 286 | func (agent *LogicalAgent) updateFlowsAndGroupsOfDevice(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response { |
divyadesai | cb8b59d | 2020-08-18 09:55:47 +0000 | [diff] [blame] | 287 | logger.Debugw(ctx, "send-update-flows-to-device-manager", log.Fields{"logical-device-id": agent.logicalDeviceID}) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 288 | |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 289 | responses := make([]coreutils.Response, 0) |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 290 | for deviceID, value := range deviceRules.GetRules() { |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 291 | response := coreutils.NewResponse() |
| 292 | responses = append(responses, response) |
| 293 | go func(deviceId string, value *fu.FlowsAndGroups) { |
Rohan Agrawal | cf12f20 | 2020-08-03 04:42:01 +0000 | [diff] [blame] | 294 | subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout) |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 295 | subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx) |
| 296 | |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 297 | defer cancel() |
khenaidoo | 0db4c81 | 2020-05-27 15:27:30 -0400 | [diff] [blame] | 298 | if err := agent.deviceMgr.updateFlowsAndGroups(subCtx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil { |
divyadesai | cb8b59d | 2020-08-18 09:55:47 +0000 | [diff] [blame] | 299 | logger.Errorw(ctx, "flow-update-failed", log.Fields{"device-id": deviceId, "error": err}) |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 300 | response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId)) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 301 | } |
Kent Hagerman | 8da2f1e | 2019-11-25 17:28:09 -0500 | [diff] [blame] | 302 | response.Done() |
npujar | 1d86a52 | 2019-11-14 17:11:16 +0530 | [diff] [blame] | 303 | }(deviceID, value) |
khenaidoo | 0458db6 | 2019-06-20 08:50:36 -0400 | [diff] [blame] | 304 | } |
khenaidoo | 442e7c7 | 2020-03-10 16:13:48 -0400 | [diff] [blame] | 305 | return responses |
khenaidoo | 19d7b63 | 2018-10-30 10:49:50 -0400 | [diff] [blame] | 306 | } |
| 307 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 308 | func (agent *LogicalAgent) deleteFlowsFromParentDevice(ctx context.Context, flows map[uint64]*ofp.OfpFlowStats, metadata *voltha.FlowMetadata, mod *ofp.OfpFlowMod) []coreutils.Response { |
| 309 | logger.Debugw(ctx, "deleting-flows-from-parent-device", log.Fields{"logical-device-id": agent.logicalDeviceID, "flows": flows}) |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 310 | responses := make([]coreutils.Response, 0) |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 311 | for _, flow := range flows { |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 312 | response := coreutils.NewResponse() |
| 313 | responses = append(responses, response) |
| 314 | uniPort, err := agent.getUNILogicalPortNo(flow) |
| 315 | if err != nil { |
divyadesai | cb8b59d | 2020-08-18 09:55:47 +0000 | [diff] [blame] | 316 | logger.Error(ctx, "no-uni-port-in-flow", log.Fields{"device-id": agent.rootDeviceID, "flow": flow, "error": err}) |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 317 | response.Error(err) |
| 318 | response.Done() |
| 319 | continue |
| 320 | } |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 321 | logger.Debugw(ctx, "uni-port", log.Fields{"flows": flows, "uni-port": uniPort}) |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 322 | go func(uniPort uint32, metadata *voltha.FlowMetadata) { |
Rohan Agrawal | cf12f20 | 2020-08-03 04:42:01 +0000 | [diff] [blame] | 323 | subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), agent.defaultTimeout) |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 324 | subCtx = coreutils.WithRPCMetadataFromContext(subCtx, ctx) |
| 325 | |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 326 | defer cancel() |
khenaidoo | 0db4c81 | 2020-05-27 15:27:30 -0400 | [diff] [blame] | 327 | if err := agent.deviceMgr.deleteParentFlows(subCtx, agent.rootDeviceID, uniPort, metadata); err != nil { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 328 | logger.Error(ctx, "flow-delete-failed-from-parent-device", log.Fields{ |
Matteo Scandolo | 367162b | 2020-06-22 15:07:33 -0700 | [diff] [blame] | 329 | "device-id": agent.rootDeviceID, |
| 330 | "error": err, |
| 331 | "flow-cookie": mod.Cookie, |
| 332 | }) |
khenaidoo | 787224a | 2020-04-16 18:08:47 -0400 | [diff] [blame] | 333 | response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s %v", agent.rootDeviceID, err)) |
| 334 | } |
| 335 | response.Done() |
| 336 | }(uniPort, metadata) |
| 337 | } |
| 338 | return responses |
| 339 | } |
| 340 | |
Kent Hagerman | 2b21604 | 2020-04-03 18:28:56 -0400 | [diff] [blame] | 341 | func (agent *LogicalAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) { |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 342 | if logger.V(log.InfoLevel) { |
| 343 | logger.Infow(ctx, "packet-out", log.Fields{ |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 344 | "packet": hex.EncodeToString(packet.Data), |
| 345 | "in-port": packet.GetInPort(), |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 346 | }) |
| 347 | } |
khenaidoo | 68c930b | 2019-05-13 11:46:51 -0400 | [diff] [blame] | 348 | outPort := fu.GetPacketOutPort(packet) |
khenaidoo | fdbad6e | 2018-11-06 22:26:38 -0500 | [diff] [blame] | 349 | //frame := packet.GetData() |
| 350 | //TODO: Use a channel between the logical agent and the device agent |
npujar | 467fe75 | 2020-01-16 20:17:45 +0530 | [diff] [blame] | 351 | if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil { |
Himani Chawla | b4c2591 | 2020-11-12 17:16:38 +0530 | [diff] [blame] | 352 | logger.Error(ctx, "packet-out-failed", log.Fields{"logical-device-id": agent.rootDeviceID}) |
khenaidoo | ca30132 | 2019-01-09 23:06:32 -0500 | [diff] [blame] | 353 | } |
khenaidoo | fdbad6e | 2018-11-06 22:26:38 -0500 | [diff] [blame] | 354 | } |
| 355 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 356 | func (agent *LogicalAgent) packetIn(ctx context.Context, port uint32, transactionID string, packet []byte) { |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 357 | if logger.V(log.InfoLevel) { |
Andrea Campanella | 9d7ddcb | 2021-03-03 10:34:15 +0100 | [diff] [blame] | 358 | logger.Debugw(ctx, "packet-in", log.Fields{ |
Matteo Scandolo | 45e514a | 2020-08-05 15:27:10 -0700 | [diff] [blame] | 359 | "port": port, |
| 360 | "packet": hex.EncodeToString(packet), |
| 361 | "transactionId": transactionID, |
| 362 | }) |
| 363 | } |
| 364 | |
khenaidoo | 68c930b | 2019-05-13 11:46:51 -0400 | [diff] [blame] | 365 | packetIn := fu.MkPacketIn(port, packet) |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 366 | agent.ldeviceMgr.SendPacketIn(ctx, agent.logicalDeviceID, transactionID, packetIn) |
| 367 | logger.Debugw(ctx, "sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)}) |
khenaidoo | fdbad6e | 2018-11-06 22:26:38 -0500 | [diff] [blame] | 368 | } |