blob: 743614a56ac2454a7107ed206d2dc236371a81fb [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"
khenaidoob9203542018-09-17 22:56:37 -040024 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050025 "github.com/opencord/voltha-go/db/model"
npujar1d86a522019-11-14 17:11:16 +053026 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo442e7c72020-03-10 16:13:48 -040027 "github.com/opencord/voltha-go/rw_core/route"
Scott Bakerb671a862019-10-24 10:53:40 -070028 coreutils "github.com/opencord/voltha-go/rw_core/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080029 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
32 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
33 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040034 "google.golang.org/grpc/codes"
35 "google.golang.org/grpc/status"
khenaidoo442e7c72020-03-10 16:13:48 -040036 "reflect"
37 "sync"
38 "time"
39)
40
41const (
42 maxOrderedLogicalDeviceRequestQueueSize = 1000
khenaidoob9203542018-09-17 22:56:37 -040043)
44
npujar1d86a522019-11-14 17:11:16 +053045// LogicalDeviceAgent represent attributes of logical device agent
khenaidoob9203542018-09-17 22:56:37 -040046type LogicalDeviceAgent struct {
npujar1d86a522019-11-14 17:11:16 +053047 logicalDeviceID string
48 rootDeviceID string
khenaidoo3306c992019-05-24 16:57:35 -040049 deviceMgr *DeviceManager
50 ldeviceMgr *LogicalDeviceManager
51 clusterDataProxy *model.Proxy
52 exitChannel chan int
khenaidoo820197c2020-02-13 16:35:33 -050053 deviceRoutes *route.DeviceRoutes
khenaidoo3306c992019-05-24 16:57:35 -040054 flowProxy *model.Proxy
55 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040056 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040057 ldProxy *model.Proxy
58 portProxies map[string]*model.Proxy
khenaidoo820197c2020-02-13 16:35:33 -050059 lockDeviceRoutes sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040060 logicalPortsNo map[uint32]bool //value is true for NNI port
61 lockLogicalPortsNo sync.RWMutex
62 flowDecomposer *fd.FlowDecomposer
khenaidoo442e7c72020-03-10 16:13:48 -040063 defaultTimeout time.Duration
khenaidoo6e55d9e2019-12-12 18:26:26 -050064 logicalDevice *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -040065 requestQueue *coreutils.RequestQueue
66 startOnce sync.Once
67 stopOnce sync.Once
khenaidoob9203542018-09-17 22:56:37 -040068}
69
npujar1d86a522019-11-14 17:11:16 +053070func newLogicalDeviceAgent(id string, deviceID string, ldeviceMgr *LogicalDeviceManager,
Stephane Barbarie1ab43272018-12-08 21:42:13 -050071 deviceMgr *DeviceManager,
khenaidoo442e7c72020-03-10 16:13:48 -040072 cdProxy *model.Proxy, timeout time.Duration) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040073 var agent LogicalDeviceAgent
74 agent.exitChannel = make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +053075 agent.logicalDeviceID = id
76 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040077 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040078 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040079 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040080 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoofc1314d2019-03-14 09:34:21 -040081 agent.portProxies = make(map[string]*model.Proxy)
khenaidoo2c6a0992019-04-29 13:46:56 -040082 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040083 agent.defaultTimeout = timeout
khenaidoo442e7c72020-03-10 16:13:48 -040084 agent.requestQueue = coreutils.NewRequestQueue(agent.logicalDeviceID, maxOrderedLogicalDeviceRequestQueueSize)
khenaidoob9203542018-09-17 22:56:37 -040085 return &agent
86}
87
khenaidoo4d4802d2018-10-04 21:59:49 -040088// start creates the logical device and add it to the data model
khenaidoo442e7c72020-03-10 16:13:48 -040089func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromDB bool) error {
90 needToStart := false
91 if agent.startOnce.Do(func() { needToStart = true }); !needToStart {
92 return nil
93 }
94
Girish Kumarf56a4682020-03-20 20:07:46 +000095 logger.Infow("starting-logical_device-agent", log.Fields{"logical-device-id": agent.logicalDeviceID, "load-from-db": loadFromDB})
khenaidoo442e7c72020-03-10 16:13:48 -040096
97 var startSucceeded bool
98 defer func() {
99 if !startSucceeded {
100 if err := agent.stop(ctx); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000101 logger.Errorw("failed-to-cleanup-after-unsuccessful-start", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo442e7c72020-03-10 16:13:48 -0400102 }
103 }
104 }()
105
106 // Launch the request queue - it will launch a go routine
107 agent.requestQueue.Start()
108
khenaidoo297cd252019-02-07 22:10:23 -0500109 var ld *voltha.LogicalDevice
khenaidoo442e7c72020-03-10 16:13:48 -0400110 if !loadFromDB {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400111 //Build the logical device based on information retrieved from the device adapter
112 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -0500113 var err error
npujar1d86a522019-11-14 17:11:16 +0530114 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -0400115 return err
116 }
npujar1d86a522019-11-14 17:11:16 +0530117 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -0500118
119 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
120 var datapathID uint64
npujar1d86a522019-11-14 17:11:16 +0530121 if datapathID, err = CreateDataPathID(agent.logicalDeviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500122 return err
123 }
124 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400125 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
Girish Kumarf56a4682020-03-20 20:07:46 +0000126 logger.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo7e3d8f12019-08-02 16:06:30 -0400127 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500128 ld.Flows = &ofp.Flows{Items: nil}
129 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoo49085352020-01-13 19:15:43 -0500130 ld.Ports = []*voltha.LogicalPort{}
khenaidoo297cd252019-02-07 22:10:23 -0500131
khenaidoo297cd252019-02-07 22:10:23 -0500132 // Save the logical device
Thomas Lee Se5a44012019-11-07 20:32:24 +0530133 added, err := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, "")
134 if err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530135 return err
136 }
137 if added == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000138 logger.Errorw("failed-to-add-logical-device", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500139 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000140 logger.Debugw("logicaldevice-created", log.Fields{"logical-device-id": agent.logicalDeviceID, "root-id": ld.RootDeviceId})
khenaidoo297cd252019-02-07 22:10:23 -0500141 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500142
143 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
khenaidoofc1314d2019-03-14 09:34:21 -0400144
khenaidoo442e7c72020-03-10 16:13:48 -0400145 // Setup the logicalports - internal processing, no need to propagate the client context
npujar1d86a522019-11-14 17:11:16 +0530146 go func() {
khenaidoo442e7c72020-03-10 16:13:48 -0400147 err := agent.setupLogicalPorts(context.Background())
npujar1d86a522019-11-14 17:11:16 +0530148 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000149 logger.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530150 }
151 }()
khenaidoo297cd252019-02-07 22:10:23 -0500152 } else {
153 // load from dB - the logical may not exist at this time. On error, just return and the calling function
154 // will destroy this agent.
npujar467fe752020-01-16 20:17:45 +0530155 logicalDevice, err := agent.clusterDataProxy.Get(ctx, "/logical_devices/"+agent.logicalDeviceID, 0, true, "")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530156 if err != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400157 return err
Thomas Lee Se5a44012019-11-07 20:32:24 +0530158 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500159 ld, ok := logicalDevice.(*voltha.LogicalDevice)
160 if !ok {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500161 return status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo297cd252019-02-07 22:10:23 -0500162 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500163 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530164 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400165
khenaidoo6e55d9e2019-12-12 18:26:26 -0500166 // Update the last data
167 agent.logicalDevice = proto.Clone(ld).(*voltha.LogicalDevice)
168
khenaidoo3d3b8c22019-05-22 18:10:39 -0400169 // Setup the local list of logical ports
170 agent.addLogicalPortsToMap(ld.Ports)
khenaidoob9203542018-09-17 22:56:37 -0400171 }
khenaidoofc1314d2019-03-14 09:34:21 -0400172
khenaidoo442e7c72020-03-10 16:13:48 -0400173 var err error
Thomas Lee Se5a44012019-11-07 20:32:24 +0530174 agent.flowProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400175 ctx,
npujar1d86a522019-11-14 17:11:16 +0530176 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400177 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530178 if err != nil {
Thomas Lee Se5a44012019-11-07 20:32:24 +0530179 return err
180 }
181 agent.meterProxy, err = agent.clusterDataProxy.CreateProxy(
Manikkaraj kb1a10922019-07-29 12:10:34 -0400182 ctx,
npujar1d86a522019-11-14 17:11:16 +0530183 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400184 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530185 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000186 logger.Errorw("failed-to-create-meter-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530187 return err
188 }
189 agent.groupProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400190 ctx,
npujar1d86a522019-11-14 17:11:16 +0530191 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400192 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530193 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000194 logger.Errorw("failed-to-create-group-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530195 return err
196 }
197 agent.ldProxy, err = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400198 ctx,
npujar1d86a522019-11-14 17:11:16 +0530199 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400200 false)
Thomas Lee Se5a44012019-11-07 20:32:24 +0530201 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000202 logger.Errorw("failed-to-create-logical-device-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530203 return err
204 }
khenaidoofc1314d2019-03-14 09:34:21 -0400205 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400206 if agent.ldProxy != nil {
npujar9a30c702019-11-14 17:06:39 +0530207 agent.ldProxy.RegisterCallback(model.PostUpdate, agent.portUpdated)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400208 } else {
khenaidoo3d3b8c22019-05-22 18:10:39 -0400209 return status.Error(codes.Internal, "logical-device-proxy-null")
210 }
khenaidoobcf205b2019-01-25 22:21:14 -0500211
khenaidoo820197c2020-02-13 16:35:33 -0500212 // 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 -0400213 if loadFromDB {
khenaidoo820197c2020-02-13 16:35:33 -0500214 go func() {
215 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000216 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -0500217 }
218 }()
khenaidoo4c9e5592019-09-09 16:20:41 -0400219 }
khenaidoo442e7c72020-03-10 16:13:48 -0400220 startSucceeded = true
221
khenaidoob9203542018-09-17 22:56:37 -0400222 return nil
223}
224
khenaidoo442e7c72020-03-10 16:13:48 -0400225// stop stops the logical device agent. This removes the logical device from the data model.
Thomas Lee Se5a44012019-11-07 20:32:24 +0530226func (agent *LogicalDeviceAgent) stop(ctx context.Context) error {
khenaidoo442e7c72020-03-10 16:13:48 -0400227 var returnErr error
228 agent.stopOnce.Do(func() {
Girish Kumarf56a4682020-03-20 20:07:46 +0000229 logger.Info("stopping-logical_device-agent")
khenaidoo8c3303d2019-02-13 14:59:39 -0500230
khenaidoo442e7c72020-03-10 16:13:48 -0400231 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
232 // This should never happen - an error is returned only if the agent is stopped and an agent is only stopped once.
233 returnErr = err
234 return
235 }
236 defer agent.requestQueue.RequestComplete()
237
238 //Remove the logical device from the model
239 if removed, err := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); err != nil {
240 returnErr = err
241 } else if removed == nil {
242 returnErr = status.Errorf(codes.Aborted, "failed-to-remove-logical-ldevice-%s", agent.logicalDeviceID)
243 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000244 logger.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400245 }
246
247 // Stop the request queue and request complete indication
248 agent.requestQueue.Stop()
249
250 close(agent.exitChannel)
251
Girish Kumarf56a4682020-03-20 20:07:46 +0000252 logger.Info("logical_device-agent-stopped")
khenaidoo442e7c72020-03-10 16:13:48 -0400253 })
254 return returnErr
khenaidoo4d4802d2018-10-04 21:59:49 -0400255}
256
khenaidoo6e55d9e2019-12-12 18:26:26 -0500257// GetLogicalDevice returns the latest logical device data
khenaidoo442e7c72020-03-10 16:13:48 -0400258func (agent *LogicalDeviceAgent) GetLogicalDevice(ctx context.Context) (*voltha.LogicalDevice, error) {
259 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
260 return nil, err
261 }
262 defer agent.requestQueue.RequestComplete()
263 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice), nil
khenaidoo92e62c52018-10-03 14:02:54 -0400264}
265
npujar1d86a522019-11-14 17:11:16 +0530266// ListLogicalDeviceFlows returns logical device flows
khenaidoo442e7c72020-03-10 16:13:48 -0400267func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows(ctx context.Context) (*ofp.Flows, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000268 logger.Debug("ListLogicalDeviceFlows")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500269
khenaidoo442e7c72020-03-10 16:13:48 -0400270 logicalDevice, err := agent.GetLogicalDevice(ctx)
271 if err != nil {
272 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400273 }
khenaidoo442e7c72020-03-10 16:13:48 -0400274 if logicalDevice.Flows == nil {
275 return &ofp.Flows{}, nil
276 }
277 return (proto.Clone(logicalDevice.Flows)).(*ofp.Flows), nil
khenaidoodd237172019-05-27 16:37:17 -0400278}
279
npujar1d86a522019-11-14 17:11:16 +0530280// ListLogicalDeviceMeters returns logical device meters
khenaidoo442e7c72020-03-10 16:13:48 -0400281func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters(ctx context.Context) (*ofp.Meters, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000282 logger.Debug("ListLogicalDeviceMeters")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500283
khenaidoo442e7c72020-03-10 16:13:48 -0400284 logicalDevice, err := agent.GetLogicalDevice(ctx)
285 if err != nil {
286 return nil, err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400287 }
khenaidoo442e7c72020-03-10 16:13:48 -0400288 if logicalDevice.Meters == nil {
289 return &ofp.Meters{}, nil
290 }
291 return (proto.Clone(logicalDevice.Meters)).(*ofp.Meters), nil
Manikkaraj kb1a10922019-07-29 12:10:34 -0400292}
293
npujar1d86a522019-11-14 17:11:16 +0530294// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoo442e7c72020-03-10 16:13:48 -0400295func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups(ctx context.Context) (*ofp.FlowGroups, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000296 logger.Debug("ListLogicalDeviceFlowGroups")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500297
khenaidoo442e7c72020-03-10 16:13:48 -0400298 logicalDevice, err := agent.GetLogicalDevice(ctx)
299 if err != nil {
300 return nil, err
khenaidoodd237172019-05-27 16:37:17 -0400301 }
khenaidoo442e7c72020-03-10 16:13:48 -0400302 if logicalDevice.FlowGroups == nil {
303 return &ofp.FlowGroups{}, nil
304 }
305 return (proto.Clone(logicalDevice.FlowGroups)).(*ofp.FlowGroups), nil
khenaidoodd237172019-05-27 16:37:17 -0400306}
307
npujar1d86a522019-11-14 17:11:16 +0530308// ListLogicalDevicePorts returns logical device ports
khenaidoo442e7c72020-03-10 16:13:48 -0400309func (agent *LogicalDeviceAgent) ListLogicalDevicePorts(ctx context.Context) (*voltha.LogicalPorts, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000310 logger.Debug("ListLogicalDevicePorts")
khenaidoo442e7c72020-03-10 16:13:48 -0400311 logicalDevice, err := agent.GetLogicalDevice(ctx)
312 if err != nil {
313 return nil, err
314 }
315 if logicalDevice == nil {
316 return &voltha.LogicalPorts{}, nil
317 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500318 lPorts := make([]*voltha.LogicalPort, 0)
319 lPorts = append(lPorts, logicalDevice.Ports...)
khenaidoo442e7c72020-03-10 16:13:48 -0400320 return &voltha.LogicalPorts{Items: lPorts}, nil
khenaidoo19d7b632018-10-30 10:49:50 -0400321}
322
khenaidoo4c9e5592019-09-09 16:20:41 -0400323//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
npujar467fe752020-01-16 20:17:45 +0530324func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(ctx context.Context, flows *ofp.Flows) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500325 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400326
Girish Kumarf56a4682020-03-20 20:07:46 +0000327 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500328 ld.Flows = flows
329
npujar467fe752020-01-16 20:17:45 +0530330 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000331 logger.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400332 return err
khenaidoo43c82122018-11-22 18:38:28 -0500333 }
khenaidoo43c82122018-11-22 18:38:28 -0500334 return nil
335}
336
khenaidoo4c9e5592019-09-09 16:20:41 -0400337//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
npujar467fe752020-01-16 20:17:45 +0530338func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(ctx context.Context, meters *ofp.Meters) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500339 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400340
Girish Kumarf56a4682020-03-20 20:07:46 +0000341 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500342 ld.Meters = meters
343
npujar467fe752020-01-16 20:17:45 +0530344 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000345 logger.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400346 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400347 }
348 return nil
349}
350
khenaidoo4c9e5592019-09-09 16:20:41 -0400351//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
npujar467fe752020-01-16 20:17:45 +0530352func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(ctx context.Context, flowGroups *ofp.FlowGroups) error {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500353 ld := agent.getLogicalDeviceWithoutLock()
khenaidoo4c9e5592019-09-09 16:20:41 -0400354
Girish Kumarf56a4682020-03-20 20:07:46 +0000355 logger.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
khenaidoo6e55d9e2019-12-12 18:26:26 -0500356 ld.FlowGroups = flowGroups
357
npujar467fe752020-01-16 20:17:45 +0530358 if err := agent.updateLogicalDeviceWithoutLock(ctx, ld); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000359 logger.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
khenaidoo4c9e5592019-09-09 16:20:41 -0400360 return err
khenaidoo43c82122018-11-22 18:38:28 -0500361 }
khenaidoo43c82122018-11-22 18:38:28 -0500362 return nil
363}
364
khenaidoo6e55d9e2019-12-12 18:26:26 -0500365// getLogicalDeviceWithoutLock returns a cloned logical device to a function that already holds the agent lock.
366func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() *voltha.LogicalDevice {
Girish Kumarf56a4682020-03-20 20:07:46 +0000367 logger.Debug("getLogicalDeviceWithoutLock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500368 return proto.Clone(agent.logicalDevice).(*voltha.LogicalDevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400369}
370
npujar467fe752020-01-16 20:17:45 +0530371func (agent *LogicalDeviceAgent) updateLogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000372 logger.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
khenaidoo2c6a0992019-04-29 13:46:56 -0400373 var err error
374 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530375 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400376 return err
377 }
378 agent.addLogicalPortToMap(port.PortNo, true)
379 } else if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530380 if _, err = agent.addUNILogicalPort(ctx, device, port); err != nil {
khenaidoo2c6a0992019-04-29 13:46:56 -0400381 return err
382 }
383 agent.addLogicalPortToMap(port.PortNo, false)
384 } else {
khenaidoo820197c2020-02-13 16:35:33 -0500385 // Update the device routes to ensure all routes on the logical device have been calculated
386 if err = agent.buildRoutes(ctx); err != nil {
387 // Not an error - temporary state
Girish Kumarf56a4682020-03-20 20:07:46 +0000388 logger.Warnw("failed-to-update-routes", log.Fields{"device-id": device.Id, "port": port, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400389 }
390 }
391 return nil
392}
393
khenaidoo3d3b8c22019-05-22 18:10:39 -0400394// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
395// added to it. While the logical device was being created we could have received requests to add
396// NNI and UNI ports which were discarded. Now is the time to add them if needed
397func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000398 logger.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400399 // First add any NNI ports which could have been missing
npujar467fe752020-01-16 20:17:45 +0530400 if err := agent.setupNNILogicalPorts(ctx, agent.rootDeviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000401 logger.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400402 return err
403 }
404
405 // Now, set up the UNI ports if needed.
npujar467fe752020-01-16 20:17:45 +0530406 children, err := agent.deviceMgr.getAllChildDevices(ctx, agent.rootDeviceID)
npujar1d86a522019-11-14 17:11:16 +0530407 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000408 logger.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400409 return err
npujar1d86a522019-11-14 17:11:16 +0530410 }
411 responses := make([]coreutils.Response, 0)
412 for _, child := range children.Items {
413 response := coreutils.NewResponse()
414 responses = append(responses, response)
415 go func(child *voltha.Device) {
khenaidoo442e7c72020-03-10 16:13:48 -0400416 if err = agent.setupUNILogicalPorts(context.Background(), child); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000417 logger.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
npujar1d86a522019-11-14 17:11:16 +0530418 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
419 }
420 response.Done()
421 }(child)
422 }
423 // Wait for completion
424 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
425 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400426 }
427 return nil
428}
429
khenaidoofc1314d2019-03-14 09:34:21 -0400430// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530431func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000432 logger.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400433 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400434 var err error
435
436 var device *voltha.Device
npujar467fe752020-01-16 20:17:45 +0530437 if device, err = agent.deviceMgr.GetDevice(ctx, deviceID); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000438 logger.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400439 return err
440 }
441
442 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400443 for _, port := range device.Ports {
444 if port.Type == voltha.Port_ETHERNET_NNI {
npujar467fe752020-01-16 20:17:45 +0530445 if _, err = agent.addNNILogicalPort(ctx, device, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000446 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400447 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400448 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400449 }
450 }
khenaidoofc1314d2019-03-14 09:34:21 -0400451 return err
452}
453
khenaidoo171b98e2019-10-31 11:48:15 -0400454// updatePortState updates the port state of the device
npujar467fe752020-01-16 20:17:45 +0530455func (agent *LogicalDeviceAgent) updatePortState(ctx context.Context, deviceID string, portNo uint32, operStatus voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000456 logger.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo442e7c72020-03-10 16:13:48 -0400457 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
458 return err
459 }
460 defer agent.requestQueue.RequestComplete()
khenaidoo171b98e2019-10-31 11:48:15 -0400461 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500462 cloned := agent.getLogicalDeviceWithoutLock()
463 for idx, lPort := range cloned.Ports {
npujar1d86a522019-11-14 17:11:16 +0530464 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
npujar1d86a522019-11-14 17:11:16 +0530465 if operStatus == voltha.OperStatus_ACTIVE {
466 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
467 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
468 } else {
469 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
470 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
471 }
472 // Update the logical device
npujar467fe752020-01-16 20:17:45 +0530473 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000474 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
npujar1d86a522019-11-14 17:11:16 +0530475 return err
476 }
477 return nil
478 }
479 }
480 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400481}
482
khenaidoo3ab34882019-05-02 21:33:30 -0400483// updatePortsState updates the ports state related to the device
kesavandbc2d1622020-01-21 00:42:01 -0500484func (agent *LogicalDeviceAgent) updatePortsState(ctx context.Context, device *voltha.Device, state voltha.OperStatus_Types) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000485 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400486 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
487 return err
488 }
489 defer agent.requestQueue.RequestComplete()
khenaidoo3ab34882019-05-02 21:33:30 -0400490 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500491 cloned := agent.getLogicalDeviceWithoutLock()
npujar1d86a522019-11-14 17:11:16 +0530492 for _, lport := range cloned.Ports {
493 if lport.DeviceId == device.Id {
kesavandbc2d1622020-01-21 00:42:01 -0500494 if state == voltha.OperStatus_ACTIVE {
npujar1d86a522019-11-14 17:11:16 +0530495 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
496 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
kesavandbc2d1622020-01-21 00:42:01 -0500497 } else {
npujar1d86a522019-11-14 17:11:16 +0530498 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
499 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
khenaidoo3ab34882019-05-02 21:33:30 -0400500 }
kesavandbc2d1622020-01-21 00:42:01 -0500501
khenaidoo3ab34882019-05-02 21:33:30 -0400502 }
npujar1d86a522019-11-14 17:11:16 +0530503 }
504 // Updating the logical device will trigger the poprt change events to be populated to the controller
npujar467fe752020-01-16 20:17:45 +0530505 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000506 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
npujar1d86a522019-11-14 17:11:16 +0530507 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400508 }
509 return nil
510}
511
khenaidoofc1314d2019-03-14 09:34:21 -0400512// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
513func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000514 logger.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400515 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400516 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400517 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400518 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400519 for _, port := range childDevice.Ports {
520 if port.Type == voltha.Port_ETHERNET_UNI {
npujar467fe752020-01-16 20:17:45 +0530521 if added, err = agent.addUNILogicalPort(ctx, childDevice, port); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000522 logger.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400523 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400524 if added {
525 agent.addLogicalPortToMap(port.PortNo, false)
526 }
khenaidoo19d7b632018-10-30 10:49:50 -0400527 }
528 }
khenaidoofc1314d2019-03-14 09:34:21 -0400529 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400530}
531
Girish Gowdra408cd962020-03-11 14:31:31 -0700532// deleteAllLogicalPorts deletes all logical ports associated with this logical device
533func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000534 logger.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400535 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
536 return err
537 }
538 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -0400539 // Get the latest logical device info
khenaidoo6e55d9e2019-12-12 18:26:26 -0500540 ld := agent.getLogicalDeviceWithoutLock()
541
npujar1d86a522019-11-14 17:11:16 +0530542 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
Girish Gowdra408cd962020-03-11 14:31:31 -0700543 var updateLogicalPorts []*voltha.LogicalPort
544 // Update an empty ports slice to remove all the ports
545 cloned.Ports = updateLogicalPorts
546
547 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000548 logger.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
Girish Gowdra408cd962020-03-11 14:31:31 -0700549 return err
khenaidoo0a822f92019-05-08 15:15:57 -0400550 }
551 return nil
552}
553
Hardik Windlassc704def2020-02-26 18:23:19 +0000554// deleteAllUNILogicalPorts deletes all UNI logical ports associated with this parent device
555func (agent *LogicalDeviceAgent) deleteAllUNILogicalPorts(ctx context.Context, parentDevice *voltha.Device) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000556 logger.Debugw("delete-all-uni-logical-ports", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400557 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
558 return err
559 }
560 defer agent.requestQueue.RequestComplete()
Hardik Windlassc704def2020-02-26 18:23:19 +0000561 // Get the latest logical device info
562 ld := agent.getLogicalDeviceWithoutLock()
563
564 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
565 updateLogicalPorts := []*voltha.LogicalPort{}
566 for _, lport := range cloned.Ports {
567 // Save NNI ports only
568 if agent.isNNIPort(lport.DevicePortNo) {
569 updateLogicalPorts = append(updateLogicalPorts, lport)
570 }
571 }
572 if len(updateLogicalPorts) < len(cloned.Ports) {
573 cloned.Ports = updateLogicalPorts
574 // Updating the logical device will trigger the port change events to be populated to the controller
575 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
576 return err
577 }
578 } else {
Girish Kumarf56a4682020-03-20 20:07:46 +0000579 logger.Debugw("no-change-required", log.Fields{"logical-device-id": agent.logicalDeviceID})
Hardik Windlassc704def2020-02-26 18:23:19 +0000580 }
581 return nil
582}
583
khenaidoo92e62c52018-10-03 14:02:54 -0400584//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
npujar467fe752020-01-16 20:17:45 +0530585func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(ctx context.Context, logicalDevice *voltha.LogicalDevice) error {
586 updateCtx := context.WithValue(ctx, model.RequestTimestamp, time.Now().UnixNano())
Thomas Lee Se5a44012019-11-07 20:32:24 +0530587 afterUpdate, err := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
588 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000589 logger.Errorw("failed-to-update-logical-devices-to-cluster-proxy", log.Fields{"error": err})
Thomas Lee Se5a44012019-11-07 20:32:24 +0530590 return err
591 }
khenaidoo92e62c52018-10-03 14:02:54 -0400592 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530593 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400594 }
khenaidoo442e7c72020-03-10 16:13:48 -0400595 //agent.logicalDevice = (proto.Clone(logicalDevice)).(*voltha.LogicalDevice)
596 agent.logicalDevice = logicalDevice
597
khenaidoo92e62c52018-10-03 14:02:54 -0400598 return nil
599}
600
khenaidoo820197c2020-02-13 16:35:33 -0500601//generateDeviceRoutesIfNeeded generates the device routes if the logical device has been updated since the last time
khenaidoo4c9e5592019-09-09 16:20:41 -0400602//that device graph was generated.
khenaidoo820197c2020-02-13 16:35:33 -0500603func (agent *LogicalDeviceAgent) generateDeviceRoutesIfNeeded(ctx context.Context) error {
604 agent.lockDeviceRoutes.Lock()
605 defer agent.lockDeviceRoutes.Unlock()
606
khenaidoo442e7c72020-03-10 16:13:48 -0400607 ld, err := agent.GetLogicalDevice(ctx)
608 if err != nil {
609 return err
610 }
khenaidoo820197c2020-02-13 16:35:33 -0500611
612 if agent.deviceRoutes != nil && agent.deviceRoutes.IsUpToDate(ld) {
npujar1d86a522019-11-14 17:11:16 +0530613 return nil
614 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000615 logger.Debug("Generation of device route required")
khenaidoo820197c2020-02-13 16:35:33 -0500616 if err := agent.buildRoutes(ctx); err != nil {
617 return err
618 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400619 return nil
620}
621
khenaidoo19d7b632018-10-30 10:49:50 -0400622//updateFlowTable updates the flow table of that logical device
623func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000624 logger.Debug("updateFlowTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400625 if flow == nil {
626 return nil
627 }
khenaidoo820197c2020-02-13 16:35:33 -0500628 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400629 return err
630 }
khenaidoo19d7b632018-10-30 10:49:50 -0400631 switch flow.GetCommand() {
632 case ofp.OfpFlowModCommand_OFPFC_ADD:
npujar467fe752020-01-16 20:17:45 +0530633 return agent.flowAdd(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400634 case ofp.OfpFlowModCommand_OFPFC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530635 return agent.flowDelete(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400636 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
npujar467fe752020-01-16 20:17:45 +0530637 return agent.flowDeleteStrict(ctx, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400638 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
639 return agent.flowModify(flow)
640 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
641 return agent.flowModifyStrict(flow)
642 }
643 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530644 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400645}
646
647//updateGroupTable updates the group table of that logical device
648func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000649 logger.Debug("updateGroupTable")
khenaidoo19d7b632018-10-30 10:49:50 -0400650 if groupMod == nil {
651 return nil
652 }
khenaidoo820197c2020-02-13 16:35:33 -0500653 if err := agent.generateDeviceRoutesIfNeeded(ctx); err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400654 return err
655 }
khenaidoo820197c2020-02-13 16:35:33 -0500656
khenaidoo19d7b632018-10-30 10:49:50 -0400657 switch groupMod.GetCommand() {
658 case ofp.OfpGroupModCommand_OFPGC_ADD:
npujar467fe752020-01-16 20:17:45 +0530659 return agent.groupAdd(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400660 case ofp.OfpGroupModCommand_OFPGC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530661 return agent.groupDelete(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400662 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530663 return agent.groupModify(ctx, groupMod)
khenaidoo19d7b632018-10-30 10:49:50 -0400664 }
665 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530666 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400667}
668
Manikkaraj kb1a10922019-07-29 12:10:34 -0400669// updateMeterTable updates the meter table of that logical device
670func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000671 logger.Debug("updateMeterTable")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400672 if meterMod == nil {
673 return nil
674 }
675 switch meterMod.GetCommand() {
676 case ofp.OfpMeterModCommand_OFPMC_ADD:
npujar467fe752020-01-16 20:17:45 +0530677 return agent.meterAdd(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400678 case ofp.OfpMeterModCommand_OFPMC_DELETE:
npujar467fe752020-01-16 20:17:45 +0530679 return agent.meterDelete(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400680 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
npujar467fe752020-01-16 20:17:45 +0530681 return agent.meterModify(ctx, meterMod)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400682 }
683 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530684 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400685
686}
687
npujar467fe752020-01-16 20:17:45 +0530688func (agent *LogicalDeviceAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000689 logger.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400690 if meterMod == nil {
691 return nil
692 }
khenaidoo442e7c72020-03-10 16:13:48 -0400693 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
694 return err
695 }
696 defer agent.requestQueue.RequestComplete()
Girish Kumarf56a4682020-03-20 20:07:46 +0000697 logger.Debug("Acquired logical device lock")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500698 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400699
700 var meters []*ofp.OfpMeterEntry
701 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
702 meters = lDevice.Meters.Items
703 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000704 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400705
706 for _, meter := range meters {
707 if meterMod.MeterId == meter.Config.MeterId {
Girish Kumarf56a4682020-03-20 20:07:46 +0000708 logger.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400709 return nil
710 }
711 }
712
713 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
714 meters = append(meters, meterEntry)
715 //Update model
npujar467fe752020-01-16 20:17:45 +0530716 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, &ofp.Meters{Items: meters}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000717 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400718 return err
719 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000720 logger.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400721 return nil
722}
723
npujar467fe752020-01-16 20:17:45 +0530724func (agent *LogicalDeviceAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000725 logger.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400726 if meterMod == nil {
727 return nil
728 }
khenaidoo442e7c72020-03-10 16:13:48 -0400729 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
730 return err
731 }
732 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400733
khenaidoo6e55d9e2019-12-12 18:26:26 -0500734 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400735
736 var meters []*ofp.OfpMeterEntry
737 var flows []*ofp.OfpFlowStats
738 updatedFlows := make([]*ofp.OfpFlowStats, 0)
739 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
740 meters = lDevice.Meters.Items
741 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400742
743 changedMeter := false
744 changedFow := false
Girish Kumarf56a4682020-03-20 20:07:46 +0000745 logger.Debugw("Available meters", log.Fields{"meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400746 for index, meter := range meters {
747 if meterMod.MeterId == meter.Config.MeterId {
748 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530749 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400750 meters = append(meters[:index], meters[index+1:]...)
Girish Kumarf56a4682020-03-20 20:07:46 +0000751 logger.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400752 changedMeter = true
753 break
754 }
755 }
756 if changedMeter {
757 //Update model
758 metersToUpdate := &ofp.Meters{}
759 if lDevice.Meters != nil {
760 metersToUpdate = &ofp.Meters{Items: meters}
761 }
npujar467fe752020-01-16 20:17:45 +0530762 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000763 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400764 return err
765 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000766 logger.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400767
768 }
769 if changedFow {
770 //Update model
npujar467fe752020-01-16 20:17:45 +0530771 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: updatedFlows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000772 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400773 return err
774 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000775 logger.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
Manikkaraj kb1a10922019-07-29 12:10:34 -0400776 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
777 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000778 logger.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400779 return nil
780}
781
npujar467fe752020-01-16 20:17:45 +0530782func (agent *LogicalDeviceAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000783 logger.Debug("meterModify")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400784 if meterMod == nil {
785 return nil
786 }
khenaidoo442e7c72020-03-10 16:13:48 -0400787 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
788 return err
789 }
790 defer agent.requestQueue.RequestComplete()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400791
khenaidoo6e55d9e2019-12-12 18:26:26 -0500792 lDevice := agent.getLogicalDeviceWithoutLock()
Manikkaraj kb1a10922019-07-29 12:10:34 -0400793
794 var meters []*ofp.OfpMeterEntry
795 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
796 meters = lDevice.Meters.Items
797 }
798 changedMeter := false
799 for index, meter := range meters {
800 if meterMod.MeterId == meter.Config.MeterId {
801 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
802 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
803 meters[index] = newmeterEntry
804 changedMeter = true
Girish Kumarf56a4682020-03-20 20:07:46 +0000805 logger.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400806 break
807 }
808 }
809 if changedMeter {
810 //Update model
811 metersToUpdate := &ofp.Meters{}
812 if lDevice.Meters != nil {
813 metersToUpdate = &ofp.Meters{Items: meters}
814 }
npujar467fe752020-01-16 20:17:45 +0530815 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000816 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400817 return err
818 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000819 logger.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400820 return nil
821 }
822
Girish Kumarf56a4682020-03-20 20:07:46 +0000823 logger.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530824 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400825
826}
827
npujar1d86a522019-11-14 17:11:16 +0530828func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
Girish Kumarf56a4682020-03-20 20:07:46 +0000829 logger.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400830 changed := false
831 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
832 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530833 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Girish Kumarf56a4682020-03-20 20:07:46 +0000834 logger.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400835 flows = append(flows[:index], flows[index+1:]...)
836 changed = true
837 }
838 }
839 return changed, flows
840}
841
842func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
843
844 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530845 meterID := fu.GetMeterIdFromFlow(flow)
Girish Kumarf56a4682020-03-20 20:07:46 +0000846 logger.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
npujar1d86a522019-11-14 17:11:16 +0530847 if meterID == 0 {
Girish Kumarf56a4682020-03-20 20:07:46 +0000848 logger.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400849 return false
850 }
851 if meters == nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000852 logger.Debug("No meters present in logical device")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400853 return false
854 }
855 changedMeter := false
856 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530857 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400858 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530859 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400860 changedMeter = true
861 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530862 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400863 changedMeter = true
864 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000865 logger.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400866 break
867 }
868 }
869 return changedMeter
870}
871
khenaidoo19d7b632018-10-30 10:49:50 -0400872//flowAdd adds a flow to the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +0530873func (agent *LogicalDeviceAgent) flowAdd(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +0000874 logger.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400875 if mod == nil {
876 return nil
877 }
khenaidoo442e7c72020-03-10 16:13:48 -0400878 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
879 return err
880 }
881 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -0400882
khenaidoo6e55d9e2019-12-12 18:26:26 -0500883 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -0400884
885 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400886 var meters []*ofp.OfpMeterEntry
887 var flow *ofp.OfpFlowStats
Scott Bakerfdea1e32020-02-21 15:35:41 -0800888 var err error
Manikkaraj kb1a10922019-07-29 12:10:34 -0400889
khenaidoo19d7b632018-10-30 10:49:50 -0400890 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
891 flows = lDevice.Flows.Items
892 }
893
Manikkaraj kb1a10922019-07-29 12:10:34 -0400894 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
895 meters = lDevice.Meters.Items
896 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400897 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400898 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400899 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400900 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
901 if checkOverlap {
902 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
903 // TODO: should this error be notified other than being logged?
Girish Kumarf56a4682020-03-20 20:07:46 +0000904 logger.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400905 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400906 // Add flow
Scott Bakerfdea1e32020-02-21 15:35:41 -0800907 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
908 if err != nil {
909 return err
910 }
khenaidoo19d7b632018-10-30 10:49:50 -0400911 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400912 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400913 changed = true
914 }
915 } else {
Scott Bakerfdea1e32020-02-21 15:35:41 -0800916 flow, err = fu.FlowStatsEntryFromFlowModMessage(mod)
917 if err != nil {
918 return err
919 }
khenaidoo19d7b632018-10-30 10:49:50 -0400920 idx := fu.FindFlows(flows, flow)
921 if idx >= 0 {
922 oldFlow := flows[idx]
923 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
924 flow.ByteCount = oldFlow.ByteCount
925 flow.PacketCount = oldFlow.PacketCount
926 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400927 if !reflect.DeepEqual(oldFlow, flow) {
928 flows[idx] = flow
929 updatedFlows = append(updatedFlows, flow)
930 changed = true
931 updated = true
932 }
933 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400934 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400935 updatedFlows = append(updatedFlows, flow)
936 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400937 }
khenaidoo19d7b632018-10-30 10:49:50 -0400938 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000939 logger.Debugw("flowAdd-changed", log.Fields{"changed": changed})
khenaidoo4c9e5592019-09-09 16:20:41 -0400940
khenaidoo19d7b632018-10-30 10:49:50 -0400941 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400942 var flowMetadata voltha.FlowMetadata
943 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 +0000944 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400945 return err
946 }
khenaidoo820197c2020-02-13 16:35:33 -0500947 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
948 if err != nil {
949 return err
950 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000951 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -0400952
khenaidoo19d7b632018-10-30 10:49:50 -0400953 // Update model
npujar467fe752020-01-16 20:17:45 +0530954 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000955 logger.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400956 return err
957 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400958 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400959 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
960 metersToUpdate := &ofp.Meters{}
961 if lDevice.Meters != nil {
962 metersToUpdate = &ofp.Meters{Items: meters}
963 }
964 if changedMeterStats {
965 //Update model
npujar467fe752020-01-16 20:17:45 +0530966 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000967 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400968 return err
969 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000970 logger.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400971
972 }
973 }
khenaidoo442e7c72020-03-10 16:13:48 -0400974 // Send the flows to the devices
975 respChannels := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &flowMetadata)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400976
khenaidoo442e7c72020-03-10 16:13:48 -0400977 // Create the go routines to wait
978 go func() {
979 // Wait for completion
980 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChannels...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000981 logger.Warnw("failure-to-add-flows", log.Fields{"errors": res, "logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -0400982 // TODO : revert added flow
983 }
984 }()
khenaidoo19d7b632018-10-30 10:49:50 -0400985 }
khenaidoo19d7b632018-10-30 10:49:50 -0400986 return nil
987}
988
npujar1d86a522019-11-14 17:11:16 +0530989// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400990func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
991 m := make(map[uint32]bool)
992 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530993 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400994 foundMeter := false
995 // Meter is present in the flow , Get from logical device
996 for _, meter := range meters {
997 if flowMeterID == meter.Config.MeterId {
998 metadata.Meters = append(metadata.Meters, meter.Config)
Girish Kumarf56a4682020-03-20 20:07:46 +0000999 logger.Debugw("Found meter in logical device",
Manikkaraj kb1a10922019-07-29 12:10:34 -04001000 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
1001 m[flowMeterID] = true
1002 foundMeter = true
1003 break
1004 }
1005 }
1006 if !foundMeter {
Girish Kumarf56a4682020-03-20 20:07:46 +00001007 logger.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +05301008 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001009 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
1010 }
1011 }
1012 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001013 logger.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001014 return nil
1015
1016}
1017
khenaidoo19d7b632018-10-30 10:49:50 -04001018//flowDelete deletes a flow from the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +05301019func (agent *LogicalDeviceAgent) flowDelete(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001020 logger.Debug("flowDelete")
khenaidoo19d7b632018-10-30 10:49:50 -04001021 if mod == nil {
1022 return nil
1023 }
khenaidoo442e7c72020-03-10 16:13:48 -04001024 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1025 return err
1026 }
1027 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001028
khenaidoo6e55d9e2019-12-12 18:26:26 -05001029 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001030
Manikkaraj kb1a10922019-07-29 12:10:34 -04001031 var meters []*ofp.OfpMeterEntry
1032 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001033 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -04001034
1035 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1036 flows = lDevice.Flows.Items
1037 }
1038
1039 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1040 meters = lDevice.Meters.Items
1041 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001042
1043 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
1044 flowGroups = lDevice.FlowGroups.Items
1045 }
1046
khenaidoo19d7b632018-10-30 10:49:50 -04001047 //build a list of what to keep vs what to delete
1048 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -04001049 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001050 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -04001051 // Check whether the flow and the flowmod matches
Scott Bakerfdea1e32020-02-21 15:35:41 -08001052 fs, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1053 if err != nil {
1054 return err
1055 }
1056 if fu.FlowMatch(f, fs) {
khenaidoo0458db62019-06-20 08:50:36 -04001057 toDelete = append(toDelete, f)
1058 continue
1059 }
1060 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -04001061 if !fu.FlowMatchesMod(f, mod) {
1062 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -04001063 } else {
1064 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -04001065 }
1066 }
1067
Girish Kumarf56a4682020-03-20 20:07:46 +00001068 logger.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -04001069
khenaidoo19d7b632018-10-30 10:49:50 -04001070 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -04001071 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -04001072 var flowMetadata voltha.FlowMetadata
1073 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
Girish Kumarf56a4682020-03-20 20:07:46 +00001074 logger.Error("Meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001075 return errors.New("Meter-referred-in-flows-not-present")
1076 }
khenaidoo820197c2020-02-13 16:35:33 -05001077 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{Items: flowGroups})
1078 if err != nil {
1079 return err
1080 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001081 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001082
npujar467fe752020-01-16 20:17:45 +05301083 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: toKeep}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001084 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001085 return err
1086 }
khenaidoo442e7c72020-03-10 16:13:48 -04001087
1088 // Update the devices
1089 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1090
1091 // Wait for the responses
1092 go func() {
1093 // Wait for completion
1094 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001095 logger.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001096 // TODO: Revert the flow deletion
1097 }
1098 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001099 }
1100
1101 //TODO: send announcement on delete
1102 return nil
1103}
1104
khenaidoo442e7c72020-03-10 16:13:48 -04001105func (agent *LogicalDeviceAgent) addFlowsAndGroupsToDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001106 logger.Debugw("send-add-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001107
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001108 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301109 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001110 response := coreutils.NewResponse()
1111 responses = append(responses, response)
1112 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001113 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1114 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301115 if err := agent.deviceMgr.addFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001116 logger.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001117 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001118 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001119 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301120 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001121 }
khenaidoo442e7c72020-03-10 16:13:48 -04001122 // Return responses (an array of channels) for the caller to wait for a response from the far end.
1123 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001124}
khenaidoo19d7b632018-10-30 10:49:50 -04001125
khenaidoo442e7c72020-03-10 16:13:48 -04001126func (agent *LogicalDeviceAgent) deleteFlowsAndGroupsFromDevices(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001127 logger.Debugw("send-delete-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001128
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001129 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301130 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001131 response := coreutils.NewResponse()
1132 responses = append(responses, response)
1133 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001134 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1135 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301136 if err := agent.deviceMgr.deleteFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001137 logger.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001138 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001139 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001140 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301141 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001142 }
khenaidoo442e7c72020-03-10 16:13:48 -04001143 return responses
khenaidoo0458db62019-06-20 08:50:36 -04001144}
1145
khenaidoo442e7c72020-03-10 16:13:48 -04001146func (agent *LogicalDeviceAgent) updateFlowsAndGroupsOfDevice(ctx context.Context, deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) []coreutils.Response {
Girish Kumarf56a4682020-03-20 20:07:46 +00001147 logger.Debugw("send-update-flows-to-device-manager", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001148
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001149 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301150 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001151 response := coreutils.NewResponse()
1152 responses = append(responses, response)
1153 go func(deviceId string, value *fu.FlowsAndGroups) {
khenaidoo442e7c72020-03-10 16:13:48 -04001154 ctx, cancel := context.WithTimeout(context.Background(), agent.defaultTimeout)
1155 defer cancel()
npujar467fe752020-01-16 20:17:45 +05301156 if err := agent.deviceMgr.updateFlowsAndGroups(ctx, deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001157 logger.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001158 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001159 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001160 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301161 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001162 }
khenaidoo442e7c72020-03-10 16:13:48 -04001163 return responses
khenaidoo19d7b632018-10-30 10:49:50 -04001164}
1165
1166//flowDeleteStrict deletes a flow from the flow table of that logical device
npujar467fe752020-01-16 20:17:45 +05301167func (agent *LogicalDeviceAgent) flowDeleteStrict(ctx context.Context, mod *ofp.OfpFlowMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001168 logger.Debug("flowDeleteStrict")
khenaidoo19d7b632018-10-30 10:49:50 -04001169 if mod == nil {
1170 return nil
1171 }
khenaidoo442e7c72020-03-10 16:13:48 -04001172 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1173 return err
1174 }
1175 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001176
khenaidoo6e55d9e2019-12-12 18:26:26 -05001177 lDevice := agent.getLogicalDeviceWithoutLock()
1178
Manikkaraj kb1a10922019-07-29 12:10:34 -04001179 var meters []*ofp.OfpMeterEntry
1180 var flows []*ofp.OfpFlowStats
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001181 var flowGroups []*ofp.OfpGroupEntry
Manikkaraj kb1a10922019-07-29 12:10:34 -04001182 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1183 meters = lDevice.Meters.Items
1184 }
1185 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1186 flows = lDevice.Flows.Items
1187 }
Esin Karamanfc3b1af2020-01-29 16:52:00 +00001188 if lDevice.FlowGroups != nil && lDevice.FlowGroups.Items != nil {
1189 flowGroups = lDevice.FlowGroups.Items
1190 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001191
1192 changedFlow := false
1193 changedMeter := false
Scott Bakerfdea1e32020-02-21 15:35:41 -08001194 flow, err := fu.FlowStatsEntryFromFlowModMessage(mod)
1195 if err != nil {
1196 return err
1197 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001198 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001199 idx := fu.FindFlows(flows, flow)
1200 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001201 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001202 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001203 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001204 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001205 } else {
npujar1d86a522019-11-14 17:11:16 +05301206 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001207 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001208 if changedMeter {
1209 //Update model
1210 metersToUpdate := &ofp.Meters{}
1211 if lDevice.Meters != nil {
1212 metersToUpdate = &ofp.Meters{Items: meters}
1213 }
npujar467fe752020-01-16 20:17:45 +05301214 if err := agent.updateLogicalDeviceMetersWithoutLock(ctx, metersToUpdate); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001215 logger.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001216 return err
1217 }
khenaidoo19d7b632018-10-30 10:49:50 -04001218
Manikkaraj kb1a10922019-07-29 12:10:34 -04001219 }
1220 if changedFlow {
1221 var flowMetadata voltha.FlowMetadata
1222 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001223 logger.Error("meter-referred-in-flows-not-present")
Manikkaraj kb1a10922019-07-29 12:10:34 -04001224 return err
1225 }
khenaidoo820197c2020-02-13 16:35:33 -05001226 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{Items: flowGroups})
1227 if err != nil {
1228 return err
1229 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001230 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001231
npujar467fe752020-01-16 20:17:45 +05301232 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001233 logger.Errorw("cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001234 return err
1235 }
khenaidoo442e7c72020-03-10 16:13:48 -04001236
1237 // Update the devices
1238 respChnls := agent.deleteFlowsAndGroupsFromDevices(ctx, deviceRules, &flowMetadata)
1239
1240 // Wait for completion
1241 go func() {
1242 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001243 logger.Warnw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001244 //TODO: Revert flow changes
1245 }
1246 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001247 }
khenaidoo19d7b632018-10-30 10:49:50 -04001248 return nil
1249}
1250
1251//flowModify modifies a flow from the flow table of that logical device
1252func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1253 return errors.New("flowModify not implemented")
1254}
1255
1256//flowModifyStrict deletes a flow from the flow table of that logical device
1257func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1258 return errors.New("flowModifyStrict not implemented")
1259}
1260
npujar467fe752020-01-16 20:17:45 +05301261func (agent *LogicalDeviceAgent) groupAdd(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001262 logger.Debug("groupAdd")
khenaidoo19d7b632018-10-30 10:49:50 -04001263 if groupMod == nil {
1264 return nil
1265 }
khenaidoo442e7c72020-03-10 16:13:48 -04001266 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1267 return err
1268 }
1269 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001270
khenaidoo6e55d9e2019-12-12 18:26:26 -05001271 lDevice := agent.getLogicalDeviceWithoutLock()
1272
khenaidoo19d7b632018-10-30 10:49:50 -04001273 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001274 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001275 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001276
Esin Karaman2ea59212019-12-06 11:41:58 +00001277 deviceRules := fu.NewDeviceRules()
1278 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1279 fg := fu.NewFlowsAndGroups()
1280 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1281 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
1282
Girish Kumarf56a4682020-03-20 20:07:46 +00001283 logger.Debugw("rules", log.Fields{"rules for group-add": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001284
npujar467fe752020-01-16 20:17:45 +05301285 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001286 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001287 return err
1288 }
khenaidoo442e7c72020-03-10 16:13:48 -04001289
1290 // Update the devices
1291 respChnls := agent.addFlowsAndGroupsToDevices(ctx, deviceRules, &voltha.FlowMetadata{})
1292
1293 // Wait for completion
1294 go func() {
1295 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001296 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001297 //TODO: Revert flow changes
1298 }
1299 }()
1300 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001301 }
khenaidoo442e7c72020-03-10 16:13:48 -04001302 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001303}
1304
npujar467fe752020-01-16 20:17:45 +05301305func (agent *LogicalDeviceAgent) groupDelete(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001306 logger.Debug("groupDelete")
khenaidoo19d7b632018-10-30 10:49:50 -04001307 if groupMod == nil {
1308 return nil
1309 }
khenaidoo442e7c72020-03-10 16:13:48 -04001310 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1311 return err
1312 }
1313 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001314
khenaidoo6e55d9e2019-12-12 18:26:26 -05001315 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001316 groups := lDevice.FlowGroups.Items
1317 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301318 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001319 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301320 groupID := groupMod.GroupId
1321 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001322 //TODO we must delete all flows that point to this group and
1323 //signal controller as requested by flow's flag
1324 groups = []*ofp.OfpGroupEntry{}
1325 groupsChanged = true
1326 } else {
npujar1d86a522019-11-14 17:11:16 +05301327 idx := fu.FindGroup(groups, groupID)
1328 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001329 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001330 }
npujar1d86a522019-11-14 17:11:16 +05301331 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1332 groups = append(groups[:idx], groups[idx+1:]...)
1333 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001334 }
khenaidoo0458db62019-06-20 08:50:36 -04001335 if flowsChanged || groupsChanged {
khenaidoo820197c2020-02-13 16:35:33 -05001336 deviceRules, err := agent.flowDecomposer.DecomposeRules(ctx, agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1337 if err != nil {
1338 return err
1339 }
Girish Kumarf56a4682020-03-20 20:07:46 +00001340 logger.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001341
khenaidoo442e7c72020-03-10 16:13:48 -04001342 if groupsChanged {
1343 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001344 logger.Errorw("cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001345 return err
1346 }
khenaidoo0458db62019-06-20 08:50:36 -04001347 }
khenaidoo442e7c72020-03-10 16:13:48 -04001348 if flowsChanged {
1349 if err := agent.updateLogicalDeviceFlowsWithoutLock(ctx, &ofp.Flows{Items: flows}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001350 logger.Errorw("cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001351 return err
1352 }
1353 }
khenaidoo0458db62019-06-20 08:50:36 -04001354
khenaidoo442e7c72020-03-10 16:13:48 -04001355 // Update the devices
1356 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, nil)
1357
1358 // Wait for completion
1359 go func() {
1360 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001361 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001362 //TODO: Revert flow changes
1363 }
1364 }()
khenaidoo43c82122018-11-22 18:38:28 -05001365 }
khenaidoo19d7b632018-10-30 10:49:50 -04001366 return nil
1367}
1368
npujar467fe752020-01-16 20:17:45 +05301369func (agent *LogicalDeviceAgent) groupModify(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001370 logger.Debug("groupModify")
khenaidoo19d7b632018-10-30 10:49:50 -04001371 if groupMod == nil {
1372 return nil
1373 }
khenaidoo442e7c72020-03-10 16:13:48 -04001374 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1375 return err
1376 }
1377 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001378
khenaidoo6e55d9e2019-12-12 18:26:26 -05001379 lDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001380 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301381 var groupsChanged bool
1382 groupID := groupMod.GroupId
1383 idx := fu.FindGroup(groups, groupID)
1384 if idx == -1 {
1385 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001386 }
npujar1d86a522019-11-14 17:11:16 +05301387 //replace existing group entry with new group definition
1388 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1389 groups[idx] = groupEntry
1390 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001391 if groupsChanged {
Esin Karaman2ea59212019-12-06 11:41:58 +00001392 deviceRules := fu.NewDeviceRules()
1393 deviceRules.CreateEntryIfNotExist(agent.rootDeviceID)
1394 fg := fu.NewFlowsAndGroups()
1395 fg.AddGroup(fu.GroupEntryFromGroupMod(groupMod))
1396 deviceRules.AddFlowsAndGroup(agent.rootDeviceID, fg)
khenaidoo0458db62019-06-20 08:50:36 -04001397
Girish Kumarf56a4682020-03-20 20:07:46 +00001398 logger.Debugw("rules", log.Fields{"rules for group-modify": deviceRules.String()})
khenaidoo0458db62019-06-20 08:50:36 -04001399
npujar467fe752020-01-16 20:17:45 +05301400 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(ctx, &ofp.FlowGroups{Items: groups}); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001401 logger.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001402 return err
1403 }
khenaidoo442e7c72020-03-10 16:13:48 -04001404
1405 // Update the devices
1406 respChnls := agent.updateFlowsAndGroupsOfDevice(ctx, deviceRules, &voltha.FlowMetadata{})
1407
1408 // Wait for completion
1409 go func() {
1410 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, respChnls...); res != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001411 logger.Warnw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "errors": res})
khenaidoo442e7c72020-03-10 16:13:48 -04001412 //TODO: Revert flow changes
1413 }
1414 }()
khenaidoo19d7b632018-10-30 10:49:50 -04001415 }
1416 return nil
1417}
1418
1419// deleteLogicalPort removes the logical port
npujar467fe752020-01-16 20:17:45 +05301420func (agent *LogicalDeviceAgent) deleteLogicalPort(ctx context.Context, lPort *voltha.LogicalPort) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001421 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1422 return err
1423 }
1424 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001425
khenaidoo6e55d9e2019-12-12 18:26:26 -05001426 logicalDevice := agent.getLogicalDeviceWithoutLock()
1427
khenaidoo92e62c52018-10-03 14:02:54 -04001428 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001429 for i, logicalPort := range logicalDevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001430 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001431 index = i
1432 break
1433 }
1434 }
1435 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001436 copy(logicalDevice.Ports[index:], logicalDevice.Ports[index+1:])
1437 logicalDevice.Ports[len(logicalDevice.Ports)-1] = nil
1438 logicalDevice.Ports = logicalDevice.Ports[:len(logicalDevice.Ports)-1]
Girish Kumarf56a4682020-03-20 20:07:46 +00001439 logger.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
npujar467fe752020-01-16 20:17:45 +05301440 if err := agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001441 logger.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001442 return err
1443 }
khenaidoo820197c2020-02-13 16:35:33 -05001444
1445 // Remove the logical port from cache
1446 agent.deleteLogicalPortsFromMap([]uint32{lPort.DevicePortNo})
1447
1448 // Reset the logical device routes
1449 go func() {
1450 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001451 logger.Warnw("device-routes-not-ready", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001452 }
1453 }()
khenaidoo92e62c52018-10-03 14:02:54 -04001454 }
1455 return nil
khenaidoob9203542018-09-17 22:56:37 -04001456}
1457
khenaidoo0a822f92019-05-08 15:15:57 -04001458// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar467fe752020-01-16 20:17:45 +05301459func (agent *LogicalDeviceAgent) deleteLogicalPorts(ctx context.Context, deviceID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001460 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1461 return err
1462 }
1463 defer agent.requestQueue.RequestComplete()
khenaidoo0a822f92019-05-08 15:15:57 -04001464
khenaidoo6e55d9e2019-12-12 18:26:26 -05001465 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo820197c2020-02-13 16:35:33 -05001466 lPortstoKeep := []*voltha.LogicalPort{}
1467 lPortsNoToDelete := []uint32{}
khenaidoo6e55d9e2019-12-12 18:26:26 -05001468 for _, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301469 if logicalPort.DeviceId != deviceID {
khenaidoo820197c2020-02-13 16:35:33 -05001470 lPortstoKeep = append(lPortstoKeep, logicalPort)
1471 } else {
1472 lPortsNoToDelete = append(lPortsNoToDelete, logicalPort.DevicePortNo)
khenaidoo0a822f92019-05-08 15:15:57 -04001473 }
1474 }
khenaidoo820197c2020-02-13 16:35:33 -05001475 logicalDevice.Ports = lPortstoKeep
1476
Girish Kumarf56a4682020-03-20 20:07:46 +00001477 logger.Debugw("updated-logical-ports", log.Fields{"ports": lPortstoKeep})
npujar467fe752020-01-16 20:17:45 +05301478 if err := agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001479 logger.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001480 return err
1481 }
khenaidoo820197c2020-02-13 16:35:33 -05001482 // Remove the port from the cached logical ports set
1483 agent.deleteLogicalPortsFromMap(lPortsNoToDelete)
1484
1485 // Reset the logical device routes
1486 go func() {
1487 if err := agent.buildRoutes(context.Background()); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001488 logger.Warnw("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001489 }
1490 }()
khenaidoo0a822f92019-05-08 15:15:57 -04001491
1492 return nil
1493}
1494
khenaidoo19d7b632018-10-30 10:49:50 -04001495// enableLogicalPort enables the logical port
npujar467fe752020-01-16 20:17:45 +05301496func (agent *LogicalDeviceAgent) enableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001497 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1498 return err
1499 }
1500 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001501
khenaidoo6e55d9e2019-12-12 18:26:26 -05001502 logicalDevice := agent.getLogicalDeviceWithoutLock()
1503
khenaidoo19d7b632018-10-30 10:49:50 -04001504 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001505 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301506 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001507 index = i
1508 break
1509 }
1510 }
1511 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001512 logicalDevice.Ports[index].OfpPort.Config = logicalDevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
npujar467fe752020-01-16 20:17:45 +05301513 return agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001514 }
npujar1d86a522019-11-14 17:11:16 +05301515 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001516}
1517
1518// disableLogicalPort disabled the logical port
npujar467fe752020-01-16 20:17:45 +05301519func (agent *LogicalDeviceAgent) disableLogicalPort(ctx context.Context, lPortID string) error {
khenaidoo442e7c72020-03-10 16:13:48 -04001520 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1521 return err
1522 }
1523 defer agent.requestQueue.RequestComplete()
khenaidoo19d7b632018-10-30 10:49:50 -04001524
1525 // Get the most up to date logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001526 logicalDevice := agent.getLogicalDeviceWithoutLock()
khenaidoo19d7b632018-10-30 10:49:50 -04001527 index := -1
khenaidoo6e55d9e2019-12-12 18:26:26 -05001528 for i, logicalPort := range logicalDevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301529 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001530 index = i
1531 break
1532 }
1533 }
1534 if index >= 0 {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001535 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 +05301536 return agent.updateLogicalDeviceWithoutLock(ctx, logicalDevice)
khenaidoo19d7b632018-10-30 10:49:50 -04001537 }
npujar1d86a522019-11-14 17:11:16 +05301538 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001539}
1540
khenaidoo820197c2020-02-13 16:35:33 -05001541func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001542 logger.Debugw("ROUTE", log.Fields{"len": len(agent.deviceRoutes.Routes)})
khenaidoo820197c2020-02-13 16:35:33 -05001543 for routeLink, route := range agent.deviceRoutes.Routes {
Girish Kumarf56a4682020-03-20 20:07:46 +00001544 logger.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001545 if ingress == routeLink.Ingress && egress == routeLink.Egress {
khenaidoo820197c2020-02-13 16:35:33 -05001546 return route, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001547 }
1548 }
khenaidoo820197c2020-02-13 16:35:33 -05001549 return nil, status.Errorf(codes.FailedPrecondition, "no route from:%d to:%d", ingress, egress)
khenaidoo89b0e942018-10-21 21:11:33 -04001550}
1551
npujar1d86a522019-11-14 17:11:16 +05301552// GetRoute returns route
khenaidoo820197c2020-02-13 16:35:33 -05001553func (agent *LogicalDeviceAgent) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001554 logger.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo820197c2020-02-13 16:35:33 -05001555 routes := make([]route.Hop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001556
khenaidoo19d7b632018-10-30 10:49:50 -04001557 // Note: A port value of 0 is equivalent to a nil port
1558
khenaidoo89b0e942018-10-21 21:11:33 -04001559 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001560 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001561 logger.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo2c6a0992019-04-29 13:46:56 -04001562 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001563 //This is a trap on the NNI Port
khenaidoo820197c2020-02-13 16:35:33 -05001564 if len(agent.deviceRoutes.Routes) == 0 {
khenaidoo8f474192019-04-03 17:20:44 -04001565 // 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 -04001566 // route with same IngressHop and EgressHop
khenaidoo820197c2020-02-13 16:35:33 -05001567 hop := route.Hop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001568 routes = append(routes, hop)
1569 routes = append(routes, hop)
khenaidoo820197c2020-02-13 16:35:33 -05001570 return routes, nil
khenaidoo8f474192019-04-03 17:20:44 -04001571 }
khenaidoo89b0e942018-10-21 21:11:33 -04001572 //Return a 'half' route to make the flow decomposer logic happy
khenaidoo820197c2020-02-13 16:35:33 -05001573 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001574 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001575 routes = append(routes, route.Hop{}) // first hop is set to empty
1576 routes = append(routes, path[1])
1577 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001578 }
1579 }
khenaidoo820197c2020-02-13 16:35:33 -05001580 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001581 }
1582 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001583 var err error
1584 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001585 logger.Warnw("no-nni-port", log.Fields{"error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001586 return nil, err
khenaidoo2c6a0992019-04-29 13:46:56 -04001587 }
khenaidoo89b0e942018-10-21 21:11:33 -04001588 }
1589 //If ingress port is not specified (nil), it may be a wildcarded
1590 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1591 //in which case we need to create a half-route where only the egress
1592 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001593 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001594 // We can use the 2nd hop of any upstream route, so just find the first upstream:
khenaidoo820197c2020-02-13 16:35:33 -05001595 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001596 if agent.isNNIPort(routeLink.Egress) {
khenaidoo820197c2020-02-13 16:35:33 -05001597 routes = append(routes, route.Hop{}) // first hop is set to empty
1598 routes = append(routes, path[1])
1599 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001600 }
1601 }
khenaidoo820197c2020-02-13 16:35:33 -05001602 return nil, status.Errorf(codes.FailedPrecondition, "no upstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001603 }
1604 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001605 if egressPortNo == 0 {
khenaidoo820197c2020-02-13 16:35:33 -05001606 for routeLink, path := range agent.deviceRoutes.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001607 if routeLink.Ingress == ingressPortNo {
khenaidoo820197c2020-02-13 16:35:33 -05001608 routes = append(routes, path[0])
1609 routes = append(routes, route.Hop{})
1610 return routes, nil
khenaidoo89b0e942018-10-21 21:11:33 -04001611 }
1612 }
khenaidoo820197c2020-02-13 16:35:33 -05001613 return nil, status.Errorf(codes.FailedPrecondition, "no downstream route from:%d to:%d", ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001614 }
khenaidoo89b0e942018-10-21 21:11:33 -04001615 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001616 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001617}
1618
khenaidoo3d3b8c22019-05-22 18:10:39 -04001619//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1620//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1621//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001622func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1623 lPorts := make([]uint32, 0)
1624 var exclPort uint32
1625 if len(excludePort) == 1 {
1626 exclPort = excludePort[0]
1627 }
khenaidoo6e55d9e2019-12-12 18:26:26 -05001628 lDevice := agent.getLogicalDeviceWithoutLock()
1629 for _, port := range lDevice.Ports {
1630 if port.OfpPort.PortNo != exclPort {
1631 lPorts = append(lPorts, port.OfpPort.PortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001632 }
1633 }
1634 return lPorts
1635}
khenaidoo19d7b632018-10-30 10:49:50 -04001636
khenaidoo820197c2020-02-13 16:35:33 -05001637// GetDeviceRoutes returns device graph
1638func (agent *LogicalDeviceAgent) GetDeviceRoutes() *route.DeviceRoutes {
1639 return agent.deviceRoutes
khenaidoo19d7b632018-10-30 10:49:50 -04001640}
1641
khenaidoo820197c2020-02-13 16:35:33 -05001642//rebuildRoutes rebuilds the device routes
1643func (agent *LogicalDeviceAgent) buildRoutes(ctx context.Context) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001644 logger.Debugf("building-routes", log.Fields{"logical-device-id": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001645 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1646 return err
1647 }
1648 defer agent.requestQueue.RequestComplete()
1649
khenaidoo820197c2020-02-13 16:35:33 -05001650 if agent.deviceRoutes == nil {
1651 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001652 }
1653 // Get all the logical ports on that logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001654 lDevice := agent.getLogicalDeviceWithoutLock()
1655
khenaidoo820197c2020-02-13 16:35:33 -05001656 if err := agent.deviceRoutes.ComputeRoutes(ctx, lDevice.Ports); err != nil {
1657 return err
1658 }
1659 if err := agent.deviceRoutes.Print(); err != nil {
1660 return err
1661 }
1662
khenaidoo2c6a0992019-04-29 13:46:56 -04001663 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001664}
1665
khenaidoo820197c2020-02-13 16:35:33 -05001666//updateRoutes updates the device routes
1667func (agent *LogicalDeviceAgent) updateRoutes(ctx context.Context, lp *voltha.LogicalPort) error {
Girish Kumarf56a4682020-03-20 20:07:46 +00001668 logger.Debugw("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo442e7c72020-03-10 16:13:48 -04001669 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1670 return err
1671 }
1672 defer agent.requestQueue.RequestComplete()
1673
khenaidoo820197c2020-02-13 16:35:33 -05001674 if agent.deviceRoutes == nil {
1675 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001676 }
khenaidoo820197c2020-02-13 16:35:33 -05001677 if err := agent.deviceRoutes.AddPort(ctx, lp, agent.logicalDevice.Ports); err != nil {
1678 return err
khenaidoo0a822f92019-05-08 15:15:57 -04001679 }
khenaidoo820197c2020-02-13 16:35:33 -05001680 if err := agent.deviceRoutes.Print(); err != nil {
1681 return err
1682 }
1683 return nil
khenaidoo0a822f92019-05-08 15:15:57 -04001684}
1685
khenaidoofc1314d2019-03-14 09:34:21 -04001686// 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 -04001687func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001688 newPorts = make([]*voltha.LogicalPort, 0)
1689 changedPorts = make([]*voltha.LogicalPort, 0)
1690 deletedPorts = make([]*voltha.LogicalPort, 0)
1691 for _, o := range oldList {
1692 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001693 for _, n := range newList {
1694 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001695 found = true
1696 break
1697 }
1698 }
1699 if !found {
1700 deletedPorts = append(deletedPorts, o)
1701 }
khenaidoofc1314d2019-03-14 09:34:21 -04001702 }
1703 for _, n := range newList {
1704 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001705 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001706 for _, o := range oldList {
1707 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001708 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001709 found = true
1710 break
1711 }
1712 }
1713 if !found {
1714 newPorts = append(newPorts, n)
1715 }
khenaidoo2bc48282019-07-16 18:13:46 -04001716 if changed {
1717 changedPorts = append(changedPorts, n)
1718 }
khenaidoofc1314d2019-03-14 09:34:21 -04001719 }
1720 return
1721}
1722
1723// portUpdated is invoked when a port is updated on the logical device. Until
1724// the POST_ADD notification is fixed, we will use the logical device to
1725// update that data.
npujar467fe752020-01-16 20:17:45 +05301726func (agent *LogicalDeviceAgent) portUpdated(ctx context.Context, args ...interface{}) interface{} {
Girish Kumarf56a4682020-03-20 20:07:46 +00001727 logger.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
khenaidoofc1314d2019-03-14 09:34:21 -04001728
1729 var oldLD *voltha.LogicalDevice
1730 var newlD *voltha.LogicalDevice
1731
1732 var ok bool
1733 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +00001734 logger.Errorw("invalid-args", log.Fields{"args0": args[0]})
khenaidoofc1314d2019-03-14 09:34:21 -04001735 return nil
1736 }
1737 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
Girish Kumarf56a4682020-03-20 20:07:46 +00001738 logger.Errorw("invalid-args", log.Fields{"args1": args[1]})
khenaidoofc1314d2019-03-14 09:34:21 -04001739 return nil
1740 }
1741
1742 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001743 logger.Debug("ports-have-not-changed")
khenaidoofc1314d2019-03-14 09:34:21 -04001744 return nil
1745 }
1746
1747 // Get the difference between the two list
1748 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1749
1750 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001751 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301752 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001753 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001754 }
1755 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301756 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001757 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001758 }
1759 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301760 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001761 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001762 }
1763
1764 return nil
1765}
1766
khenaidoo8f474192019-04-03 17:20:44 -04001767// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1768// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1769// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1770// scenario. This also applies to the case where the port was already added.
npujar467fe752020-01-16 20:17:45 +05301771func (agent *LogicalDeviceAgent) addNNILogicalPort(ctx context.Context, device *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001772 logger.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001773 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
Girish Kumarf56a4682020-03-20 20:07:46 +00001774 logger.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
khenaidoo8f474192019-04-03 17:20:44 -04001775 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001776 }
khenaidoo442e7c72020-03-10 16:13:48 -04001777 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1778 return false, err
1779 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001780 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001781 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001782 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001783 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001784 }
khenaidoo442e7c72020-03-10 16:13:48 -04001785 agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001786
khenaidoofc1314d2019-03-14 09:34:21 -04001787 var portCap *ic.PortCapability
1788 var err error
1789 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301790 if portCap, err = agent.deviceMgr.getPortCapability(ctx, device.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001791 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001792 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001793 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001794
khenaidoo442e7c72020-03-10 16:13:48 -04001795 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1796 return false, err
1797 }
1798
1799 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001800 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1801 if agent.portExist(device, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001802 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001803 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001804 }
1805
khenaidoofc1314d2019-03-14 09:34:21 -04001806 portCap.Port.RootPort = true
1807 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1808 lp.DeviceId = device.Id
1809 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1810 lp.OfpPort.PortNo = port.PortNo
1811 lp.OfpPort.Name = lp.Id
1812 lp.DevicePortNo = port.PortNo
1813
khenaidoo6e55d9e2019-12-12 18:26:26 -05001814 ld := agent.getLogicalDeviceWithoutLock()
1815
khenaidoofc1314d2019-03-14 09:34:21 -04001816 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1817 if cloned.Ports == nil {
1818 cloned.Ports = make([]*voltha.LogicalPort, 0)
1819 }
1820 cloned.Ports = append(cloned.Ports, lp)
1821
npujar467fe752020-01-16 20:17:45 +05301822 if err = agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001823 logger.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001824 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001825 }
khenaidoo910204f2019-04-08 17:56:40 -04001826
khenaidoo820197c2020-02-13 16:35:33 -05001827 // Update the device routes with this new logical port
khenaidoo910204f2019-04-08 17:56:40 -04001828 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001829 go func() {
1830 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001831 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 -05001832 }
1833 }()
khenaidoo910204f2019-04-08 17:56:40 -04001834
khenaidoo8f474192019-04-03 17:20:44 -04001835 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001836}
1837
khenaidoo910204f2019-04-08 17:56:40 -04001838func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo6e55d9e2019-12-12 18:26:26 -05001839 ldevice := agent.getLogicalDeviceWithoutLock()
1840 for _, lPort := range ldevice.Ports {
1841 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
1842 return true
khenaidoofc1314d2019-03-14 09:34:21 -04001843 }
1844 }
1845 return false
1846}
1847
khenaidoo8f474192019-04-03 17:20:44 -04001848// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1849// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1850// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1851// scenario. This also applies to the case where the port was already added.
npujar467fe752020-01-16 20:17:45 +05301852func (agent *LogicalDeviceAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device, port *voltha.Port) (bool, error) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001853 logger.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001854 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
Girish Kumarf56a4682020-03-20 20:07:46 +00001855 logger.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
khenaidoo8f474192019-04-03 17:20:44 -04001856 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001857 }
khenaidoo442e7c72020-03-10 16:13:48 -04001858 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1859 return false, err
1860 }
1861
khenaidoo1ce37ad2019-03-24 22:07:24 -04001862 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001863 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo442e7c72020-03-10 16:13:48 -04001864 agent.requestQueue.RequestComplete()
khenaidoo8f474192019-04-03 17:20:44 -04001865 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001866 }
khenaidoo442e7c72020-03-10 16:13:48 -04001867 agent.requestQueue.RequestComplete()
khenaidoofc1314d2019-03-14 09:34:21 -04001868 var portCap *ic.PortCapability
1869 var err error
1870 // First get the port capability
npujar467fe752020-01-16 20:17:45 +05301871 if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, port.PortNo); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001872 logger.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001873 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001874 }
khenaidoo442e7c72020-03-10 16:13:48 -04001875 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
1876 return false, err
1877 }
1878 defer agent.requestQueue.RequestComplete()
khenaidoo1ce37ad2019-03-24 22:07:24 -04001879 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1880 if agent.portExist(childDevice, port) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001881 logger.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001882 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001883 }
khenaidoofc1314d2019-03-14 09:34:21 -04001884 // Get stored logical device
khenaidoo6e55d9e2019-12-12 18:26:26 -05001885 ldevice := agent.getLogicalDeviceWithoutLock()
1886
Girish Kumarf56a4682020-03-20 20:07:46 +00001887 logger.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
npujar1d86a522019-11-14 17:11:16 +05301888 portCap.Port.RootPort = false
1889 portCap.Port.Id = port.Label
1890 portCap.Port.OfpPort.PortNo = port.PortNo
1891 portCap.Port.DeviceId = childDevice.Id
1892 portCap.Port.DevicePortNo = port.PortNo
1893 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1894 if cloned.Ports == nil {
1895 cloned.Ports = make([]*voltha.LogicalPort, 0)
1896 }
1897 cloned.Ports = append(cloned.Ports, portCap.Port)
npujar467fe752020-01-16 20:17:45 +05301898 if err := agent.updateLogicalDeviceWithoutLock(ctx, cloned); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301899 return false, err
1900 }
1901 // Update the device graph with this new logical port
1902 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
khenaidoo820197c2020-02-13 16:35:33 -05001903
1904 go func() {
1905 if err := agent.updateRoutes(context.Background(), clonedLP); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001906 logger.Warn("routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "error": err})
khenaidoo820197c2020-02-13 16:35:33 -05001907 }
1908 }()
1909
npujar1d86a522019-11-14 17:11:16 +05301910 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001911}
1912
npujar467fe752020-01-16 20:17:45 +05301913func (agent *LogicalDeviceAgent) packetOut(ctx context.Context, packet *ofp.OfpPacketOut) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001914 logger.Debugw("packet-out", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001915 "packet": hex.EncodeToString(packet.Data),
1916 "inPort": packet.GetInPort(),
1917 })
khenaidoo68c930b2019-05-13 11:46:51 -04001918 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001919 //frame := packet.GetData()
1920 //TODO: Use a channel between the logical agent and the device agent
npujar467fe752020-01-16 20:17:45 +05301921 if err := agent.deviceMgr.packetOut(ctx, agent.rootDeviceID, outPort, packet); err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +00001922 logger.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001923 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001924}
1925
npujar1d86a522019-11-14 17:11:16 +05301926func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Girish Kumarf56a4682020-03-20 20:07:46 +00001927 logger.Debugw("packet-in", log.Fields{
Matteo Scandolo360605d2019-11-05 18:29:17 -08001928 "port": port,
1929 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301930 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001931 })
khenaidoo68c930b2019-05-13 11:46:51 -04001932 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301933 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Girish Kumarf56a4682020-03-20 20:07:46 +00001934 logger.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001935}
khenaidoo2c6a0992019-04-29 13:46:56 -04001936
1937func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1938 agent.lockLogicalPortsNo.Lock()
1939 defer agent.lockLogicalPortsNo.Unlock()
1940 if exist := agent.logicalPortsNo[portNo]; !exist {
1941 agent.logicalPortsNo[portNo] = nniPort
1942 }
1943}
1944
khenaidoo820197c2020-02-13 16:35:33 -05001945func (agent *LogicalDeviceAgent) deleteLogicalPortsFromMap(portsNo []uint32) {
1946 agent.lockLogicalPortsNo.Lock()
1947 defer agent.lockLogicalPortsNo.Unlock()
1948 for _, pNo := range portsNo {
1949 delete(agent.logicalPortsNo, pNo)
1950 }
1951}
1952
khenaidoo3d3b8c22019-05-22 18:10:39 -04001953func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1954 agent.lockLogicalPortsNo.Lock()
1955 defer agent.lockLogicalPortsNo.Unlock()
1956 for _, lp := range lps {
1957 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1958 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1959 }
1960 }
1961}
1962
khenaidoo2c6a0992019-04-29 13:46:56 -04001963func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1964 agent.lockLogicalPortsNo.RLock()
1965 defer agent.lockLogicalPortsNo.RUnlock()
1966 if exist := agent.logicalPortsNo[portNo]; exist {
1967 return agent.logicalPortsNo[portNo]
1968 }
1969 return false
1970}
1971
1972func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1973 agent.lockLogicalPortsNo.RLock()
1974 defer agent.lockLogicalPortsNo.RUnlock()
1975 for portNo, nni := range agent.logicalPortsNo {
1976 if nni {
1977 return portNo, nil
1978 }
1979 }
1980 return 0, status.Error(codes.NotFound, "No NNI port found")
1981}
Esin Karaman09959ae2019-11-29 13:59:58 +00001982
1983//GetNNIPorts returns NNI ports.
1984func (agent *LogicalDeviceAgent) GetNNIPorts() []uint32 {
1985 agent.lockLogicalPortsNo.RLock()
1986 defer agent.lockLogicalPortsNo.RUnlock()
1987 nniPorts := make([]uint32, 0)
1988 for portNo, nni := range agent.logicalPortsNo {
1989 if nni {
1990 nniPorts = append(nniPorts, portNo)
1991 }
1992 }
1993 return nniPorts
1994}