blob: 4208e32f7f52aff28b2cad59969ca4763fdb3846 [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
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
20 "context"
Matteo Scandolo360605d2019-11-05 18:29:17 -080021 "encoding/hex"
khenaidoo19d7b632018-10-30 10:49:50 -040022 "errors"
23 "fmt"
David Bainbridged1afd662020-03-26 18:27:41 -070024 "reflect"
25 "sync"
26 "time"
27
khenaidoob9203542018-09-17 22:56:37 -040028 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
npujar1d86a522019-11-14 17:11:16 +053030 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo442e7c72020-03-10 16:13:48 -040031 "github.com/opencord/voltha-go/rw_core/route"
Scott Bakerb671a862019-10-24 10:53:40 -070032 coreutils "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080033 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
34 "github.com/opencord/voltha-lib-go/v3/pkg/log"
35 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
37 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040040)
41
npujar1d86a522019-11-14 17:11:16 +053042// LogicalDeviceAgent represent attributes of logical device agent
khenaidoob9203542018-09-17 22:56:37 -040043type LogicalDeviceAgent struct {
npujar1d86a522019-11-14 17:11:16 +053044 logicalDeviceID string
David Bainbridged1afd662020-03-26 18:27:41 -070045 serialNumber string
npujar1d86a522019-11-14 17:11:16 +053046 rootDeviceID string
khenaidoo3306c992019-05-24 16:57:35 -040047 deviceMgr *DeviceManager
48 ldeviceMgr *LogicalDeviceManager
49 clusterDataProxy *model.Proxy
50 exitChannel chan int
khenaidoo820197c2020-02-13 16:35:33 -050051 deviceRoutes *route.DeviceRoutes
khenaidoo3306c992019-05-24 16:57:35 -040052 flowProxy *model.Proxy
53 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040054 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040055 ldProxy *model.Proxy
56 portProxies map[string]*model.Proxy
khenaidoo820197c2020-02-13 16:35:33 -050057 lockDeviceRoutes sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040058 logicalPortsNo map[uint32]bool //value is true for NNI port
59 lockLogicalPortsNo sync.RWMutex
60 flowDecomposer *fd.FlowDecomposer
khenaidoo442e7c72020-03-10 16:13:48 -040061 defaultTimeout time.Duration
khenaidoo6e55d9e2019-12-12 18:26:26 -050062 logicalDevice *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -040063 requestQueue *coreutils.RequestQueue
64 startOnce sync.Once
65 stopOnce sync.Once
khenaidoob9203542018-09-17 22:56:37 -040066}
67
David Bainbridged1afd662020-03-26 18:27:41 -070068func newLogicalDeviceAgent(id string, sn string, deviceID string, ldeviceMgr *LogicalDeviceManager,
69 deviceMgr *DeviceManager, cdProxy *model.Proxy, timeout time.Duration) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040070 var agent LogicalDeviceAgent
71 agent.exitChannel = make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +053072 agent.logicalDeviceID = id
David Bainbridged1afd662020-03-26 18:27:41 -070073 agent.serialNumber = sn
npujar1d86a522019-11-14 17:11:16 +053074 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040075 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040076 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040077 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040078 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoofc1314d2019-03-14 09:34:21 -040079 agent.portProxies = make(map[string]*model.Proxy)
khenaidoo2c6a0992019-04-29 13:46:56 -040080 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040081 agent.defaultTimeout = timeout
Kent Hagerman730cbdf2020-03-31 12:22:08 -040082 agent.requestQueue = coreutils.NewRequestQueue()
khenaidoob9203542018-09-17 22:56:37 -040083 return &agent
84}
85
khenaidoo4d4802d2018-10-04 21:59:49 -040086// start creates the logical device and add it to the data model
khenaidoo442e7c72020-03-10 16:13:48 -040087func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromDB bool) error {
88 needToStart := false
89 if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
90 return nil
91 }
92
Girish Kumarf56a4682020-03-20 20:07:46 +000093 logger.Infow("starting-logical_device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB})
khenaidoo442e7c72020-03-10 16:13:48 -040094
95 var startSucceeded bool
96 defer func() {
97 if !startSucceeded {
98 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +000099 logger.Errorw("failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400100 }
101 }
102 }()
103
khenaidoo297cd252019-02-07 22:10:23 -0500104 var ld *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -0400105 if !loadFromDB {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400106 //Build the logical device based on information retrieved from the device adapter
107 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -0500108 var err error
npujar1d86a522019-11-14 17:11:16 +0530109 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400110 return err
111 }
npujar1d86a522019-11-14 17:11:16 +0530112 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500113
114 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
115 var datapathID uint64
David Bainbridged1afd662020-03-26 18:27:41 -0700116 if datapathID, err = CreateDataPathID(agent.serialNumber); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500117 return err
118 }
119 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400120 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
Girish Kumarf56a4682020-03-20 20:07:46 +0000121 logger.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo7e3d8f12019-08-02 16:06:30 -0400122 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500123 ld.Flows = &ofp.Flows{Items: nil}
124 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoo49085352020-01-13 19:15:43 -0500125 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500126
khenaidoo297cd252019-02-07 22:10:23 -0500127 // Save the logical device
Thomas Lee Se5a44012019-11-07 20:32:24 +0530128 added, err := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, "")
129 if err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530130 return err
131 }
132 if added == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000133 logger.Errorw("failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500134 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000135 logger.Debugw("logicaldevice-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId})
khenaidoo297cd252019-02-07 22:10:23 -0500136 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500137
138 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoofc1314d2019-03-14 09:34:21 -0400139
khenaidoo442e7c72020-03-10 16:13:48 -0400140 // Setup the logicalports - internal processing, no need to propagate the client context
npujar1d86a522019-11-14 17:11:16 +0530141 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400142 err := agent.setupLogicalPorts(context.Background())
npujar1d86a522019-11-14 17:11:16 +0530143 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000144 logger.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530145 }
146 }()
khenaidoo297cd252019-02-07 22:10:23 -0500147 } else {
148 // load from dB - the logical may not exist at this time. On error, just return and the calling function
149 // will destroy this agent.
npujar467fe752020-01-16 20:17:45 +0530150 logicalDevice, err := agent.clusterDataProxy.Get(ctx, "/logical_devices/"+agent.logicalDeviceID, 0, true, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530151 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400152 return err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530153 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500154 ld, ok := logicalDevice.(*voltha.LogicalDevice)
155 if !ok {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500156 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500157 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500158 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530159 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400160
khenaidoo6e55d9e2019-12-12 18:26:26 -0500161 // Update the last data
162 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
163
khenaidoo3d3b8c22019-05-22 18:10:39 -0400164 // Setup the local list of logical ports
165 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400166 }
khenaidoofc1314d2019-03-14 09:34:21 -0400167
khenaidoo442e7c72020-03-10 16:13:48 -0400168 var err error
Thomas Lee Se5a44012019-11-07 20:32:24 +0530169 agent.flowProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400170 ctx,
npujar1d86a522019-11-14 17:11:16 +0530171 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400172 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530173 if err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530174 return err
175 }
176 agent.meterProxy, err = agent.clusterDataProxy.CreateProxy(
Manikkaraj kb1a10922019-07-29 12:10:34 -0400177 ctx,
npujar1d86a522019-11-14 17:11:16 +0530178 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400179 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530180 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000181 logger.Errorw("failed-to-create-meter-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530182 return err
183 }
184 agent.groupProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400185 ctx,
npujar1d86a522019-11-14 17:11:16 +0530186 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400187 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530188 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000189 logger.Errorw("failed-to-create-group-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530190 return err
191 }
192 agent.ldProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400193 ctx,
npujar1d86a522019-11-14 17:11:16 +0530194 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400195 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530196 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000197 logger.Errorw("failed-to-create-logical-device-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530198 return err
199 }
khenaidoofc1314d2019-03-14 09:34:21 -0400200 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400201 if agent.ldProxy != nil {
npujar9a30c702019-11-14 17:06:39 +0530202 agent.ldProxy.RegisterCallback(model.PostUpdate, agent.portUpdated)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400203 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400204 return status.Error(codes.Internal, "logical-device-proxy-null")
205 }
khenaidoobcf205b2019-01-25 22:21:14 -0500206
khenaidoo820197c2020-02-13 16:35:33 -0500207 // 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 -0400208 if loadFromDB {
khenaidoo820197c2020-02-13 16:35:33 -0500209 go func() {
210 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000211 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -0500212 }
213 }()
khenaidoo4c9e5592019-09-09 16:20:41 -0400214 }
khenaidoo442e7c72020-03-10 16:13:48 -0400215 startSucceeded = true
216
khenaidoob9203542018-09-17 22:56:37 -0400217 return nil
218}
219
khenaidoo442e7c72020-03-10 16:13:48 -0400220// stop stops the logical device agent. This removes the logical device from the data model.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530221func (agent *LogicalDeviceAgent) stop(ctx context.Context) error {
khenaidoo442e7c72020-03-10 16:13:48 -0400222 var returnErr error
223 agent.stopOnce.Do(func() {
Girish Kumarf56a4682020-03-20 20:07:46 +0000224 logger.Info("stopping-logical_device-agent")
khenaidoo8c3303d2019-02-13 14:59:39 -0500225
khenaidoo442e7c72020-03-10 16:13:48 -0400226 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
227 // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once.
228 returnErr = err
229 return
230 }
231 defer agent.requestQueue.RequestComplete()
232
233 //Remove the logical device from the model
234 if removed, err := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); err != nil {
235 returnErr = err
236 } else if removed == nil {
237 returnErr = status.Errorf(codes.Aborted, "failed-to-remove-logical-ldevice-%s", agent.logicalDeviceID)
238 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000239 logger.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400240 }
241
khenaidoo442e7c72020-03-10 16:13:48 -0400242 close(agent.exitChannel)
243
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Info("logical_device-agent-stopped")
khenaidoo442e7c72020-03-10 16:13:48 -0400245 })
246 return returnErr
khenaidoo4d4802d2018-10-04 21:59:49 -0400247}
248
khenaidoo6e55d9e2019-12-12 18:26:26 -0500249// GetLogicalDevice returns the latest logical device data
khenaidoo442e7c72020-03-10 16:13:48 -0400250func (agent *LogicalDeviceAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
251 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
252 return nil, err
253 }
254 defer agent.requestQueue.RequestComplete()
255 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400256}
257
npujar1d86a522019-11-14 17:11:16 +0530258// ListLogicalDeviceFlows returns logical device flows
khenaidoo442e7c72020-03-10 16:13:48 -0400259func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows(ctx context.Context) (*ofp.Flows, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000260 logger.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500261
khenaidoo442e7c72020-03-10 16:13:48 -0400262 logicalDevice, err := agent.GetLogicalDevice(ctx)
263 if err != nil {
264 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400265 }
khenaidoo442e7c72020-03-10 16:13:48 -0400266 if logicalDevice.Flows == nil {
267 return &ofp.Flows{}, nil
268 }
269 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows), nil
khenaidoodd237172019-05-27 16:37:17 -0400270}
271
npujar1d86a522019-11-14 17:11:16 +0530272// ListLogicalDeviceMeters returns logical device meters
khenaidoo442e7c72020-03-10 16:13:48 -0400273func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters(ctx context.Context) (*ofp.Meters, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000274 logger.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500275
khenaidoo442e7c72020-03-10 16:13:48 -0400276 logicalDevice, err := agent.GetLogicalDevice(ctx)
277 if err != nil {
278 return nil, err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400279 }
khenaidoo442e7c72020-03-10 16:13:48 -0400280 if logicalDevice.Meters == nil {
281 return &ofp.Meters{}, nil
282 }
283 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters), nil
Manikkaraj kb1a10922019-07-29 12:10:34 -0400284}
285
npujar1d86a522019-11-14 17:11:16 +0530286// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoo442e7c72020-03-10 16:13:48 -0400287func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups(ctx context.Context) (*ofp.FlowGroups, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000288 logger.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500289
khenaidoo442e7c72020-03-10 16:13:48 -0400290 logicalDevice, err := agent.GetLogicalDevice(ctx)
291 if err != nil {
292 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400293 }
khenaidoo442e7c72020-03-10 16:13:48 -0400294 if logicalDevice.FlowGroups == nil {
295 return &ofp.FlowGroups{}, nil
296 }
297 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups), nil
khenaidoodd237172019-05-27 16:37:17 -0400298}
299
npujar1d86a522019-11-14 17:11:16 +0530300// ListLogicalDevicePorts returns logical device ports
khenaidoo442e7c72020-03-10 16:13:48 -0400301func (agent *LogicalDeviceAgent) ListLogicalDevicePorts(ctx context.Context) (*voltha.LogicalPorts, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000302 logger.Debug("ListLogicalDevicePorts")
khenaidoo442e7c72020-03-10 16:13:48 -0400303 logicalDevice, err := agent.GetLogicalDevice(ctx)
304 if err != nil {
305 return nil, err
306 }
307 if logicalDevice == nil {
308 return &voltha.LogicalPorts{}, nil
309 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500310 lPorts := make([]*voltha.LogicalPort, 0)
311 lPorts = append(lPorts, logicalDevice.Ports...)
khenaidoo442e7c72020-03-10 16:13:48 -0400312 return &voltha.LogicalPorts{Items: lPorts}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400313}
314
khenaidoo4c9e5592019-09-09 16:20:41 -0400315//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
npujar467fe752020-01-16 20:17:45 +0530316func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(ctx context.Context, flows *ofp.Flows) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500317 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400318
Girish Kumarf56a4682020-03-20 20:07:46 +0000319 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500320 ld.Flows = flows
321
npujar467fe752020-01-16 20:17:45 +0530322 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000323 logger.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400324 return err
khenaidoo43c82122018-11-22 18:38:28 -0500325 }
khenaidoo43c82122018-11-22 18:38:28 -0500326 return nil
327}
328
khenaidoo4c9e5592019-09-09 16:20:41 -0400329//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
npujar467fe752020-01-16 20:17:45 +0530330func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(ctx context.Context, meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500331 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400332
Girish Kumarf56a4682020-03-20 20:07:46 +0000333 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500334 ld.Meters = meters
335
npujar467fe752020-01-16 20:17:45 +0530336 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000337 logger.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400338 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400339 }
340 return nil
341}
342
khenaidoo4c9e5592019-09-09 16:20:41 -0400343//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
npujar467fe752020-01-16 20:17:45 +0530344func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(ctx context.Context, flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500345 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400346
Girish Kumarf56a4682020-03-20 20:07:46 +0000347 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500348 ld.FlowGroups = flowGroups
349
npujar467fe752020-01-16 20:17:45 +0530350 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000351 logger.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400352 return err
khenaidoo43c82122018-11-22 18:38:28 -0500353 }
khenaidoo43c82122018-11-22 18:38:28 -0500354 return nil
355}
356
khenaidoo6e55d9e2019-12-12 18:26:26 -0500357// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
358func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
Girish Kumarf56a4682020-03-20 20:07:46 +0000359 logger.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500360 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400361}
362
npujar467fe752020-01-16 20:17:45 +0530363func (agent *LogicalDeviceAgent) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000364 logger.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
khenaidoo2c6a0992019-04-29 13:46:56 -0400365 var err error
366 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530367 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400368 return err
369 }
370 agent.addLogicalPortToMap(port.PortNo, true)
371 } else if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530372 if _, err = agent.addUNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400373 return err
374 }
375 agent.addLogicalPortToMap(port.PortNo, false)
376 } else {
khenaidoo820197c2020-02-13 16:35:33 -0500377 // Update the device routes to ensure all routes on the logical device have been calculated
378 if err = agent.buildRoutes(ctx); err != nil {
379 // Not an error - temporary state
Girish Kumarf56a4682020-03-20 20:07:46 +0000380 logger.Warnw("failed-to-update-routes", log.Fields{"device-id": device.Id, "port": port, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400381 }
382 }
383 return nil
384}
385
khenaidoo3d3b8c22019-05-22 18:10:39 -0400386// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
387// added to it. While the logical device was being created we could have received requests to add
388// NNI and UNI ports which were discarded. Now is the time to add them if needed
389func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000390 logger.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400391 // First add any NNI ports which could have been missing
npujar467fe752020-01-16 20:17:45 +0530392 if err := agent.setupNNILogicalPorts(ctx, agent.rootDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000393 logger.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400394 return err
395 }
396
397 // Now, set up the UNI ports if needed.
npujar467fe752020-01-16 20:17:45 +0530398 children, err := agent.deviceMgr.getAllChildDevices(ctx, agent.rootDeviceID)
npujar1d86a522019-11-14 17:11:16 +0530399 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000400 logger.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400401 return err
npujar1d86a522019-11-14 17:11:16 +0530402 }
403 responses := make([]coreutils.Response, 0)
404 for _, child := range children.Items {
405 response := coreutils.NewResponse()
406 responses = append(responses, response)
407 go func(child *voltha.Device) {
khenaidoo442e7c72020-03-10 16:13:48 -0400408 if err = agent.setupUNILogicalPorts(context.Background(), child); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000409 logger.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
npujar1d86a522019-11-14 17:11:16 +0530410 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
411 }
412 response.Done()
413 }(child)
414 }
415 // Wait for completion
416 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
417 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400418 }
419 return nil
420}
421
khenaidoofc1314d2019-03-14 09:34:21 -0400422// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530423func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000424 logger.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400425 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400426 var err error
427
428 var device *voltha.Device
npujar467fe752020-01-16 20:17:45 +0530429 if device, err = agent.deviceMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000430 logger.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400431 return err
432 }
433
434 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400435 for _, port := range device.Ports {
436 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530437 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000438 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400439 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400440 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400441 }
442 }
khenaidoofc1314d2019-03-14 09:34:21 -0400443 return err
444}
445
khenaidoo171b98e2019-10-31 11:48:15 -0400446// updatePortState updates the port state of the device
npujar467fe752020-01-16 20:17:45 +0530447func (agent *LogicalDeviceAgent) updatePortState(ctx context.Context, deviceID string, portNo uint32, operStatus voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000448 logger.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo442e7c72020-03-10 16:13:48 -0400449 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
450 return err
451 }
452 defer agent.requestQueue.RequestComplete()
khenaidoo171b98e2019-10-31 11:48:15 -0400453 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500454 cloned := agent.getLogicalDeviceWithoutLock()
455 for idx, lPort := range cloned.Ports {
npujar1d86a522019-11-14 17:11:16 +0530456 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530457 if operStatus == voltha.OperStatus_ACTIVE {
458 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
459 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
460 } else {
461 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
462 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
463 }
464 // Update the logical device
npujar467fe752020-01-16 20:17:45 +0530465 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000466 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530467 return err
468 }
469 return nil
470 }
471 }
472 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400473}
474
khenaidoo3ab34882019-05-02 21:33:30 -0400475// updatePortsState updates the ports state related to the device
kesavandbc2d1622020-01-21 00:42:01 -0500476func (agent *LogicalDeviceAgent) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000477 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400478 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
479 return err
480 }
481 defer agent.requestQueue.RequestComplete()
khenaidoo3ab34882019-05-02 21:33:30 -0400482 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500483 cloned := agent.getLogicalDeviceWithoutLock()
npujar1d86a522019-11-14 17:11:16 +0530484 for _, lport := range cloned.Ports {
485 if lport.DeviceId == device.Id {
kesavandbc2d1622020-01-21 00:42:01 -0500486 if state == voltha.OperStatus_ACTIVE {
npujar1d86a522019-11-14 17:11:16 +0530487 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
488 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
kesavandbc2d1622020-01-21 00:42:01 -0500489 } else {
npujar1d86a522019-11-14 17:11:16 +0530490 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
491 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
khenaidoo3ab34882019-05-02 21:33:30 -0400492 }
kesavandbc2d1622020-01-21 00:42:01 -0500493
khenaidoo3ab34882019-05-02 21:33:30 -0400494 }
npujar1d86a522019-11-14 17:11:16 +0530495 }
496 // Updating the logical device will trigger the poprt change events to be populated to the controller
npujar467fe752020-01-16 20:17:45 +0530497 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000498 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530499 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400500 }
501 return nil
502}
503
khenaidoofc1314d2019-03-14 09:34:21 -0400504// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
505func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000506 logger.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400507 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400508 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400509 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400510 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400511 for _, port := range childDevice.Ports {
512 if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530513 if added, err = agent.addUNILogicalPort(ctx, childDevice, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000514 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400515 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400516 if added {
517 agent.addLogicalPortToMap(port.PortNo, false)
518 }
khenaidoo19d7b632018-10-30 10:49:50 -0400519 }
520 }
khenaidoofc1314d2019-03-14 09:34:21 -0400521 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400522}
523
Girish Gowdra408cd962020-03-11 14:31:31 -0700524// deleteAllLogicalPorts deletes all logical ports associated with this logical device
525func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000526 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400527 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
528 return err
529 }
530 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -0400531 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500532 ld := agent.getLogicalDeviceWithoutLock()
533
npujar1d86a522019-11-14 17:11:16 +0530534 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
Girish Gowdra408cd962020-03-11 14:31:31 -0700535 var updateLogicalPorts []*voltha.LogicalPort
536 // Update an empty ports slice to remove all the ports
537 cloned.Ports = updateLogicalPorts
538
539 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000540 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -0700541 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400542 }
543 return nil
544}
545
Hardik Windlassc704def2020-02-26 18:23:19 +0000546// deleteAllUNILogicalPorts deletes all UNI logical ports associated with this parent device
547func (agent *LogicalDeviceAgent) deleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000548 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400549 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
550 return err
551 }
552 defer agent.requestQueue.RequestComplete()
Hardik Windlassc704def2020-02-26 18:23:19 +0000553 // Get the latest logical device info
554 ld := agent.getLogicalDeviceWithoutLock()
555
556 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
557 updateLogicalPorts := []*voltha.LogicalPort{}
558 for _, lport := range cloned.Ports {
559 // Save NNI ports only
560 if agent.isNNIPort(lport.DevicePortNo) {
561 updateLogicalPorts = append(updateLogicalPorts, lport)
562 }
563 }
564 if len(updateLogicalPorts) < len(cloned.Ports) {
565 cloned.Ports = updateLogicalPorts
566 // Updating the logical device will trigger the port change events to be populated to the controller
567 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
568 return err
569 }
570 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000571 logger.Debugw("no-change-required", log.Fields{"logical-device-id": agent.logicalDeviceID})
Hardik Windlassc704def2020-02-26 18:23:19 +0000572 }
573 return nil
574}
575
khenaidoo92e62c52018-10-03 14:02:54 -0400576//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
npujar467fe752020-01-16 20:17:45 +0530577func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(ctx context.Context, logicalDevice *voltha.LogicalDevice) error {
578 updateCtx := context.WithValue(ctx, model.RequestTimestamp, time.Now().UnixNano())
Thomas Lee Se5a44012019-11-07 20:32:24 +0530579 afterUpdate, err := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
580 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000581 logger.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530582 return err
583 }
khenaidoo92e62c52018-10-03 14:02:54 -0400584 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530585 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400586 }
khenaidoo442e7c72020-03-10 16:13:48 -0400587 //agent.logicalDevice = (proto.Clone(logicalDevice)).(*voltha.LogicalDevice)
588 agent.logicalDevice = logicalDevice
589
khenaidoo92e62c52018-10-03 14:02:54 -0400590 return nil
591}
592
khenaidoo820197c2020-02-13 16:35:33 -0500593//generateDeviceRoutesIfNeeded generates the device routes if the logical device has been updated since the last time
khenaidoo4c9e5592019-09-09 16:20:41 -0400594//that device graph was generated.
khenaidoo820197c2020-02-13 16:35:33 -0500595func (agent *LogicalDeviceAgent) generateDeviceRoutesIfNeeded(ctx context.Context) error {
596 agent.lockDeviceRoutes.Lock()
597 defer agent.lockDeviceRoutes.Unlock()
598
khenaidoo442e7c72020-03-10 16:13:48 -0400599 ld, err := agent.GetLogicalDevice(ctx)
600 if err != nil {
601 return err
602 }
khenaidoo820197c2020-02-13 16:35:33 -0500603
604 if agent.deviceRoutes != nil && agent.deviceRoutes.IsUpToDate(ld) {
npujar1d86a522019-11-14 17:11:16 +0530605 return nil
606 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000607 logger.Debug("Generation of device route required")
khenaidoo820197c2020-02-13 16:35:33 -0500608 if err := agent.buildRoutes(ctx); err != nil {
609 return err
610 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400611 return nil
612}
613
khenaidoo19d7b632018-10-30 10:49:50 -0400614//updateFlowTable updates the flow table of that logical device
615func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000616 logger.Debug("updateFlowTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400617 if flow == nil {
618 return nil
619 }
khenaidoo820197c2020-02-13 16:35:33 -0500620 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400621 return err
622 }
khenaidoo19d7b632018-10-30 10:49:50 -0400623 switch flow.GetCommand() {
624 case ofp.OfpFlowModCommand_OFPFC_ADD:
npujar467fe752020-01-16 20:17:45 +0530625 return agent.flowAdd(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400626 case ofp.OfpFlowModCommand_OFPFC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530627 return agent.flowDelete(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400628 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
npujar467fe752020-01-16 20:17:45 +0530629 return agent.flowDeleteStrict(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400630 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
631 return agent.flowModify(flow)
632 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
633 return agent.flowModifyStrict(flow)
634 }
635 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530636 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400637}
638
639//updateGroupTable updates the group table of that logical device
640func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000641 logger.Debug("updateGroupTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400642 if groupMod == nil {
643 return nil
644 }
khenaidoo820197c2020-02-13 16:35:33 -0500645 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400646 return err
647 }
khenaidoo820197c2020-02-13 16:35:33 -0500648
khenaidoo19d7b632018-10-30 10:49:50 -0400649 switch groupMod.GetCommand() {
650 case ofp.OfpGroupModCommand_OFPGC_ADD:
npujar467fe752020-01-16 20:17:45 +0530651 return agent.groupAdd(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400652 case ofp.OfpGroupModCommand_OFPGC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530653 return agent.groupDelete(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400654 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530655 return agent.groupModify(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400656 }
657 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530658 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400659}
660
Manikkaraj kb1a10922019-07-29 12:10:34 -0400661// updateMeterTable updates the meter table of that logical device
662func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000663 logger.Debug("updateMeterTable")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400664 if meterMod == nil {
665 return nil
666 }
667 switch meterMod.GetCommand() {
668 case ofp.OfpMeterModCommand_OFPMC_ADD:
npujar467fe752020-01-16 20:17:45 +0530669 return agent.meterAdd(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400670 case ofp.OfpMeterModCommand_OFPMC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530671 return agent.meterDelete(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400672 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530673 return agent.meterModify(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400674 }
675 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530676 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400677
678}
679
npujar467fe752020-01-16 20:17:45 +0530680func (agent *LogicalDeviceAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000681 logger.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400682 if meterMod == nil {
683 return nil
684 }
khenaidoo442e7c72020-03-10 16:13:48 -0400685 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
686 return err
687 }
688 defer agent.requestQueue.RequestComplete()
Girish Kumarf56a4682020-03-20 20:07:46 +0000689 logger.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500690 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400691
692 var meters []*ofp.OfpMeterEntry
693 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
694 meters = lDevice.Meters.Items
695 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000696 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400697
698 for _, meter := range meters {
699 if meterMod.MeterId == meter.Config.MeterId {
Girish Kumarf56a4682020-03-20 20:07:46 +0000700 logger.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400701 return nil
702 }
703 }
704
705 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
706 meters = append(meters, meterEntry)
707 //Update model
npujar467fe752020-01-16 20:17:45 +0530708 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, &ofp.Meters{Items: meters}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000709 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400710 return err
711 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000712 logger.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400713 return nil
714}
715
npujar467fe752020-01-16 20:17:45 +0530716func (agent *LogicalDeviceAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000717 logger.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400718 if meterMod == nil {
719 return nil
720 }
khenaidoo442e7c72020-03-10 16:13:48 -0400721 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
722 return err
723 }
724 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400725
khenaidoo6e55d9e2019-12-12 18:26:26 -0500726 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400727
728 var meters []*ofp.OfpMeterEntry
729 var flows []*ofp.OfpFlowStats
730 updatedFlows := make([]*ofp.OfpFlowStats, 0)
731 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
732 meters = lDevice.Meters.Items
733 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400734
735 changedMeter := false
736 changedFow := false
Girish Kumarf56a4682020-03-20 20:07:46 +0000737 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400738 for index, meter := range meters {
739 if meterMod.MeterId == meter.Config.MeterId {
740 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530741 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400742 meters = append(meters[:index], meters[index+1:]...)
Girish Kumarf56a4682020-03-20 20:07:46 +0000743 logger.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400744 changedMeter = true
745 break
746 }
747 }
748 if changedMeter {
749 //Update model
750 metersToUpdate := &ofp.Meters{}
751 if lDevice.Meters != nil {
752 metersToUpdate = &ofp.Meters{Items: meters}
753 }
npujar467fe752020-01-16 20:17:45 +0530754 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000755 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400756 return err
757 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000758 logger.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400759
760 }
761 if changedFow {
762 //Update model
npujar467fe752020-01-16 20:17:45 +0530763 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: updatedFlows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000764 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400765 return err
766 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000767 logger.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
Manikkaraj kb1a10922019-07-29 12:10:34 -0400768 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
769 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000770 logger.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400771 return nil
772}
773
npujar467fe752020-01-16 20:17:45 +0530774func (agent *LogicalDeviceAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000775 logger.Debug("meterModify")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400776 if meterMod == nil {
777 return nil
778 }
khenaidoo442e7c72020-03-10 16:13:48 -0400779 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
780 return err
781 }
782 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400783
khenaidoo6e55d9e2019-12-12 18:26:26 -0500784 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400785
786 var meters []*ofp.OfpMeterEntry
787 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
788 meters = lDevice.Meters.Items
789 }
790 changedMeter := false
791 for index, meter := range meters {
792 if meterMod.MeterId == meter.Config.MeterId {
793 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
794 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
795 meters[index] = newmeterEntry
796 changedMeter = true
Girish Kumarf56a4682020-03-20 20:07:46 +0000797 logger.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400798 break
799 }
800 }
801 if changedMeter {
802 //Update model
803 metersToUpdate := &ofp.Meters{}
804 if lDevice.Meters != nil {
805 metersToUpdate = &ofp.Meters{Items: meters}
806 }
npujar467fe752020-01-16 20:17:45 +0530807 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000808 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400809 return err
810 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000811 logger.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400812 return nil
813 }
814
Girish Kumarf56a4682020-03-20 20:07:46 +0000815 logger.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530816 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400817
818}
819
npujar1d86a522019-11-14 17:11:16 +0530820func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000821 logger.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400822 changed := false
823 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
824 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530825 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Girish Kumarf56a4682020-03-20 20:07:46 +0000826 logger.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400827 flows = append(flows[:index], flows[index+1:]...)
828 changed = true
829 }
830 }
831 return changed, flows
832}
833
834func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
835
836 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530837 meterID := fu.GetMeterIdFromFlow(flow)
Girish Kumarf56a4682020-03-20 20:07:46 +0000838 logger.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
npujar1d86a522019-11-14 17:11:16 +0530839 if meterID == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000840 logger.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400841 return false
842 }
843 if meters == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000844 logger.Debug("No meters present in logical device")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400845 return false
846 }
847 changedMeter := false
848 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530849 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400850 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530851 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400852 changedMeter = true
853 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530854 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400855 changedMeter = true
856 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000857 logger.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400858 break
859 }
860 }
861 return changedMeter
862}
863
khenaidoo19d7b632018-10-30 10:49:50 -0400864//flowAdd adds a flow to the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +0530865func (agent *LogicalDeviceAgent) flowAdd(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000866 logger.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400867 if mod == nil {
868 return nil
869 }
khenaidoo442e7c72020-03-10 16:13:48 -0400870 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
871 return err
872 }
873 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -0400874
khenaidoo6e55d9e2019-12-12 18:26:26 -0500875 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400876
877 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400878 var meters []*ofp.OfpMeterEntry
879 var flow *ofp.OfpFlowStats
Scott Bakerfdea1e32020-02-21 15:35:41 -0800880 var err error
Manikkaraj kb1a10922019-07-29 12:10:34 -0400881
khenaidoo19d7b632018-10-30 10:49:50 -0400882 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
883 flows = lDevice.Flows.Items
884 }
885
Manikkaraj kb1a10922019-07-29 12:10:34 -0400886 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
887 meters = lDevice.Meters.Items
888 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400889 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400890 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400891 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400892 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
893 if checkOverlap {
894 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
895 // TODO: should this error be notified other than being logged?
Girish Kumarf56a4682020-03-20 20:07:46 +0000896 logger.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400897 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400898 // Add flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800899 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
900 if err != nil {
901 return err
902 }
khenaidoo19d7b632018-10-30 10:49:50 -0400903 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400904 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400905 changed = true
906 }
907 } else {
Scott Bakerfdea1e32020-02-21 15:35:41 -0800908 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
909 if err != nil {
910 return err
911 }
khenaidoo19d7b632018-10-30 10:49:50 -0400912 idx := fu.FindFlows(flows, flow)
913 if idx >= 0 {
914 oldFlow := flows[idx]
915 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
916 flow.ByteCount = oldFlow.ByteCount
917 flow.PacketCount = oldFlow.PacketCount
918 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400919 if !reflect.DeepEqual(oldFlow, flow) {
920 flows[idx] = flow
921 updatedFlows = append(updatedFlows, flow)
922 changed = true
923 updated = true
924 }
925 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400926 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400927 updatedFlows = append(updatedFlows, flow)
928 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400929 }
khenaidoo19d7b632018-10-30 10:49:50 -0400930 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000931 logger.Debugw("flowAdd-changed", log.Fields{"changed": changed})
khenaidoo4c9e5592019-09-09 16:20:41 -0400932
khenaidoo19d7b632018-10-30 10:49:50 -0400933 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400934 var flowMetadata voltha.FlowMetadata
935 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
Girish Kumarf56a4682020-03-20 20:07:46 +0000936 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400937 return err
938 }
khenaidoo820197c2020-02-13 16:35:33 -0500939 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
940 if err != nil {
941 return err
942 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000943 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -0400944
khenaidoo19d7b632018-10-30 10:49:50 -0400945 // Update model
npujar467fe752020-01-16 20:17:45 +0530946 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000947 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400948 return err
949 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400950 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400951 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
952 metersToUpdate := &ofp.Meters{}
953 if lDevice.Meters != nil {
954 metersToUpdate = &ofp.Meters{Items: meters}
955 }
956 if changedMeterStats {
957 //Update model
npujar467fe752020-01-16 20:17:45 +0530958 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000959 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400960 return err
961 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000962 logger.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400963
964 }
965 }
khenaidoo442e7c72020-03-10 16:13:48 -0400966 // Send the flows to the devices
967 respChannels := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &flowMetadata)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400968
khenaidoo442e7c72020-03-10 16:13:48 -0400969 // Create the go routines to wait
970 go func() {
971 // Wait for completion
972 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChannels...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000973 logger.Warnw("failure-to-add-flows", log.Fields{"errors": res, "logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400974 // TODO : revert added flow
975 }
976 }()
khenaidoo19d7b632018-10-30 10:49:50 -0400977 }
khenaidoo19d7b632018-10-30 10:49:50 -0400978 return nil
979}
980
npujar1d86a522019-11-14 17:11:16 +0530981// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400982func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
983 m := make(map[uint32]bool)
984 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530985 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400986 foundMeter := false
987 // Meter is present in the flow , Get from logical device
988 for _, meter := range meters {
989 if flowMeterID == meter.Config.MeterId {
990 metadata.Meters = append(metadata.Meters, meter.Config)
Girish Kumarf56a4682020-03-20 20:07:46 +0000991 logger.Debugw("Found meter in logical device",
Manikkaraj kb1a10922019-07-29 12:10:34 -0400992 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
993 m[flowMeterID] = true
994 foundMeter = true
995 break
996 }
997 }
998 if !foundMeter {
Girish Kumarf56a4682020-03-20 20:07:46 +0000999 logger.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +05301000 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001001 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
1002 }
1003 }
1004 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001005 logger.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001006 return nil
1007
1008}
1009
khenaidoo19d7b632018-10-30 10:49:50 -04001010//flowDelete deletes a flow from the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +05301011func (agent *LogicalDeviceAgent) flowDelete(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001012 logger.Debug("flowDelete")
khenaidoo19d7b632018-10-30 10:49:50 -04001013 if mod == nil {
1014 return nil
1015 }
khenaidoo442e7c72020-03-10 16:13:48 -04001016 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1017 return err
1018 }
1019 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001020
khenaidoo6e55d9e2019-12-12 18:26:26 -05001021 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001022
Manikkaraj kb1a10922019-07-29 12:10:34 -04001023 var meters []*ofp.OfpMeterEntry
1024 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001025 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -04001026
1027 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1028 flows = lDevice.Flows.Items
1029 }
1030
1031 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1032 meters = lDevice.Meters.Items
1033 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001034
1035 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
1036 flowGroups = lDevice.FlowGroups.Items
1037 }
1038
khenaidoo19d7b632018-10-30 10:49:50 -04001039 //build a list of what to keep vs what to delete
1040 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001041 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001042 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -04001043 // Check whether the flow and the flowmod matches
Scott Bakerfdea1e32020-02-21 15:35:41 -08001044 fs, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1045 if err != nil {
1046 return err
1047 }
1048 if fu.FlowMatch(f, fs) {
khenaidoo0458db62019-06-20 08:50:36 -04001049 toDelete = append(toDelete, f)
1050 continue
1051 }
1052 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -04001053 if !fu.FlowMatchesMod(f, mod) {
1054 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -04001055 } else {
1056 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -04001057 }
1058 }
1059
Girish Kumarf56a4682020-03-20 20:07:46 +00001060 logger.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -04001061
khenaidoo19d7b632018-10-30 10:49:50 -04001062 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -04001063 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001064 var flowMetadata voltha.FlowMetadata
1065 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
Girish Kumarf56a4682020-03-20 20:07:46 +00001066 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001067 return errors.New("Meter-referred-in-flows-not-present")
1068 }
khenaidoo820197c2020-02-13 16:35:33 -05001069 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{Items: flowGroups})
1070 if err != nil {
1071 return err
1072 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001073 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001074
npujar467fe752020-01-16 20:17:45 +05301075 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: toKeep}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001076 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001077 return err
1078 }
khenaidoo442e7c72020-03-10 16:13:48 -04001079
1080 // Update the devices
1081 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1082
1083 // Wait for the responses
1084 go func() {
1085 // Wait for completion
1086 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001087 logger.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001088 // TODO: Revert the flow deletion
1089 }
1090 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001091 }
1092
1093 //TODO: send announcement on delete
1094 return nil
1095}
1096
khenaidoo442e7c72020-03-10 16:13:48 -04001097func (agent *LogicalDeviceAgent) addFlowsAndGroupsToDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001098 logger.Debugw("send-add-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001099
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001100 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301101 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001102 response := coreutils.NewResponse()
1103 responses = append(responses, response)
1104 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001105 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1106 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301107 if err := agent.deviceMgr.addFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001108 logger.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001109 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001110 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001111 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301112 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001113 }
khenaidoo442e7c72020-03-10 16:13:48 -04001114 // Return responses (an array of channels) for the caller to wait for a response from the far end.
1115 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001116}
khenaidoo19d7b632018-10-30 10:49:50 -04001117
khenaidoo442e7c72020-03-10 16:13:48 -04001118func (agent *LogicalDeviceAgent) deleteFlowsAndGroupsFromDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001119 logger.Debugw("send-delete-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001120
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001121 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301122 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001123 response := coreutils.NewResponse()
1124 responses = append(responses, response)
1125 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001126 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1127 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301128 if err := agent.deviceMgr.deleteFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001129 logger.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001130 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001131 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001132 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301133 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001134 }
khenaidoo442e7c72020-03-10 16:13:48 -04001135 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001136}
1137
khenaidoo442e7c72020-03-10 16:13:48 -04001138func (agent *LogicalDeviceAgent) updateFlowsAndGroupsOfDevice(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001139 logger.Debugw("send-update-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001140
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001141 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301142 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001143 response := coreutils.NewResponse()
1144 responses = append(responses, response)
1145 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001146 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1147 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301148 if err := agent.deviceMgr.updateFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001149 logger.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001150 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001151 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001152 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301153 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001154 }
khenaidoo442e7c72020-03-10 16:13:48 -04001155 return responses
khenaidoo19d7b632018-10-30 10:49:50 -04001156}
1157
1158//flowDeleteStrict deletes a flow from the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +05301159func (agent *LogicalDeviceAgent) flowDeleteStrict(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001160 logger.Debug("flowDeleteStrict")
khenaidoo19d7b632018-10-30 10:49:50 -04001161 if mod == nil {
1162 return nil
1163 }
khenaidoo442e7c72020-03-10 16:13:48 -04001164 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1165 return err
1166 }
1167 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001168
khenaidoo6e55d9e2019-12-12 18:26:26 -05001169 lDevice := agent.getLogicalDeviceWithoutLock()
1170
Manikkaraj kb1a10922019-07-29 12:10:34 -04001171 var meters []*ofp.OfpMeterEntry
1172 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001173 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -04001174 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1175 meters = lDevice.Meters.Items
1176 }
1177 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1178 flows = lDevice.Flows.Items
1179 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001180 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
1181 flowGroups = lDevice.FlowGroups.Items
1182 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001183
1184 changedFlow := false
1185 changedMeter := false
Scott Bakerfdea1e32020-02-21 15:35:41 -08001186 flow, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1187 if err != nil {
1188 return err
1189 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001190 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001191 idx := fu.FindFlows(flows, flow)
1192 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001193 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001194 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001195 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001196 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001197 } else {
npujar1d86a522019-11-14 17:11:16 +05301198 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001199 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001200 if changedMeter {
1201 //Update model
1202 metersToUpdate := &ofp.Meters{}
1203 if lDevice.Meters != nil {
1204 metersToUpdate = &ofp.Meters{Items: meters}
1205 }
npujar467fe752020-01-16 20:17:45 +05301206 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001207 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001208 return err
1209 }
khenaidoo19d7b632018-10-30 10:49:50 -04001210
Manikkaraj kb1a10922019-07-29 12:10:34 -04001211 }
1212 if changedFlow {
1213 var flowMetadata voltha.FlowMetadata
1214 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001215 logger.Error("meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001216 return err
1217 }
khenaidoo820197c2020-02-13 16:35:33 -05001218 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{Items: flowGroups})
1219 if err != nil {
1220 return err
1221 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001222 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001223
npujar467fe752020-01-16 20:17:45 +05301224 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001225 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001226 return err
1227 }
khenaidoo442e7c72020-03-10 16:13:48 -04001228
1229 // Update the devices
1230 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1231
1232 // Wait for completion
1233 go func() {
1234 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001235 logger.Warnw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001236 //TODO: Revert flow changes
1237 }
1238 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001239 }
khenaidoo19d7b632018-10-30 10:49:50 -04001240 return nil
1241}
1242
1243//flowModify modifies a flow from the flow table of that logical device
1244func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1245 return errors.New("flowModify not implemented")
1246}
1247
1248//flowModifyStrict deletes a flow from the flow table of that logical device
1249func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1250 return errors.New("flowModifyStrict not implemented")
1251}
1252
npujar467fe752020-01-16 20:17:45 +05301253func (agent *LogicalDeviceAgent) groupAdd(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001254 logger.Debug("groupAdd")
khenaidoo19d7b632018-10-30 10:49:50 -04001255 if groupMod == nil {
1256 return nil
1257 }
khenaidoo442e7c72020-03-10 16:13:48 -04001258 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1259 return err
1260 }
1261 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001262
khenaidoo6e55d9e2019-12-12 18:26:26 -05001263 lDevice := agent.getLogicalDeviceWithoutLock()
1264
khenaidoo19d7b632018-10-30 10:49:50 -04001265 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001266 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001267 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001268
Esin Karaman2ea59212019-12-06 11:41:58 +00001269 deviceRules := fu.NewDeviceRules()
1270 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1271 fg := fu.NewFlowsAndGroups()
1272 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1273 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1274
Girish Kumarf56a4682020-03-20 20:07:46 +00001275 logger.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001276
npujar467fe752020-01-16 20:17:45 +05301277 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001278 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001279 return err
1280 }
khenaidoo442e7c72020-03-10 16:13:48 -04001281
1282 // Update the devices
1283 respChnls := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &voltha.FlowMetadata{})
1284
1285 // Wait for completion
1286 go func() {
1287 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001288 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001289 //TODO: Revert flow changes
1290 }
1291 }()
1292 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001293 }
khenaidoo442e7c72020-03-10 16:13:48 -04001294 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001295}
1296
npujar467fe752020-01-16 20:17:45 +05301297func (agent *LogicalDeviceAgent) groupDelete(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001298 logger.Debug("groupDelete")
khenaidoo19d7b632018-10-30 10:49:50 -04001299 if groupMod == nil {
1300 return nil
1301 }
khenaidoo442e7c72020-03-10 16:13:48 -04001302 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1303 return err
1304 }
1305 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001306
khenaidoo6e55d9e2019-12-12 18:26:26 -05001307 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001308 groups := lDevice.FlowGroups.Items
1309 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301310 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001311 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301312 groupID := groupMod.GroupId
1313 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001314 //TODO we must delete all flows that point to this group and
1315 //signal controller as requested by flow's flag
1316 groups = []*ofp.OfpGroupEntry{}
1317 groupsChanged = true
1318 } else {
npujar1d86a522019-11-14 17:11:16 +05301319 idx := fu.FindGroup(groups, groupID)
1320 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001321 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001322 }
npujar1d86a522019-11-14 17:11:16 +05301323 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1324 groups = append(groups[:idx], groups[idx+1:]...)
1325 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001326 }
khenaidoo0458db62019-06-20 08:50:36 -04001327 if flowsChanged || groupsChanged {
khenaidoo820197c2020-02-13 16:35:33 -05001328 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1329 if err != nil {
1330 return err
1331 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001332 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001333
khenaidoo442e7c72020-03-10 16:13:48 -04001334 if groupsChanged {
1335 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001336 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001337 return err
1338 }
khenaidoo0458db62019-06-20 08:50:36 -04001339 }
khenaidoo442e7c72020-03-10 16:13:48 -04001340 if flowsChanged {
1341 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001342 logger.Errorw("cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001343 return err
1344 }
1345 }
khenaidoo0458db62019-06-20 08:50:36 -04001346
khenaidoo442e7c72020-03-10 16:13:48 -04001347 // Update the devices
1348 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, nil)
1349
1350 // Wait for completion
1351 go func() {
1352 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001353 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001354 //TODO: Revert flow changes
1355 }
1356 }()
khenaidoo43c82122018-11-22 18:38:28 -05001357 }
khenaidoo19d7b632018-10-30 10:49:50 -04001358 return nil
1359}
1360
npujar467fe752020-01-16 20:17:45 +05301361func (agent *LogicalDeviceAgent) groupModify(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001362 logger.Debug("groupModify")
khenaidoo19d7b632018-10-30 10:49:50 -04001363 if groupMod == nil {
1364 return nil
1365 }
khenaidoo442e7c72020-03-10 16:13:48 -04001366 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1367 return err
1368 }
1369 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001370
khenaidoo6e55d9e2019-12-12 18:26:26 -05001371 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001372 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301373 var groupsChanged bool
1374 groupID := groupMod.GroupId
1375 idx := fu.FindGroup(groups, groupID)
1376 if idx == -1 {
1377 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001378 }
npujar1d86a522019-11-14 17:11:16 +05301379 //replace existing group entry with new group definition
1380 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1381 groups[idx] = groupEntry
1382 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001383 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001384 deviceRules := fu.NewDeviceRules()
1385 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1386 fg := fu.NewFlowsAndGroups()
1387 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1388 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001389
Girish Kumarf56a4682020-03-20 20:07:46 +00001390 logger.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001391
npujar467fe752020-01-16 20:17:45 +05301392 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001393 logger.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001394 return err
1395 }
khenaidoo442e7c72020-03-10 16:13:48 -04001396
1397 // Update the devices
1398 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, &voltha.FlowMetadata{})
1399
1400 // Wait for completion
1401 go func() {
1402 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001403 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001404 //TODO: Revert flow changes
1405 }
1406 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001407 }
1408 return nil
1409}
1410
1411// deleteLogicalPort removes the logical port
npujar467fe752020-01-16 20:17:45 +05301412func (agent *LogicalDeviceAgent) deleteLogicalPort(ctx context.Context, lPort *voltha.LogicalPort) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001413 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1414 return err
1415 }
1416 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001417
khenaidoo6e55d9e2019-12-12 18:26:26 -05001418 logicalDevice := agent.getLogicalDeviceWithoutLock()
1419
khenaidoo92e62c52018-10-03 14:02:54 -04001420 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001421 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001422 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001423 index = i
1424 break
1425 }
1426 }
1427 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001428 copy(logicalDevice.Ports[index:], logicalDevice.Ports[index+1:])
1429 logicalDevice.Ports[len(logicalDevice.Ports)-1] = nil
1430 logicalDevice.Ports = logicalDevice.Ports[:len(logicalDevice.Ports)-1]
Girish Kumarf56a4682020-03-20 20:07:46 +00001431 logger.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
npujar467fe752020-01-16 20:17:45 +05301432 if err := agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001433 logger.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001434 return err
1435 }
khenaidoo820197c2020-02-13 16:35:33 -05001436
1437 // Remove the logical port from cache
1438 agent.deleteLogicalPortsFromMap([]uint32{lPort.DevicePortNo})
1439
1440 // Reset the logical device routes
1441 go func() {
1442 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001443 logger.Warnw("device-routes-not-ready", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001444 }
1445 }()
khenaidoo92e62c52018-10-03 14:02:54 -04001446 }
1447 return nil
khenaidoob9203542018-09-17 22:56:37 -04001448}
1449
khenaidoo0a822f92019-05-08 15:15:57 -04001450// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301451func (agent *LogicalDeviceAgent) deleteLogicalPorts(ctx context.Context, deviceID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001452 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1453 return err
1454 }
1455 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -04001456
khenaidoo6e55d9e2019-12-12 18:26:26 -05001457 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo820197c2020-02-13 16:35:33 -05001458 lPortstoKeep := []*voltha.LogicalPort{}
1459 lPortsNoToDelete := []uint32{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001460 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301461 if logicalPort.DeviceId != deviceID {
khenaidoo820197c2020-02-13 16:35:33 -05001462 lPortstoKeep = append(lPortstoKeep, logicalPort)
1463 } else {
1464 lPortsNoToDelete = append(lPortsNoToDelete, logicalPort.DevicePortNo)
khenaidoo0a822f92019-05-08 15:15:57 -04001465 }
1466 }
khenaidoo820197c2020-02-13 16:35:33 -05001467 logicalDevice.Ports = lPortstoKeep
1468
Girish Kumarf56a4682020-03-20 20:07:46 +00001469 logger.Debugw("updated-logical-ports", log.Fields{"ports": lPortstoKeep})
npujar467fe752020-01-16 20:17:45 +05301470 if err := agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001471 logger.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001472 return err
1473 }
khenaidoo820197c2020-02-13 16:35:33 -05001474 // Remove the port from the cached logical ports set
1475 agent.deleteLogicalPortsFromMap(lPortsNoToDelete)
1476
1477 // Reset the logical device routes
1478 go func() {
1479 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001480 logger.Warnw("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001481 }
1482 }()
khenaidoo0a822f92019-05-08 15:15:57 -04001483
1484 return nil
1485}
1486
khenaidoo19d7b632018-10-30 10:49:50 -04001487// enableLogicalPort enables the logical port
npujar467fe752020-01-16 20:17:45 +05301488func (agent *LogicalDeviceAgent) enableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001489 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1490 return err
1491 }
1492 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001493
khenaidoo6e55d9e2019-12-12 18:26:26 -05001494 logicalDevice := agent.getLogicalDeviceWithoutLock()
1495
khenaidoo19d7b632018-10-30 10:49:50 -04001496 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001497 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301498 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001499 index = i
1500 break
1501 }
1502 }
1503 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001504 logicalDevice.Ports[index].OfpPort.Config = logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
npujar467fe752020-01-16 20:17:45 +05301505 return agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001506 }
npujar1d86a522019-11-14 17:11:16 +05301507 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001508}
1509
1510// disableLogicalPort disabled the logical port
npujar467fe752020-01-16 20:17:45 +05301511func (agent *LogicalDeviceAgent) disableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001512 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1513 return err
1514 }
1515 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001516
1517 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001518 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001519 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001520 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301521 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001522 index = i
1523 break
1524 }
1525 }
1526 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001527 logicalDevice.Ports[index].OfpPort.Config = (logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
npujar467fe752020-01-16 20:17:45 +05301528 return agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001529 }
npujar1d86a522019-11-14 17:11:16 +05301530 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001531}
1532
khenaidoo820197c2020-02-13 16:35:33 -05001533func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001534 logger.Debugw("ROUTE", log.Fields{"len": len(agent.deviceRoutes.Routes)})
khenaidoo820197c2020-02-13 16:35:33 -05001535 for routeLink, route := range agent.deviceRoutes.Routes {
Girish Kumarf56a4682020-03-20 20:07:46 +00001536 logger.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001537 if ingress == routeLink.Ingress && egress == routeLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -05001538 return route, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001539 }
1540 }
khenaidoo820197c2020-02-13 16:35:33 -05001541 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingress, egress)
khenaidoo89b0e942018-10-21 21:11:33 -04001542}
1543
npujar1d86a522019-11-14 17:11:16 +05301544// GetRoute returns route
khenaidoo820197c2020-02-13 16:35:33 -05001545func (agent *LogicalDeviceAgent) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001546 logger.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo820197c2020-02-13 16:35:33 -05001547 routes := make([]route.Hop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001548
khenaidoo19d7b632018-10-30 10:49:50 -04001549 // Note: A port value of 0 is equivalent to a nil port
1550
khenaidoo89b0e942018-10-21 21:11:33 -04001551 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001552 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001553 logger.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo2c6a0992019-04-29 13:46:56 -04001554 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001555 //This is a trap on the NNI Port
khenaidoo820197c2020-02-13 16:35:33 -05001556 if len(agent.deviceRoutes.Routes) == 0 {
khenaidoo8f474192019-04-03 17:20:44 -04001557 // If there are no routes set (usually when the logical device has only NNI port(s), then just return an
Humera Kouser4ff89012019-08-25 19:01:51 -04001558 // route with same IngressHop and EgressHop
khenaidoo820197c2020-02-13 16:35:33 -05001559 hop := route.Hop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001560 routes = append(routes, hop)
1561 routes = append(routes, hop)
khenaidoo820197c2020-02-13 16:35:33 -05001562 return routes, nil
khenaidoo8f474192019-04-03 17:20:44 -04001563 }
khenaidoo89b0e942018-10-21 21:11:33 -04001564 //Return a 'half' route to make the flow decomposer logic happy
khenaidoo820197c2020-02-13 16:35:33 -05001565 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001566 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001567 routes = append(routes, route.Hop{}) // first hop is set to empty
1568 routes = append(routes, path[1])
1569 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001570 }
1571 }
khenaidoo820197c2020-02-13 16:35:33 -05001572 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001573 }
1574 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001575 var err error
1576 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001577 logger.Warnw("no-nni-port", log.Fields{"error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001578 return nil, err
khenaidoo2c6a0992019-04-29 13:46:56 -04001579 }
khenaidoo89b0e942018-10-21 21:11:33 -04001580 }
1581 //If ingress port is not specified (nil), it may be a wildcarded
1582 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1583 //in which case we need to create a half-route where only the egress
1584 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001585 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001586 // We can use the 2nd hop of any upstream route, so just find the first upstream:
khenaidoo820197c2020-02-13 16:35:33 -05001587 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001588 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001589 routes = append(routes, route.Hop{}) // first hop is set to empty
1590 routes = append(routes, path[1])
1591 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001592 }
1593 }
khenaidoo820197c2020-02-13 16:35:33 -05001594 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001595 }
1596 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001597 if egressPortNo == 0 {
khenaidoo820197c2020-02-13 16:35:33 -05001598 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001599 if routeLink.Ingress == ingressPortNo {
khenaidoo820197c2020-02-13 16:35:33 -05001600 routes = append(routes, path[0])
1601 routes = append(routes, route.Hop{})
1602 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001603 }
1604 }
khenaidoo820197c2020-02-13 16:35:33 -05001605 return nil, status.Errorf(codes.FailedPrecondition, "no downstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001606 }
khenaidoo89b0e942018-10-21 21:11:33 -04001607 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001608 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001609}
1610
khenaidoo3d3b8c22019-05-22 18:10:39 -04001611//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1612//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1613//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001614func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1615 lPorts := make([]uint32, 0)
1616 var exclPort uint32
1617 if len(excludePort) == 1 {
1618 exclPort = excludePort[0]
1619 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001620 lDevice := agent.getLogicalDeviceWithoutLock()
1621 for _, port := range lDevice.Ports {
1622 if port.OfpPort.PortNo != exclPort {
1623 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001624 }
1625 }
1626 return lPorts
1627}
khenaidoo19d7b632018-10-30 10:49:50 -04001628
khenaidoo820197c2020-02-13 16:35:33 -05001629// GetDeviceRoutes returns device graph
1630func (agent *LogicalDeviceAgent) GetDeviceRoutes() *route.DeviceRoutes {
1631 return agent.deviceRoutes
khenaidoo19d7b632018-10-30 10:49:50 -04001632}
1633
khenaidoo820197c2020-02-13 16:35:33 -05001634//rebuildRoutes rebuilds the device routes
1635func (agent *LogicalDeviceAgent) buildRoutes(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001636 logger.Debugf("building-routes", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001637 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1638 return err
1639 }
1640 defer agent.requestQueue.RequestComplete()
1641
khenaidoo820197c2020-02-13 16:35:33 -05001642 if agent.deviceRoutes == nil {
1643 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001644 }
1645 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001646 lDevice := agent.getLogicalDeviceWithoutLock()
1647
khenaidoo820197c2020-02-13 16:35:33 -05001648 if err := agent.deviceRoutes.ComputeRoutes(ctx, lDevice.Ports); err != nil {
1649 return err
1650 }
1651 if err := agent.deviceRoutes.Print(); err != nil {
1652 return err
1653 }
1654
khenaidoo2c6a0992019-04-29 13:46:56 -04001655 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001656}
1657
khenaidoo820197c2020-02-13 16:35:33 -05001658//updateRoutes updates the device routes
1659func (agent *LogicalDeviceAgent) updateRoutes(ctx context.Context, lp *voltha.LogicalPort) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001660 logger.Debugw("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001661 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1662 return err
1663 }
1664 defer agent.requestQueue.RequestComplete()
1665
khenaidoo820197c2020-02-13 16:35:33 -05001666 if agent.deviceRoutes == nil {
1667 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001668 }
khenaidoo820197c2020-02-13 16:35:33 -05001669 if err := agent.deviceRoutes.AddPort(ctx, lp, agent.logicalDevice.Ports); err != nil {
1670 return err
khenaidoo0a822f92019-05-08 15:15:57 -04001671 }
khenaidoo820197c2020-02-13 16:35:33 -05001672 if err := agent.deviceRoutes.Print(); err != nil {
1673 return err
1674 }
1675 return nil
khenaidoo0a822f92019-05-08 15:15:57 -04001676}
1677
khenaidoofc1314d2019-03-14 09:34:21 -04001678// diff go over two lists of logical ports and return what's new, what's changed and what's removed.
khenaidoo910204f2019-04-08 17:56:40 -04001679func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001680 newPorts = make([]*voltha.LogicalPort, 0)
1681 changedPorts = make([]*voltha.LogicalPort, 0)
1682 deletedPorts = make([]*voltha.LogicalPort, 0)
1683 for _, o := range oldList {
1684 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001685 for _, n := range newList {
1686 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001687 found = true
1688 break
1689 }
1690 }
1691 if !found {
1692 deletedPorts = append(deletedPorts, o)
1693 }
khenaidoofc1314d2019-03-14 09:34:21 -04001694 }
1695 for _, n := range newList {
1696 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001697 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001698 for _, o := range oldList {
1699 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001700 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001701 found = true
1702 break
1703 }
1704 }
1705 if !found {
1706 newPorts = append(newPorts, n)
1707 }
khenaidoo2bc48282019-07-16 18:13:46 -04001708 if changed {
1709 changedPorts = append(changedPorts, n)
1710 }
khenaidoofc1314d2019-03-14 09:34:21 -04001711 }
1712 return
1713}
1714
1715// portUpdated is invoked when a port is updated on the logical device. Until
1716// the POST_ADD notification is fixed, we will use the logical device to
1717// update that data.
npujar467fe752020-01-16 20:17:45 +05301718func (agent *LogicalDeviceAgent) portUpdated(ctx context.Context, args ...interface{}) interface{} {
Girish Kumarf56a4682020-03-20 20:07:46 +00001719 logger.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
khenaidoofc1314d2019-03-14 09:34:21 -04001720
1721 var oldLD *voltha.LogicalDevice
1722 var newlD *voltha.LogicalDevice
1723
1724 var ok bool
1725 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +00001726 logger.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoofc1314d2019-03-14 09:34:21 -04001727 return nil
1728 }
1729 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +00001730 logger.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoofc1314d2019-03-14 09:34:21 -04001731 return nil
1732 }
1733
1734 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001735 logger.Debug("ports-have-not-changed")
khenaidoofc1314d2019-03-14 09:34:21 -04001736 return nil
1737 }
1738
1739 // Get the difference between the two list
1740 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1741
1742 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001743 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301744 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001745 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001746 }
1747 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301748 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001749 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001750 }
1751 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301752 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001753 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001754 }
1755
1756 return nil
1757}
1758
khenaidoo8f474192019-04-03 17:20:44 -04001759// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1760// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1761// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1762// scenario. This also applies to the case where the port was already added.
npujar467fe752020-01-16 20:17:45 +05301763func (agent *LogicalDeviceAgent) addNNILogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001764 logger.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001765 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
Girish Kumarf56a4682020-03-20 20:07:46 +00001766 logger.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
khenaidoo8f474192019-04-03 17:20:44 -04001767 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001768 }
khenaidoo442e7c72020-03-10 16:13:48 -04001769 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1770 return false, err
1771 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001772 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001773 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001774 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001775 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001776 }
khenaidoo442e7c72020-03-10 16:13:48 -04001777 agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001778
khenaidoofc1314d2019-03-14 09:34:21 -04001779 var portCap *ic.PortCapability
1780 var err error
1781 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301782 if portCap, err = agent.deviceMgr.getPortCapability(ctx, device.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001783 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001784 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001785 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001786
khenaidoo442e7c72020-03-10 16:13:48 -04001787 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1788 return false, err
1789 }
1790
1791 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001792 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1793 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001794 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001795 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001796 }
1797
khenaidoofc1314d2019-03-14 09:34:21 -04001798 portCap.Port.RootPort = true
1799 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1800 lp.DeviceId = device.Id
1801 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1802 lp.OfpPort.PortNo = port.PortNo
1803 lp.OfpPort.Name = lp.Id
1804 lp.DevicePortNo = port.PortNo
1805
khenaidoo6e55d9e2019-12-12 18:26:26 -05001806 ld := agent.getLogicalDeviceWithoutLock()
1807
khenaidoofc1314d2019-03-14 09:34:21 -04001808 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1809 if cloned.Ports == nil {
1810 cloned.Ports = make([]*voltha.LogicalPort, 0)
1811 }
1812 cloned.Ports = append(cloned.Ports, lp)
1813
npujar467fe752020-01-16 20:17:45 +05301814 if err = agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001815 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001816 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001817 }
khenaidoo910204f2019-04-08 17:56:40 -04001818
khenaidoo820197c2020-02-13 16:35:33 -05001819 // Update the device routes with this new logical port
khenaidoo910204f2019-04-08 17:56:40 -04001820 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001821 go func() {
1822 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001823 logger.Warnw("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": lp.OfpPort.PortNo, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001824 }
1825 }()
khenaidoo910204f2019-04-08 17:56:40 -04001826
khenaidoo8f474192019-04-03 17:20:44 -04001827 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001828}
1829
khenaidoo910204f2019-04-08 17:56:40 -04001830func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001831 ldevice := agent.getLogicalDeviceWithoutLock()
1832 for _, lPort := range ldevice.Ports {
1833 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1834 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001835 }
1836 }
1837 return false
1838}
1839
khenaidoo8f474192019-04-03 17:20:44 -04001840// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1841// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1842// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1843// scenario. This also applies to the case where the port was already added.
npujar467fe752020-01-16 20:17:45 +05301844func (agent *LogicalDeviceAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001845 logger.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001846 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
Girish Kumarf56a4682020-03-20 20:07:46 +00001847 logger.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
khenaidoo8f474192019-04-03 17:20:44 -04001848 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001849 }
khenaidoo442e7c72020-03-10 16:13:48 -04001850 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1851 return false, err
1852 }
1853
khenaidoo1ce37ad2019-03-24 22:07:24 -04001854 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001855 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001856 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001857 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001858 }
khenaidoo442e7c72020-03-10 16:13:48 -04001859 agent.requestQueue.RequestComplete()
khenaidoofc1314d2019-03-14 09:34:21 -04001860 var portCap *ic.PortCapability
1861 var err error
1862 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301863 if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001864 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001865 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001866 }
khenaidoo442e7c72020-03-10 16:13:48 -04001867 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1868 return false, err
1869 }
1870 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001871 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1872 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001873 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001874 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001875 }
khenaidoofc1314d2019-03-14 09:34:21 -04001876 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001877 ldevice := agent.getLogicalDeviceWithoutLock()
1878
Girish Kumarf56a4682020-03-20 20:07:46 +00001879 logger.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
npujar1d86a522019-11-14 17:11:16 +05301880 portCap.Port.RootPort = false
1881 portCap.Port.Id = port.Label
1882 portCap.Port.OfpPort.PortNo = port.PortNo
1883 portCap.Port.DeviceId = childDevice.Id
1884 portCap.Port.DevicePortNo = port.PortNo
1885 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1886 if cloned.Ports == nil {
1887 cloned.Ports = make([]*voltha.LogicalPort, 0)
1888 }
1889 cloned.Ports = append(cloned.Ports, portCap.Port)
npujar467fe752020-01-16 20:17:45 +05301890 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301891 return false, err
1892 }
1893 // Update the device graph with this new logical port
1894 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001895
1896 go func() {
1897 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001898 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001899 }
1900 }()
1901
npujar1d86a522019-11-14 17:11:16 +05301902 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001903}
1904
npujar467fe752020-01-16 20:17:45 +05301905func (agent *LogicalDeviceAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001906 logger.Debugw("packet-out", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001907 "packet": hex.EncodeToString(packet.Data),
1908 "inPort": packet.GetInPort(),
1909 })
khenaidoo68c930b2019-05-13 11:46:51 -04001910 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001911 //frame := packet.GetData()
1912 //TODO: Use a channel between the logical agent and the device agent
npujar467fe752020-01-16 20:17:45 +05301913 if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001914 logger.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001915 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001916}
1917
npujar1d86a522019-11-14 17:11:16 +05301918func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001919 logger.Debugw("packet-in", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001920 "port": port,
1921 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301922 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001923 })
khenaidoo68c930b2019-05-13 11:46:51 -04001924 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301925 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Girish Kumarf56a4682020-03-20 20:07:46 +00001926 logger.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001927}
khenaidoo2c6a0992019-04-29 13:46:56 -04001928
1929func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1930 agent.lockLogicalPortsNo.Lock()
1931 defer agent.lockLogicalPortsNo.Unlock()
1932 if exist := agent.logicalPortsNo[portNo]; !exist {
1933 agent.logicalPortsNo[portNo] = nniPort
1934 }
1935}
1936
khenaidoo820197c2020-02-13 16:35:33 -05001937func (agent *LogicalDeviceAgent) deleteLogicalPortsFromMap(portsNo []uint32) {
1938 agent.lockLogicalPortsNo.Lock()
1939 defer agent.lockLogicalPortsNo.Unlock()
1940 for _, pNo := range portsNo {
1941 delete(agent.logicalPortsNo, pNo)
1942 }
1943}
1944
khenaidoo3d3b8c22019-05-22 18:10:39 -04001945func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1946 agent.lockLogicalPortsNo.Lock()
1947 defer agent.lockLogicalPortsNo.Unlock()
1948 for _, lp := range lps {
1949 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1950 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1951 }
1952 }
1953}
1954
khenaidoo2c6a0992019-04-29 13:46:56 -04001955func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1956 agent.lockLogicalPortsNo.RLock()
1957 defer agent.lockLogicalPortsNo.RUnlock()
1958 if exist := agent.logicalPortsNo[portNo]; exist {
1959 return agent.logicalPortsNo[portNo]
1960 }
1961 return false
1962}
1963
1964func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1965 agent.lockLogicalPortsNo.RLock()
1966 defer agent.lockLogicalPortsNo.RUnlock()
1967 for portNo, nni := range agent.logicalPortsNo {
1968 if nni {
1969 return portNo, nil
1970 }
1971 }
1972 return 0, status.Error(codes.NotFound, "No NNI port found")
1973}
Esin Karaman09959ae2019-11-29 13:59:58 +00001974
1975//GetNNIPorts returns NNI ports.
1976func (agent *LogicalDeviceAgent) GetNNIPorts() []uint32 {
1977 agent.lockLogicalPortsNo.RLock()
1978 defer agent.lockLogicalPortsNo.RUnlock()
1979 nniPorts := make([]uint32, 0)
1980 for portNo, nni := range agent.logicalPortsNo {
1981 if nni {
1982 nniPorts = append(nniPorts, portNo)
1983 }
1984 }
1985 return nniPorts
1986}