blob: ca074543f6caa160c0a63b83da67c57fd92b77fe [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"
npujar1d86a522019-11-14 17:11:16 +053024 "reflect"
25 "sync"
26 "time"
27
khenaidoob9203542018-09-17 22:56:37 -040028 "github.com/gogo/protobuf/proto"
sbarbari17d7e222019-11-05 10:02:29 -050029 "github.com/opencord/voltha-go/db/model"
npujar1d86a522019-11-14 17:11:16 +053030 fd "github.com/opencord/voltha-go/rw_core/flowdecomposition"
khenaidoo89b0e942018-10-21 21:11:33 -040031 "github.com/opencord/voltha-go/rw_core/graph"
Scott Bakerb671a862019-10-24 10:53:40 -070032 coreutils "github.com/opencord/voltha-go/rw_core/utils"
Scott Baker807addd2019-10-24 15:16:21 -070033 fu "github.com/opencord/voltha-lib-go/v2/pkg/flows"
34 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker555307d2019-11-04 08:58:01 -080035 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
37 "github.com/opencord/voltha-protos/v2/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040038 "google.golang.org/grpc/codes"
39 "google.golang.org/grpc/status"
khenaidoob9203542018-09-17 22:56:37 -040040)
41
npujar1d86a522019-11-14 17:11:16 +053042// LogicalDeviceAgent represent attributes of logical device agent
khenaidoob9203542018-09-17 22:56:37 -040043type LogicalDeviceAgent struct {
npujar1d86a522019-11-14 17:11:16 +053044 logicalDeviceID string
45 rootDeviceID string
khenaidoo3306c992019-05-24 16:57:35 -040046 deviceMgr *DeviceManager
47 ldeviceMgr *LogicalDeviceManager
48 clusterDataProxy *model.Proxy
49 exitChannel chan int
50 deviceGraph *graph.DeviceGraph
51 flowProxy *model.Proxy
52 groupProxy *model.Proxy
Manikkaraj kb1a10922019-07-29 12:10:34 -040053 meterProxy *model.Proxy
khenaidoo3306c992019-05-24 16:57:35 -040054 ldProxy *model.Proxy
55 portProxies map[string]*model.Proxy
56 portProxiesLock sync.RWMutex
57 lockLogicalDevice sync.RWMutex
khenaidoo4c9e5592019-09-09 16:20:41 -040058 lockDeviceGraph sync.RWMutex
khenaidoo3306c992019-05-24 16:57:35 -040059 logicalPortsNo map[uint32]bool //value is true for NNI port
60 lockLogicalPortsNo sync.RWMutex
61 flowDecomposer *fd.FlowDecomposer
62 defaultTimeout int64
khenaidoob9203542018-09-17 22:56:37 -040063}
64
npujar1d86a522019-11-14 17:11:16 +053065func newLogicalDeviceAgent(id string, deviceID string, ldeviceMgr *LogicalDeviceManager,
Stephane Barbarie1ab43272018-12-08 21:42:13 -050066 deviceMgr *DeviceManager,
khenaidoo2c6a0992019-04-29 13:46:56 -040067 cdProxy *model.Proxy, timeout int64) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040068 var agent LogicalDeviceAgent
69 agent.exitChannel = make(chan int, 1)
npujar1d86a522019-11-14 17:11:16 +053070 agent.logicalDeviceID = id
71 agent.rootDeviceID = deviceID
khenaidoob9203542018-09-17 22:56:37 -040072 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040073 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040074 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040075 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040076 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoofc1314d2019-03-14 09:34:21 -040077 agent.portProxies = make(map[string]*model.Proxy)
78 agent.portProxiesLock = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040079 agent.lockLogicalPortsNo = sync.RWMutex{}
khenaidoo4c9e5592019-09-09 16:20:41 -040080 agent.lockDeviceGraph = sync.RWMutex{}
khenaidoo2c6a0992019-04-29 13:46:56 -040081 agent.logicalPortsNo = make(map[uint32]bool)
khenaidoo2c6a0992019-04-29 13:46:56 -040082 agent.defaultTimeout = timeout
khenaidoob9203542018-09-17 22:56:37 -040083 return &agent
84}
85
khenaidoo4d4802d2018-10-04 21:59:49 -040086// start creates the logical device and add it to the data model
khenaidoo297cd252019-02-07 22:10:23 -050087func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
npujar1d86a522019-11-14 17:11:16 +053088 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceID, "loadFromdB": loadFromdB})
khenaidoo297cd252019-02-07 22:10:23 -050089 var ld *voltha.LogicalDevice
90 if !loadFromdB {
khenaidoo7e3d8f12019-08-02 16:06:30 -040091 //Build the logical device based on information retrieved from the device adapter
92 var switchCap *ic.SwitchCapability
khenaidoo297cd252019-02-07 22:10:23 -050093 var err error
npujar1d86a522019-11-14 17:11:16 +053094 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceID); err != nil {
khenaidoo7e3d8f12019-08-02 16:06:30 -040095 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
96 return err
97 }
npujar1d86a522019-11-14 17:11:16 +053098 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceID, RootDeviceId: agent.rootDeviceID}
khenaidoo297cd252019-02-07 22:10:23 -050099
100 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
101 var datapathID uint64
npujar1d86a522019-11-14 17:11:16 +0530102 if datapathID, err = CreateDataPathID(agent.logicalDeviceID); err != nil {
khenaidoo297cd252019-02-07 22:10:23 -0500103 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
104 return err
105 }
106 ld.DatapathId = datapathID
khenaidoo7e3d8f12019-08-02 16:06:30 -0400107 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
108 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
109 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo297cd252019-02-07 22:10:23 -0500110 ld.Flows = &ofp.Flows{Items: nil}
111 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
112
khenaidoo297cd252019-02-07 22:10:23 -0500113 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500114 // Save the logical device
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400115 if added := agent.clusterDataProxy.AddWithID(ctx, "/logical_devices", ld.Id, ld, ""); added == nil {
npujar1d86a522019-11-14 17:11:16 +0530116 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500117 } else {
npujar1d86a522019-11-14 17:11:16 +0530118 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500119 }
120 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400121
khenaidoo3d3b8c22019-05-22 18:10:39 -0400122 // TODO: Set the logical ports in a separate call once the port update issue is fixed.
npujar1d86a522019-11-14 17:11:16 +0530123 go func() {
124 err := agent.setupLogicalPorts(ctx)
125 if err != nil {
126 log.Errorw("unable-to-setup-logical-ports", log.Fields{"error": err})
127 }
128 }()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400129
khenaidoo297cd252019-02-07 22:10:23 -0500130 } else {
131 // load from dB - the logical may not exist at this time. On error, just return and the calling function
132 // will destroy this agent.
133 var err error
134 if ld, err = agent.GetLogicalDevice(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530135 log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo297cd252019-02-07 22:10:23 -0500136 return err
137 }
khenaidoo3d3b8c22019-05-22 18:10:39 -0400138
khenaidoo8c3303d2019-02-13 14:59:39 -0500139 // Update the root device Id
npujar1d86a522019-11-14 17:11:16 +0530140 agent.rootDeviceID = ld.RootDeviceId
khenaidoo3d3b8c22019-05-22 18:10:39 -0400141
142 // Setup the local list of logical ports
143 agent.addLogicalPortsToMap(ld.Ports)
144
khenaidoob9203542018-09-17 22:56:37 -0400145 }
khenaidoo92e62c52018-10-03 14:02:54 -0400146 agent.lockLogicalDevice.Lock()
khenaidoo3d3b8c22019-05-22 18:10:39 -0400147 defer agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400148
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400149 agent.flowProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400150 ctx,
npujar1d86a522019-11-14 17:11:16 +0530151 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400152 false)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400153 agent.meterProxy = agent.clusterDataProxy.CreateProxy(
154 ctx,
npujar1d86a522019-11-14 17:11:16 +0530155 fmt.Sprintf("/logical_devices/%s/meters", agent.logicalDeviceID),
Manikkaraj kb1a10922019-07-29 12:10:34 -0400156 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400157 agent.groupProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400158 ctx,
npujar1d86a522019-11-14 17:11:16 +0530159 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceID),
khenaidoo19d7b632018-10-30 10:49:50 -0400160 false)
Stephane Barbarie40fd3b22019-04-23 21:50:47 -0400161 agent.ldProxy = agent.clusterDataProxy.CreateProxy(
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400162 ctx,
npujar1d86a522019-11-14 17:11:16 +0530163 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceID),
khenaidoofc1314d2019-03-14 09:34:21 -0400164 false)
khenaidoo19d7b632018-10-30 10:49:50 -0400165
khenaidoofc1314d2019-03-14 09:34:21 -0400166 // TODO: Use a port proxy once the POST_ADD is fixed
khenaidoo3d3b8c22019-05-22 18:10:39 -0400167 if agent.ldProxy != nil {
168 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
169 } else {
npujar1d86a522019-11-14 17:11:16 +0530170 log.Errorw("logical-device-proxy-null", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400171 return status.Error(codes.Internal, "logical-device-proxy-null")
172 }
khenaidoobcf205b2019-01-25 22:21:14 -0500173
khenaidoo4c9e5592019-09-09 16:20:41 -0400174 // Setup the device graph - run it in its own routine
175 if loadFromdB {
176 go agent.generateDeviceGraph()
177 }
khenaidoob9203542018-09-17 22:56:37 -0400178 return nil
179}
180
khenaidoo4d4802d2018-10-04 21:59:49 -0400181// stop stops the logical devuce agent. This removes the logical device from the data model.
182func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
183 log.Info("stopping-logical_device-agent")
184 agent.lockLogicalDevice.Lock()
185 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500186
khenaidoo4d4802d2018-10-04 21:59:49 -0400187 //Remove the logical device from the model
npujar1d86a522019-11-14 17:11:16 +0530188 if removed := agent.clusterDataProxy.Remove(ctx, "/logical_devices/"+agent.logicalDeviceID, ""); removed == nil {
189 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400190 } else {
npujar1d86a522019-11-14 17:11:16 +0530191 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo4d4802d2018-10-04 21:59:49 -0400192 }
193 agent.exitChannel <- 1
194 log.Info("logical_device-agent-stopped")
195}
196
khenaidoo19d7b632018-10-30 10:49:50 -0400197// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
198func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
199 log.Debug("GetLogicalDevice")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400200 agent.lockLogicalDevice.RLock()
201 defer agent.lockLogicalDevice.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530202 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400203 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500204 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400205 }
npujar1d86a522019-11-14 17:11:16 +0530206 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400207}
208
npujar1d86a522019-11-14 17:11:16 +0530209// ListLogicalDeviceFlows returns logical device flows
khenaidoodd237172019-05-27 16:37:17 -0400210func (agent *LogicalDeviceAgent) ListLogicalDeviceFlows() (*ofp.Flows, error) {
211 log.Debug("ListLogicalDeviceFlows")
212 agent.lockLogicalDevice.RLock()
213 defer agent.lockLogicalDevice.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530214 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400215 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
216 cFlows := (proto.Clone(lDevice.Flows)).(*ofp.Flows)
217 return cFlows, nil
218 }
npujar1d86a522019-11-14 17:11:16 +0530219 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoodd237172019-05-27 16:37:17 -0400220}
221
npujar1d86a522019-11-14 17:11:16 +0530222// ListLogicalDeviceMeters returns logical device meters
Manikkaraj kb1a10922019-07-29 12:10:34 -0400223func (agent *LogicalDeviceAgent) ListLogicalDeviceMeters() (*ofp.Meters, error) {
224 log.Debug("ListLogicalDeviceMeters")
225 agent.lockLogicalDevice.RLock()
226 defer agent.lockLogicalDevice.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530227 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
Manikkaraj kb1a10922019-07-29 12:10:34 -0400228 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Gamze Abaka6e4ac162019-10-21 11:10:10 +0000229 if lDevice.Meters == nil {
230 return &ofp.Meters{}, nil
231 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400232 cMeters := (proto.Clone(lDevice.Meters)).(*ofp.Meters)
233 return cMeters, nil
234 }
npujar1d86a522019-11-14 17:11:16 +0530235 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400236}
237
npujar1d86a522019-11-14 17:11:16 +0530238// ListLogicalDeviceFlowGroups returns logical device flow groups
khenaidoodd237172019-05-27 16:37:17 -0400239func (agent *LogicalDeviceAgent) ListLogicalDeviceFlowGroups() (*ofp.FlowGroups, error) {
240 log.Debug("ListLogicalDeviceFlowGroups")
241 agent.lockLogicalDevice.RLock()
242 defer agent.lockLogicalDevice.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530243 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
khenaidoodd237172019-05-27 16:37:17 -0400244 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
245 cFlowGroups := (proto.Clone(lDevice.FlowGroups)).(*ofp.FlowGroups)
246 return cFlowGroups, nil
247 }
npujar1d86a522019-11-14 17:11:16 +0530248 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoodd237172019-05-27 16:37:17 -0400249}
250
npujar1d86a522019-11-14 17:11:16 +0530251// ListLogicalDevicePorts returns logical device ports
khenaidoo19d7b632018-10-30 10:49:50 -0400252func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400253 log.Debug("ListLogicalDevicePorts")
254 agent.lockLogicalDevice.RLock()
255 defer agent.lockLogicalDevice.RUnlock()
npujar1d86a522019-11-14 17:11:16 +0530256 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400257 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
258 lPorts := make([]*voltha.LogicalPort, 0)
npujar1d86a522019-11-14 17:11:16 +0530259 lPorts = append(lPorts, lDevice.Ports...)
khenaidoo19d7b632018-10-30 10:49:50 -0400260 return &voltha.LogicalPorts{Items: lPorts}, nil
261 }
npujar1d86a522019-11-14 17:11:16 +0530262 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400263}
264
khenaidoo4c9e5592019-09-09 16:20:41 -0400265//updateLogicalDeviceFlowsWithoutLock updates the logical device with the latest flows in the model.
khenaidoo43c82122018-11-22 18:38:28 -0500266func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400267 ld, err := agent.getLogicalDeviceWithoutLock()
268 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530269 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400270 }
271 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
272 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
273 cloned.Flows = flows
274
275 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
276 log.Errorw("error-updating-logical-device-with-flows", log.Fields{"error": err})
277 return err
khenaidoo43c82122018-11-22 18:38:28 -0500278 }
khenaidoo43c82122018-11-22 18:38:28 -0500279 return nil
280}
281
khenaidoo4c9e5592019-09-09 16:20:41 -0400282//updateLogicalDeviceMetersWithoutLock updates the logical device with the meters info
Manikkaraj kb1a10922019-07-29 12:10:34 -0400283func (agent *LogicalDeviceAgent) updateLogicalDeviceMetersWithoutLock(meters *ofp.Meters) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400284 ld, err := agent.getLogicalDeviceWithoutLock()
285 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530286 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400287 }
288 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
289 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
290 cloned.Meters = meters
291
292 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
293 log.Errorw("error-updating-logical-device-with-meters", log.Fields{"error": err})
294 return err
Manikkaraj kb1a10922019-07-29 12:10:34 -0400295 }
296 return nil
297}
298
khenaidoo4c9e5592019-09-09 16:20:41 -0400299//updateLogicalDeviceFlowGroupsWithoutLock updates the logical device with the flow groups
khenaidoo43c82122018-11-22 18:38:28 -0500300func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400301 ld, err := agent.getLogicalDeviceWithoutLock()
302 if err != nil {
npujar1d86a522019-11-14 17:11:16 +0530303 return status.Errorf(codes.Internal, "logical-device-absent:%s", agent.logicalDeviceID)
khenaidoo4c9e5592019-09-09 16:20:41 -0400304 }
305 log.Debugw("logical-device-before", log.Fields{"lports": len(ld.Ports)})
306 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
307 cloned.FlowGroups = flowGroups
308
309 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
310 log.Errorw("error-updating-logical-device-with-flowgroups", log.Fields{"error": err})
311 return err
khenaidoo43c82122018-11-22 18:38:28 -0500312 }
khenaidoo43c82122018-11-22 18:38:28 -0500313 return nil
314}
315
khenaidoo4d4802d2018-10-04 21:59:49 -0400316// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
317// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400318func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
319 log.Debug("getLogicalDeviceWithoutLock")
npujar1d86a522019-11-14 17:11:16 +0530320 logicalDevice := agent.clusterDataProxy.Get(context.Background(), "/logical_devices/"+agent.logicalDeviceID, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400321 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400322 //log.Debug("getLogicalDeviceWithoutLock", log.Fields{"ldevice": lDevice})
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500323 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400324 }
npujar1d86a522019-11-14 17:11:16 +0530325 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400326}
327
khenaidoo2c6a0992019-04-29 13:46:56 -0400328func (agent *LogicalDeviceAgent) updateLogicalPort(device *voltha.Device, port *voltha.Port) error {
329 log.Debugw("updateLogicalPort", log.Fields{"deviceId": device.Id, "port": port})
330 var err error
331 if port.Type == voltha.Port_ETHERNET_NNI {
332 if _, err = agent.addNNILogicalPort(device, port); err != nil {
333 return err
334 }
335 agent.addLogicalPortToMap(port.PortNo, true)
336 } else if port.Type == voltha.Port_ETHERNET_UNI {
337 if _, err = agent.addUNILogicalPort(device, port); err != nil {
338 return err
339 }
340 agent.addLogicalPortToMap(port.PortNo, false)
341 } else {
342 // Update the device graph to ensure all routes on the logical device have been calculated
343 if err = agent.updateRoutes(device, port); err != nil {
344 log.Errorw("failed-to-update-routes", log.Fields{"deviceId": device.Id, "port": port, "error": err})
345 return err
346 }
347 }
348 return nil
349}
350
khenaidoo3d3b8c22019-05-22 18:10:39 -0400351// setupLogicalPorts is invoked once the logical device has been created and is ready to get ports
352// added to it. While the logical device was being created we could have received requests to add
353// NNI and UNI ports which were discarded. Now is the time to add them if needed
354func (agent *LogicalDeviceAgent) setupLogicalPorts(ctx context.Context) error {
npujar1d86a522019-11-14 17:11:16 +0530355 log.Infow("setupLogicalPorts", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400356 // First add any NNI ports which could have been missing
npujar1d86a522019-11-14 17:11:16 +0530357 if err := agent.setupNNILogicalPorts(context.TODO(), agent.rootDeviceID); err != nil {
358 log.Errorw("error-setting-up-NNI-ports", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400359 return err
360 }
361
362 // Now, set up the UNI ports if needed.
npujar1d86a522019-11-14 17:11:16 +0530363 children, err := agent.deviceMgr.getAllChildDevices(agent.rootDeviceID)
364 if err != nil {
365 log.Errorw("error-getting-child-devices", log.Fields{"error": err, "deviceId": agent.rootDeviceID})
khenaidoo3d3b8c22019-05-22 18:10:39 -0400366 return err
npujar1d86a522019-11-14 17:11:16 +0530367 }
368 responses := make([]coreutils.Response, 0)
369 for _, child := range children.Items {
370 response := coreutils.NewResponse()
371 responses = append(responses, response)
372 go func(child *voltha.Device) {
373 if err = agent.setupUNILogicalPorts(context.TODO(), child); err != nil {
374 log.Error("setting-up-UNI-ports-failed", log.Fields{"deviceID": child.Id})
375 response.Error(status.Errorf(codes.Internal, "UNI-ports-setup-failed: %s", child.Id))
376 }
377 response.Done()
378 }(child)
379 }
380 // Wait for completion
381 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
382 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo3d3b8c22019-05-22 18:10:39 -0400383 }
384 return nil
385}
386
khenaidoofc1314d2019-03-14 09:34:21 -0400387// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
npujar1d86a522019-11-14 17:11:16 +0530388func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceID string) error {
389 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoob9203542018-09-17 22:56:37 -0400390 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400391 var err error
392
393 var device *voltha.Device
npujar1d86a522019-11-14 17:11:16 +0530394 if device, err = agent.deviceMgr.GetDevice(deviceID); err != nil {
395 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": deviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400396 return err
397 }
398
399 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400400 for _, port := range device.Ports {
401 if port.Type == voltha.Port_ETHERNET_NNI {
khenaidoo910204f2019-04-08 17:56:40 -0400402 if _, err = agent.addNNILogicalPort(device, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400403 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400404 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400405 agent.addLogicalPortToMap(port.PortNo, true)
khenaidoofc1314d2019-03-14 09:34:21 -0400406 }
407 }
khenaidoofc1314d2019-03-14 09:34:21 -0400408 return err
409}
410
khenaidoo171b98e2019-10-31 11:48:15 -0400411// updatePortState updates the port state of the device
npujar1d86a522019-11-14 17:11:16 +0530412func (agent *LogicalDeviceAgent) updatePortState(deviceID string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
413 log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "portNo": portNo, "state": operStatus})
khenaidoo171b98e2019-10-31 11:48:15 -0400414 agent.lockLogicalDevice.Lock()
415 defer agent.lockLogicalDevice.Unlock()
416 // Get the latest logical device info
npujar1d86a522019-11-14 17:11:16 +0530417 ld, err := agent.getLogicalDeviceWithoutLock()
418 if err != nil {
419 log.Warnw("logical-device-unknown", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo171b98e2019-10-31 11:48:15 -0400420 return err
khenaidoo171b98e2019-10-31 11:48:15 -0400421 }
npujar1d86a522019-11-14 17:11:16 +0530422 for idx, lPort := range ld.Ports {
423 if lPort.DeviceId == deviceID && lPort.DevicePortNo == portNo {
424 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
425 if operStatus == voltha.OperStatus_ACTIVE {
426 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
427 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
428 } else {
429 cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
430 cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
431 }
432 // Update the logical device
433 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
434 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
435 return err
436 }
437 return nil
438 }
439 }
440 return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
khenaidoo171b98e2019-10-31 11:48:15 -0400441}
442
khenaidoo3ab34882019-05-02 21:33:30 -0400443// updatePortsState updates the ports state related to the device
444func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
npujar1d86a522019-11-14 17:11:16 +0530445 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo3ab34882019-05-02 21:33:30 -0400446 agent.lockLogicalDevice.Lock()
447 defer agent.lockLogicalDevice.Unlock()
448 // Get the latest logical device info
npujar1d86a522019-11-14 17:11:16 +0530449 ld, err := agent.getLogicalDeviceWithoutLock()
450 if err != nil {
451 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
khenaidoo3ab34882019-05-02 21:33:30 -0400452 return err
npujar1d86a522019-11-14 17:11:16 +0530453 }
454 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
455 for _, lport := range cloned.Ports {
456 if lport.DeviceId == device.Id {
457 switch state {
458 case voltha.AdminState_ENABLED:
459 lport.OfpPort.Config = lport.OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
460 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
461 case voltha.AdminState_DISABLED:
462 lport.OfpPort.Config = lport.OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
463 lport.OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
464 default:
465 log.Warnw("unsupported-state-change", log.Fields{"deviceId": device.Id, "state": state})
khenaidoo3ab34882019-05-02 21:33:30 -0400466 }
467 }
npujar1d86a522019-11-14 17:11:16 +0530468 }
469 // Updating the logical device will trigger the poprt change events to be populated to the controller
470 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
471 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
472 return err
khenaidoo3ab34882019-05-02 21:33:30 -0400473 }
474 return nil
475}
476
khenaidoofc1314d2019-03-14 09:34:21 -0400477// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
478func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530479 log.Infow("setupUNILogicalPort", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoofc1314d2019-03-14 09:34:21 -0400480 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400481 var err error
khenaidoo59ef7be2019-06-21 12:40:28 -0400482 var added bool
khenaidoo19d7b632018-10-30 10:49:50 -0400483 //Get UNI port number
khenaidoo19d7b632018-10-30 10:49:50 -0400484 for _, port := range childDevice.Ports {
485 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoo59ef7be2019-06-21 12:40:28 -0400486 if added, err = agent.addUNILogicalPort(childDevice, port); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -0400487 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
khenaidoofc1314d2019-03-14 09:34:21 -0400488 }
khenaidoo59ef7be2019-06-21 12:40:28 -0400489 if added {
490 agent.addLogicalPortToMap(port.PortNo, false)
491 }
khenaidoo19d7b632018-10-30 10:49:50 -0400492 }
493 }
khenaidoofc1314d2019-03-14 09:34:21 -0400494 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400495}
496
khenaidoo0a822f92019-05-08 15:15:57 -0400497// deleteAllLogicalPorts deletes all logical ports associated with this device
498func (agent *LogicalDeviceAgent) deleteAllLogicalPorts(device *voltha.Device) error {
npujar1d86a522019-11-14 17:11:16 +0530499 log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400500 agent.lockLogicalDevice.Lock()
501 defer agent.lockLogicalDevice.Unlock()
502 // Get the latest logical device info
npujar1d86a522019-11-14 17:11:16 +0530503 ld, err := agent.getLogicalDeviceWithoutLock()
504 if err != nil {
505 log.Warnw("logical-device-unknown", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -0400506 return err
npujar1d86a522019-11-14 17:11:16 +0530507 }
508 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
509 updateLogicalPorts := []*voltha.LogicalPort{}
510 for _, lport := range cloned.Ports {
511 if lport.DeviceId != device.Id {
512 updateLogicalPorts = append(updateLogicalPorts, lport)
513 }
514 }
515 if len(updateLogicalPorts) < len(cloned.Ports) {
516 cloned.Ports = updateLogicalPorts
517 // Updating the logical device will trigger the poprt change events to be populated to the controller
518 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
519 log.Warnw("logical-device-update-failed", log.Fields{"ldeviceId": agent.logicalDeviceID, "error": err})
520 return err
521 }
khenaidoo0a822f92019-05-08 15:15:57 -0400522 } else {
npujar1d86a522019-11-14 17:11:16 +0530523 log.Debugw("no-change-required", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -0400524 }
525 return nil
526}
527
khenaidoo92e62c52018-10-03 14:02:54 -0400528//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
529func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400530 updateCtx := context.WithValue(context.Background(), model.RequestTimestamp, time.Now().UnixNano())
npujar1d86a522019-11-14 17:11:16 +0530531 afterUpdate := agent.clusterDataProxy.Update(updateCtx, "/logical_devices/"+agent.logicalDeviceID, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400532 if afterUpdate == nil {
npujar1d86a522019-11-14 17:11:16 +0530533 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceID)
khenaidoo92e62c52018-10-03 14:02:54 -0400534 }
535 return nil
536}
537
khenaidoo4c9e5592019-09-09 16:20:41 -0400538//generateDeviceGraphIfNeeded generates the device graph if the logical device has been updated since the last time
539//that device graph was generated.
540func (agent *LogicalDeviceAgent) generateDeviceGraphIfNeeded() error {
npujar1d86a522019-11-14 17:11:16 +0530541 ld, err := agent.GetLogicalDevice()
542 if err != nil {
khenaidoo4c9e5592019-09-09 16:20:41 -0400543 log.Errorw("get-logical-device-error", log.Fields{"error": err})
544 return err
khenaidoo4c9e5592019-09-09 16:20:41 -0400545 }
npujar1d86a522019-11-14 17:11:16 +0530546 agent.lockDeviceGraph.Lock()
547 defer agent.lockDeviceGraph.Unlock()
548 if agent.deviceGraph != nil && agent.deviceGraph.IsUpToDate(ld) {
549 return nil
550 }
551 log.Debug("Generation of device graph required")
552 agent.generateDeviceGraph()
khenaidoo4c9e5592019-09-09 16:20:41 -0400553 return nil
554}
555
khenaidoo19d7b632018-10-30 10:49:50 -0400556//updateFlowTable updates the flow table of that logical device
557func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
558 log.Debug("updateFlowTable")
559 if flow == nil {
560 return nil
561 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400562 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
563 return err
564 }
khenaidoo19d7b632018-10-30 10:49:50 -0400565 switch flow.GetCommand() {
566 case ofp.OfpFlowModCommand_OFPFC_ADD:
567 return agent.flowAdd(flow)
568 case ofp.OfpFlowModCommand_OFPFC_DELETE:
569 return agent.flowDelete(flow)
570 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
571 return agent.flowDeleteStrict(flow)
572 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
573 return agent.flowModify(flow)
574 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
575 return agent.flowModifyStrict(flow)
576 }
577 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530578 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, flow.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400579}
580
581//updateGroupTable updates the group table of that logical device
582func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
583 log.Debug("updateGroupTable")
584 if groupMod == nil {
585 return nil
586 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400587 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
588 return err
589 }
khenaidoo19d7b632018-10-30 10:49:50 -0400590 switch groupMod.GetCommand() {
591 case ofp.OfpGroupModCommand_OFPGC_ADD:
592 return agent.groupAdd(groupMod)
593 case ofp.OfpGroupModCommand_OFPGC_DELETE:
594 return agent.groupDelete(groupMod)
595 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
596 return agent.groupModify(groupMod)
597 }
598 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530599 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, groupMod.GetCommand())
khenaidoo19d7b632018-10-30 10:49:50 -0400600}
601
Manikkaraj kb1a10922019-07-29 12:10:34 -0400602// updateMeterTable updates the meter table of that logical device
603func (agent *LogicalDeviceAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
604 log.Debug("updateMeterTable")
605 if meterMod == nil {
606 return nil
607 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400608 if err := agent.generateDeviceGraphIfNeeded(); err != nil {
609 return err
610 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400611 switch meterMod.GetCommand() {
612 case ofp.OfpMeterModCommand_OFPMC_ADD:
613 return agent.meterAdd(meterMod)
614 case ofp.OfpMeterModCommand_OFPMC_DELETE:
615 return agent.meterDelete(meterMod)
616 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
617 return agent.meterModify(meterMod)
618 }
619 return status.Errorf(codes.Internal,
npujar1d86a522019-11-14 17:11:16 +0530620 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Manikkaraj kb1a10922019-07-29 12:10:34 -0400621
622}
623
624func (agent *LogicalDeviceAgent) meterAdd(meterMod *ofp.OfpMeterMod) error {
625 log.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
626 if meterMod == nil {
627 return nil
628 }
629 log.Debug("Waiting for logical device lock!!")
630 agent.lockLogicalDevice.Lock()
631 defer agent.lockLogicalDevice.Unlock()
632 log.Debug("Acquired logical device lock")
633 var lDevice *voltha.LogicalDevice
634 var err error
635 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530636 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
637 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400638 }
639
640 var meters []*ofp.OfpMeterEntry
641 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
642 meters = lDevice.Meters.Items
643 }
644 log.Debugw("Available meters", log.Fields{"meters": meters})
645
646 for _, meter := range meters {
647 if meterMod.MeterId == meter.Config.MeterId {
648 log.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
649 return nil
650 }
651 }
652
653 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
654 meters = append(meters, meterEntry)
655 //Update model
656 if err := agent.updateLogicalDeviceMetersWithoutLock(&ofp.Meters{Items: meters}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530657 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400658 return err
659 }
660 log.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "updated-meters": lDevice.Meters})
661 return nil
662}
663
664func (agent *LogicalDeviceAgent) meterDelete(meterMod *ofp.OfpMeterMod) error {
665 log.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
666 if meterMod == nil {
667 return nil
668 }
669 agent.lockLogicalDevice.Lock()
670 defer agent.lockLogicalDevice.Unlock()
671
672 var lDevice *voltha.LogicalDevice
673 var err error
674 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530675 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
676 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400677 }
678
679 var meters []*ofp.OfpMeterEntry
680 var flows []*ofp.OfpFlowStats
681 updatedFlows := make([]*ofp.OfpFlowStats, 0)
682 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
683 meters = lDevice.Meters.Items
684 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400685
686 changedMeter := false
687 changedFow := false
688 log.Debugw("Available meters", log.Fields{"meters": meters})
689 for index, meter := range meters {
690 if meterMod.MeterId == meter.Config.MeterId {
691 flows = lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +0530692 changedFow, updatedFlows = agent.getUpdatedFlowsAfterDeletebyMeterID(flows, meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400693 meters = append(meters[:index], meters[index+1:]...)
694 log.Debugw("Meter has been deleted", log.Fields{"meter": meter, "index": index})
695 changedMeter = true
696 break
697 }
698 }
699 if changedMeter {
700 //Update model
701 metersToUpdate := &ofp.Meters{}
702 if lDevice.Meters != nil {
703 metersToUpdate = &ofp.Meters{Items: meters}
704 }
705 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530706 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400707 return err
708 }
709 log.Debug("Meter-deleted-from-DB-successfully", log.Fields{"updatedMeters": metersToUpdate, "no-of-meter": len(metersToUpdate.Items)})
710
711 }
712 if changedFow {
713 //Update model
714 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: updatedFlows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530715 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400716 return err
717 }
718 log.Debug("Flows-associated-with-meter-deleted-from-DB-successfully",
719 log.Fields{"updated-no-of-flows": len(updatedFlows), "meter": meterMod.MeterId})
720 }
721 log.Debugw("meterDelete success", log.Fields{"meterID": meterMod.MeterId})
722 return nil
723}
724
725func (agent *LogicalDeviceAgent) meterModify(meterMod *ofp.OfpMeterMod) error {
726 log.Debug("meterModify")
727 if meterMod == nil {
728 return nil
729 }
730 agent.lockLogicalDevice.Lock()
731 defer agent.lockLogicalDevice.Unlock()
732
733 var lDevice *voltha.LogicalDevice
734 var err error
735 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530736 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
737 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400738 }
739
740 var meters []*ofp.OfpMeterEntry
741 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
742 meters = lDevice.Meters.Items
743 }
744 changedMeter := false
745 for index, meter := range meters {
746 if meterMod.MeterId == meter.Config.MeterId {
747 newmeterEntry := fu.MeterEntryFromMeterMod(meterMod)
748 newmeterEntry.Stats.FlowCount = meter.Stats.FlowCount
749 meters[index] = newmeterEntry
750 changedMeter = true
751 log.Debugw("Found meter, replaced with new meter", log.Fields{"old meter": meter, "new meter": newmeterEntry})
752 break
753 }
754 }
755 if changedMeter {
756 //Update model
757 metersToUpdate := &ofp.Meters{}
758 if lDevice.Meters != nil {
759 metersToUpdate = &ofp.Meters{Items: meters}
760 }
761 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530762 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400763 return err
764 }
765 log.Debugw("meter-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
766 return nil
767 }
768
769 log.Errorw("Meter not found ", log.Fields{"meter": meterMod})
npujar1d86a522019-11-14 17:11:16 +0530770 return fmt.Errorf("no-logical-device-present:%d", meterMod.MeterId)
Manikkaraj kb1a10922019-07-29 12:10:34 -0400771
772}
773
npujar1d86a522019-11-14 17:11:16 +0530774func (agent *LogicalDeviceAgent) getUpdatedFlowsAfterDeletebyMeterID(flows []*ofp.OfpFlowStats, meterID uint32) (bool, []*ofp.OfpFlowStats) {
775 log.Infow("Delete flows matching meter", log.Fields{"meter": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400776 changed := false
777 //updatedFlows := make([]*ofp.OfpFlowStats, 0)
778 for index := len(flows) - 1; index >= 0; index-- {
npujar1d86a522019-11-14 17:11:16 +0530779 if mID := fu.GetMeterIdFromFlow(flows[index]); mID != 0 && mID == meterID {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400780 log.Debugw("Flow to be deleted", log.Fields{"flow": flows[index], "index": index})
781 flows = append(flows[:index], flows[index+1:]...)
782 changed = true
783 }
784 }
785 return changed, flows
786}
787
788func (agent *LogicalDeviceAgent) updateFlowCountOfMeterStats(modCommand *ofp.OfpFlowMod, meters []*ofp.OfpMeterEntry, flow *ofp.OfpFlowStats) bool {
789
790 flowCommand := modCommand.GetCommand()
npujar1d86a522019-11-14 17:11:16 +0530791 meterID := fu.GetMeterIdFromFlow(flow)
792 log.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
793 if meterID == 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400794 log.Debugw("No meter present in the flow", log.Fields{"flow": *flow})
795 return false
796 }
797 if meters == nil {
798 log.Debug("No meters present in logical device")
799 return false
800 }
801 changedMeter := false
802 for _, meter := range meters {
npujar1d86a522019-11-14 17:11:16 +0530803 if meterID == meter.Config.MeterId { // Found meter in Logicaldevice
Manikkaraj kb1a10922019-07-29 12:10:34 -0400804 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
npujar1d86a522019-11-14 17:11:16 +0530805 meter.Stats.FlowCount++
Manikkaraj kb1a10922019-07-29 12:10:34 -0400806 changedMeter = true
807 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
npujar1d86a522019-11-14 17:11:16 +0530808 meter.Stats.FlowCount--
Manikkaraj kb1a10922019-07-29 12:10:34 -0400809 changedMeter = true
810 }
npujar1d86a522019-11-14 17:11:16 +0530811 log.Debugw("Found meter, updated meter flow stats", log.Fields{" meterId": meterID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400812 break
813 }
814 }
815 return changedMeter
816}
817
khenaidoo19d7b632018-10-30 10:49:50 -0400818//flowAdd adds a flow to the flow table of that logical device
819func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
khenaidoo4c9e5592019-09-09 16:20:41 -0400820 log.Debugw("flowAdd", log.Fields{"flow": mod})
khenaidoo19d7b632018-10-30 10:49:50 -0400821 if mod == nil {
822 return nil
823 }
khenaidoo92e62c52018-10-03 14:02:54 -0400824 agent.lockLogicalDevice.Lock()
825 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400826
827 var lDevice *voltha.LogicalDevice
828 var err error
829 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530830 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
831 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400832 }
833
834 var flows []*ofp.OfpFlowStats
Manikkaraj kb1a10922019-07-29 12:10:34 -0400835 var meters []*ofp.OfpMeterEntry
836 var flow *ofp.OfpFlowStats
837
khenaidoo19d7b632018-10-30 10:49:50 -0400838 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
839 flows = lDevice.Flows.Items
840 }
841
Manikkaraj kb1a10922019-07-29 12:10:34 -0400842 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
843 meters = lDevice.Meters.Items
844 }
khenaidoo2c6a0992019-04-29 13:46:56 -0400845 updatedFlows := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400846 changed := false
Manikkaraj kb1a10922019-07-29 12:10:34 -0400847 updated := false
khenaidoo19d7b632018-10-30 10:49:50 -0400848 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
849 if checkOverlap {
850 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
851 // TODO: should this error be notified other than being logged?
npujar1d86a522019-11-14 17:11:16 +0530852 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400853 } else {
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400854 // Add flow
Manikkaraj kb1a10922019-07-29 12:10:34 -0400855 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400856 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400857 updatedFlows = append(updatedFlows, flow)
khenaidoo19d7b632018-10-30 10:49:50 -0400858 changed = true
859 }
860 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400861 flow = fu.FlowStatsEntryFromFlowModMessage(mod)
khenaidoo19d7b632018-10-30 10:49:50 -0400862 idx := fu.FindFlows(flows, flow)
863 if idx >= 0 {
864 oldFlow := flows[idx]
865 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
866 flow.ByteCount = oldFlow.ByteCount
867 flow.PacketCount = oldFlow.PacketCount
868 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400869 if !reflect.DeepEqual(oldFlow, flow) {
870 flows[idx] = flow
871 updatedFlows = append(updatedFlows, flow)
872 changed = true
873 updated = true
874 }
875 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400876 flows = append(flows, flow)
khenaidoo2c6a0992019-04-29 13:46:56 -0400877 updatedFlows = append(updatedFlows, flow)
878 changed = true
khenaidoo19d7b632018-10-30 10:49:50 -0400879 }
khenaidoo19d7b632018-10-30 10:49:50 -0400880 }
khenaidoo4c9e5592019-09-09 16:20:41 -0400881 log.Debugw("flowAdd-changed", log.Fields{"changed": changed})
882
khenaidoo19d7b632018-10-30 10:49:50 -0400883 if changed {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400884 var flowMetadata voltha.FlowMetadata
885 if err := agent.GetMeterConfig(updatedFlows, meters, &flowMetadata); err != nil { // This should never happen,meters should be installed before flow arrives
886 log.Error("Meter-referred-in-flows-not-present")
887 return err
888 }
khenaidoo0458db62019-06-20 08:50:36 -0400889 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: updatedFlows}, *lDevice.FlowGroups)
890 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
891
Manikkaraj kb1a10922019-07-29 12:10:34 -0400892 if err := agent.addDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530893 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo2c6a0992019-04-29 13:46:56 -0400894 return err
895 }
896
khenaidoo19d7b632018-10-30 10:49:50 -0400897 // Update model
khenaidoo0458db62019-06-20 08:50:36 -0400898 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530899 log.Errorw("db-flow-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -0400900 return err
901 }
Matt Jeanneret518b5a42019-10-29 10:30:46 -0400902 if !updated {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400903 changedMeterStats := agent.updateFlowCountOfMeterStats(mod, meters, flow)
904 metersToUpdate := &ofp.Meters{}
905 if lDevice.Meters != nil {
906 metersToUpdate = &ofp.Meters{Items: meters}
907 }
908 if changedMeterStats {
909 //Update model
910 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530911 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400912 return err
913 }
914 log.Debugw("meter-stats-updated-in-DB-successfully", log.Fields{"updated_meters": meters})
915
916 }
917 }
918
khenaidoo19d7b632018-10-30 10:49:50 -0400919 }
khenaidoo19d7b632018-10-30 10:49:50 -0400920 return nil
921}
922
npujar1d86a522019-11-14 17:11:16 +0530923// GetMeterConfig returns meter config
Manikkaraj kb1a10922019-07-29 12:10:34 -0400924func (agent *LogicalDeviceAgent) GetMeterConfig(flows []*ofp.OfpFlowStats, meters []*ofp.OfpMeterEntry, metadata *voltha.FlowMetadata) error {
925 m := make(map[uint32]bool)
926 for _, flow := range flows {
npujar1d86a522019-11-14 17:11:16 +0530927 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 && !m[flowMeterID] {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400928 foundMeter := false
929 // Meter is present in the flow , Get from logical device
930 for _, meter := range meters {
931 if flowMeterID == meter.Config.MeterId {
932 metadata.Meters = append(metadata.Meters, meter.Config)
933 log.Debugw("Found meter in logical device",
934 log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
935 m[flowMeterID] = true
936 foundMeter = true
937 break
938 }
939 }
940 if !foundMeter {
941 log.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
npujar1d86a522019-11-14 17:11:16 +0530942 log.Fields{"meterID": flowMeterID, "Available-meters": meters, "flow": *flow})
Manikkaraj kb1a10922019-07-29 12:10:34 -0400943 return errors.New("Meter-referred-by-flow-is-not-found-in-logicaldevice")
944 }
945 }
946 }
947 log.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "metadata": metadata})
948 return nil
949
950}
951
khenaidoo19d7b632018-10-30 10:49:50 -0400952//flowDelete deletes a flow from the flow table of that logical device
953func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
954 log.Debug("flowDelete")
955 if mod == nil {
956 return nil
957 }
958 agent.lockLogicalDevice.Lock()
959 defer agent.lockLogicalDevice.Unlock()
960
961 var lDevice *voltha.LogicalDevice
962 var err error
963 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +0530964 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
965 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -0400966 }
khenaidoo19d7b632018-10-30 10:49:50 -0400967
Manikkaraj kb1a10922019-07-29 12:10:34 -0400968 var meters []*ofp.OfpMeterEntry
969 var flows []*ofp.OfpFlowStats
970
971 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
972 flows = lDevice.Flows.Items
973 }
974
975 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
976 meters = lDevice.Meters.Items
977 }
khenaidoo19d7b632018-10-30 10:49:50 -0400978 //build a list of what to keep vs what to delete
979 toKeep := make([]*ofp.OfpFlowStats, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400980 toDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -0400981 for _, f := range flows {
khenaidoo0458db62019-06-20 08:50:36 -0400982 // Check whether the flow and the flowmod matches
983 if fu.FlowMatch(f, fu.FlowStatsEntryFromFlowModMessage(mod)) {
984 toDelete = append(toDelete, f)
985 continue
986 }
987 // Check wild card match
khenaidoo19d7b632018-10-30 10:49:50 -0400988 if !fu.FlowMatchesMod(f, mod) {
989 toKeep = append(toKeep, f)
khenaidoo0458db62019-06-20 08:50:36 -0400990 } else {
991 toDelete = append(toDelete, f)
khenaidoo19d7b632018-10-30 10:49:50 -0400992 }
993 }
994
npujar1d86a522019-11-14 17:11:16 +0530995 log.Debugw("flowDelete", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "toKeep": len(toKeep), "toDelete": toDelete})
khenaidoo0458db62019-06-20 08:50:36 -0400996
khenaidoo19d7b632018-10-30 10:49:50 -0400997 //Update flows
khenaidoo0458db62019-06-20 08:50:36 -0400998 if len(toDelete) > 0 {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400999 var flowMetadata voltha.FlowMetadata
1000 if err := agent.GetMeterConfig(toDelete, meters, &flowMetadata); err != nil { // This should never happen
1001 log.Error("Meter-referred-in-flows-not-present")
1002 return errors.New("Meter-referred-in-flows-not-present")
1003 }
khenaidoo0458db62019-06-20 08:50:36 -04001004 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: toDelete}, ofp.FlowGroups{})
1005 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1006
Manikkaraj kb1a10922019-07-29 12:10:34 -04001007 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301008 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001009 return err
1010 }
1011
khenaidoo43c82122018-11-22 18:38:28 -05001012 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301013 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001014 return err
1015 }
1016 }
1017
1018 //TODO: send announcement on delete
1019 return nil
1020}
1021
Manikkaraj kb1a10922019-07-29 12:10:34 -04001022func (agent *LogicalDeviceAgent) addDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301023 log.Debugw("addDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID, "deviceRules": deviceRules, "flowMetadata": flowMetadata})
khenaidoo19d7b632018-10-30 10:49:50 -04001024
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001025 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301026 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001027 response := coreutils.NewResponse()
1028 responses = append(responses, response)
1029 go func(deviceId string, value *fu.FlowsAndGroups) {
1030 if err := agent.deviceMgr.addFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001031 log.Errorw("flow-add-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001032 response.Error(status.Errorf(codes.Internal, "flow-add-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001033 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001034 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301035 }(deviceID, value)
khenaidoo19d7b632018-10-30 10:49:50 -04001036 }
khenaidoo0458db62019-06-20 08:50:36 -04001037 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001038 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001039 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001040 }
khenaidoo0458db62019-06-20 08:50:36 -04001041 return nil
1042}
khenaidoo19d7b632018-10-30 10:49:50 -04001043
Manikkaraj kb1a10922019-07-29 12:10:34 -04001044func (agent *LogicalDeviceAgent) deleteDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301045 log.Debugw("deleteDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001046
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001047 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301048 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001049 response := coreutils.NewResponse()
1050 responses = append(responses, response)
1051 go func(deviceId string, value *fu.FlowsAndGroups) {
1052 if err := agent.deviceMgr.deleteFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001053 log.Error("flow-delete-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001054 response.Error(status.Errorf(codes.Internal, "flow-delete-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001055 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001056 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301057 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001058 }
1059 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001060 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001061 return status.Errorf(codes.Aborted, "errors-%s", res)
1062 }
1063 return nil
1064}
1065
Manikkaraj kb1a10922019-07-29 12:10:34 -04001066func (agent *LogicalDeviceAgent) updateDeviceFlowsAndGroups(deviceRules *fu.DeviceRules, flowMetadata *voltha.FlowMetadata) error {
npujar1d86a522019-11-14 17:11:16 +05301067 log.Debugw("updateDeviceFlowsAndGroups", log.Fields{"logicalDeviceID": agent.logicalDeviceID})
khenaidoo0458db62019-06-20 08:50:36 -04001068
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001069 responses := make([]coreutils.Response, 0)
npujar1d86a522019-11-14 17:11:16 +05301070 for deviceID, value := range deviceRules.GetRules() {
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001071 response := coreutils.NewResponse()
1072 responses = append(responses, response)
1073 go func(deviceId string, value *fu.FlowsAndGroups) {
1074 if err := agent.deviceMgr.updateFlowsAndGroups(deviceId, value.ListFlows(), value.ListGroups(), flowMetadata); err != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001075 log.Error("flow-update-failed", log.Fields{"deviceID": deviceId, "error": err})
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001076 response.Error(status.Errorf(codes.Internal, "flow-update-failed: %s", deviceId))
khenaidoo0458db62019-06-20 08:50:36 -04001077 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001078 response.Done()
npujar1d86a522019-11-14 17:11:16 +05301079 }(deviceID, value)
khenaidoo0458db62019-06-20 08:50:36 -04001080 }
1081 // Wait for completion
Kent Hagerman8da2f1e2019-11-25 17:28:09 -05001082 if res := coreutils.WaitForNilOrErrorResponses(agent.defaultTimeout, responses...); res != nil {
khenaidoo0458db62019-06-20 08:50:36 -04001083 return status.Errorf(codes.Aborted, "errors-%s", res)
khenaidoo19d7b632018-10-30 10:49:50 -04001084 }
1085 return nil
1086}
1087
1088//flowDeleteStrict deletes a flow from the flow table of that logical device
1089func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
1090 log.Debug("flowDeleteStrict")
1091 if mod == nil {
1092 return nil
1093 }
1094 agent.lockLogicalDevice.Lock()
1095 defer agent.lockLogicalDevice.Unlock()
1096
1097 var lDevice *voltha.LogicalDevice
1098 var err error
1099 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301100 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
1101 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001102 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001103 var meters []*ofp.OfpMeterEntry
1104 var flows []*ofp.OfpFlowStats
1105 if lDevice.Meters != nil && lDevice.Meters.Items != nil {
1106 meters = lDevice.Meters.Items
1107 }
1108 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
1109 flows = lDevice.Flows.Items
1110 }
1111
1112 changedFlow := false
1113 changedMeter := false
khenaidoo68c930b2019-05-13 11:46:51 -04001114 flow := fu.FlowStatsEntryFromFlowModMessage(mod)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001115 flowsToDelete := make([]*ofp.OfpFlowStats, 0)
khenaidoo19d7b632018-10-30 10:49:50 -04001116 idx := fu.FindFlows(flows, flow)
1117 if idx >= 0 {
Gamze Abaka6e4ac162019-10-21 11:10:10 +00001118 changedMeter = agent.updateFlowCountOfMeterStats(mod, meters, flows[idx])
Manikkaraj kb1a10922019-07-29 12:10:34 -04001119 flowsToDelete = append(flowsToDelete, flows[idx])
khenaidoo19d7b632018-10-30 10:49:50 -04001120 flows = append(flows[:idx], flows[idx+1:]...)
Manikkaraj kb1a10922019-07-29 12:10:34 -04001121 changedFlow = true
khenaidoo19d7b632018-10-30 10:49:50 -04001122 } else {
npujar1d86a522019-11-14 17:11:16 +05301123 return fmt.Errorf("Cannot delete flow - %s", flow)
khenaidoo19d7b632018-10-30 10:49:50 -04001124 }
Manikkaraj kb1a10922019-07-29 12:10:34 -04001125 if changedMeter {
1126 //Update model
1127 metersToUpdate := &ofp.Meters{}
1128 if lDevice.Meters != nil {
1129 metersToUpdate = &ofp.Meters{Items: meters}
1130 }
1131 if err := agent.updateLogicalDeviceMetersWithoutLock(metersToUpdate); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301132 log.Errorw("db-meter-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001133 return err
1134 }
khenaidoo19d7b632018-10-30 10:49:50 -04001135
Manikkaraj kb1a10922019-07-29 12:10:34 -04001136 }
1137 if changedFlow {
1138 var flowMetadata voltha.FlowMetadata
1139 if err := agent.GetMeterConfig(flowsToDelete, meters, &flowMetadata); err != nil {
1140 log.Error("Meter-referred-in-flows-not-present")
1141 return err
1142 }
1143 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flowsToDelete}, ofp.FlowGroups{})
khenaidoo0458db62019-06-20 08:50:36 -04001144 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1145
Manikkaraj kb1a10922019-07-29 12:10:34 -04001146 if err := agent.deleteDeviceFlowsAndGroups(deviceRules, &flowMetadata); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301147 log.Errorw("failure-deleting-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001148 return err
1149 }
1150
khenaidoo43c82122018-11-22 18:38:28 -05001151 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301152 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001153 return err
1154 }
1155 }
khenaidoo19d7b632018-10-30 10:49:50 -04001156 return nil
1157}
1158
1159//flowModify modifies a flow from the flow table of that logical device
1160func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
1161 return errors.New("flowModify not implemented")
1162}
1163
1164//flowModifyStrict deletes a flow from the flow table of that logical device
1165func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
1166 return errors.New("flowModifyStrict not implemented")
1167}
1168
1169func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
1170 log.Debug("groupAdd")
1171 if groupMod == nil {
1172 return nil
1173 }
1174 agent.lockLogicalDevice.Lock()
1175 defer agent.lockLogicalDevice.Unlock()
1176
1177 var lDevice *voltha.LogicalDevice
1178 var err error
1179 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301180 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
1181 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001182 }
1183 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -04001184 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
khenaidoo68c930b2019-05-13 11:46:51 -04001185 groups = append(groups, fu.GroupEntryFromGroupMod(groupMod))
khenaidoo0458db62019-06-20 08:50:36 -04001186
1187 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *lDevice.Flows, ofp.FlowGroups{Items: groups})
1188 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
Manikkaraj kb1a10922019-07-29 12:10:34 -04001189 if err := agent.addDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301190 log.Errorw("failure-updating-device-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001191 return err
1192 }
1193
khenaidoo43c82122018-11-22 18:38:28 -05001194 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301195 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001196 return err
1197 }
1198 } else {
npujar1d86a522019-11-14 17:11:16 +05301199 return fmt.Errorf("Groups %d already present", groupMod.GroupId)
khenaidoo19d7b632018-10-30 10:49:50 -04001200 }
khenaidoo19d7b632018-10-30 10:49:50 -04001201 return nil
1202}
1203
1204func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
1205 log.Debug("groupDelete")
1206 if groupMod == nil {
1207 return nil
1208 }
1209 agent.lockLogicalDevice.Lock()
1210 defer agent.lockLogicalDevice.Unlock()
1211
1212 var lDevice *voltha.LogicalDevice
1213 var err error
1214 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301215 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
1216 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001217 }
1218 groups := lDevice.FlowGroups.Items
1219 flows := lDevice.Flows.Items
npujar1d86a522019-11-14 17:11:16 +05301220 var groupsChanged bool
khenaidoo19d7b632018-10-30 10:49:50 -04001221 flowsChanged := false
npujar1d86a522019-11-14 17:11:16 +05301222 groupID := groupMod.GroupId
1223 if groupID == uint32(ofp.OfpGroup_OFPG_ALL) {
khenaidoo19d7b632018-10-30 10:49:50 -04001224 //TODO we must delete all flows that point to this group and
1225 //signal controller as requested by flow's flag
1226 groups = []*ofp.OfpGroupEntry{}
1227 groupsChanged = true
1228 } else {
npujar1d86a522019-11-14 17:11:16 +05301229 idx := fu.FindGroup(groups, groupID)
1230 if idx == -1 {
khenaidoo19d7b632018-10-30 10:49:50 -04001231 return nil // Valid case
khenaidoo19d7b632018-10-30 10:49:50 -04001232 }
npujar1d86a522019-11-14 17:11:16 +05301233 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupID)
1234 groups = append(groups[:idx], groups[idx+1:]...)
1235 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001236 }
khenaidoo0458db62019-06-20 08:50:36 -04001237 if flowsChanged || groupsChanged {
1238 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: flows}, ofp.FlowGroups{Items: groups})
1239 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1240
Manikkaraj kb1a10922019-07-29 12:10:34 -04001241 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301242 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001243 return err
1244 }
1245 }
1246
khenaidoo43c82122018-11-22 18:38:28 -05001247 if groupsChanged {
1248 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301249 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001250 return err
1251 }
1252 }
khenaidoo43c82122018-11-22 18:38:28 -05001253 if flowsChanged {
1254 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301255 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo43c82122018-11-22 18:38:28 -05001256 return err
1257 }
1258 }
khenaidoo19d7b632018-10-30 10:49:50 -04001259 return nil
1260}
1261
1262func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
1263 log.Debug("groupModify")
1264 if groupMod == nil {
1265 return nil
1266 }
1267 agent.lockLogicalDevice.Lock()
1268 defer agent.lockLogicalDevice.Unlock()
1269
1270 var lDevice *voltha.LogicalDevice
1271 var err error
1272 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301273 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
1274 return fmt.Errorf("no-logical-device-present:%s", agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001275 }
1276 groups := lDevice.FlowGroups.Items
npujar1d86a522019-11-14 17:11:16 +05301277 var groupsChanged bool
1278 groupID := groupMod.GroupId
1279 idx := fu.FindGroup(groups, groupID)
1280 if idx == -1 {
1281 return fmt.Errorf("group-absent:%d", groupID)
khenaidoo19d7b632018-10-30 10:49:50 -04001282 }
npujar1d86a522019-11-14 17:11:16 +05301283 //replace existing group entry with new group definition
1284 groupEntry := fu.GroupEntryFromGroupMod(groupMod)
1285 groups[idx] = groupEntry
1286 groupsChanged = true
khenaidoo19d7b632018-10-30 10:49:50 -04001287 if groupsChanged {
khenaidoo0458db62019-06-20 08:50:36 -04001288 deviceRules := agent.flowDecomposer.DecomposeRules(agent, ofp.Flows{Items: lDevice.Flows.Items}, ofp.FlowGroups{Items: groups})
1289 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1290
Manikkaraj kb1a10922019-07-29 12:10:34 -04001291 if err := agent.updateDeviceFlowsAndGroups(deviceRules, nil); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301292 log.Errorw("failure-updating-device-flows-groups", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0458db62019-06-20 08:50:36 -04001293 return err
1294 }
1295
khenaidoo43c82122018-11-22 18:38:28 -05001296 //lDevice.FlowGroups.Items = groups
1297 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301298 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo19d7b632018-10-30 10:49:50 -04001299 return err
1300 }
1301 }
1302 return nil
1303}
1304
1305// deleteLogicalPort removes the logical port
1306func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
1307 agent.lockLogicalDevice.Lock()
1308 defer agent.lockLogicalDevice.Unlock()
1309
khenaidoo92e62c52018-10-03 14:02:54 -04001310 // Get the most up to date logical device
1311 var logicaldevice *voltha.LogicalDevice
1312 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
npujar1d86a522019-11-14 17:11:16 +05301313 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -04001314 return nil
1315 }
khenaidoo92e62c52018-10-03 14:02:54 -04001316 index := -1
1317 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -04001318 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -04001319 index = i
1320 break
1321 }
1322 }
1323 if index >= 0 {
1324 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
1325 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
1326 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
npujar1d86a522019-11-14 17:11:16 +05301327 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001328 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301329 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001330 return err
1331 }
1332 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001333 go agent.generateDeviceGraph()
khenaidoo92e62c52018-10-03 14:02:54 -04001334 }
1335 return nil
khenaidoob9203542018-09-17 22:56:37 -04001336}
1337
khenaidoo0a822f92019-05-08 15:15:57 -04001338// deleteLogicalPorts removes the logical ports associated with that deviceId
npujar1d86a522019-11-14 17:11:16 +05301339func (agent *LogicalDeviceAgent) deleteLogicalPorts(deviceID string) error {
khenaidoo0a822f92019-05-08 15:15:57 -04001340 agent.lockLogicalDevice.Lock()
1341 defer agent.lockLogicalDevice.Unlock()
1342
1343 // Get the most up to date logical device
1344 var logicaldevice *voltha.LogicalDevice
1345 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
npujar1d86a522019-11-14 17:11:16 +05301346 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001347 return nil
1348 }
1349 updatedLPorts := []*voltha.LogicalPort{}
1350 for _, logicalPort := range logicaldevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301351 if logicalPort.DeviceId != deviceID {
khenaidoo0a822f92019-05-08 15:15:57 -04001352 updatedLPorts = append(updatedLPorts, logicalPort)
1353 }
1354 }
1355 logicaldevice.Ports = updatedLPorts
1356 log.Debugw("updated-logical-ports", log.Fields{"ports": updatedLPorts})
1357 if err := agent.updateLogicalDeviceWithoutLock(logicaldevice); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301358 log.Errorw("logical-device-update-failed", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001359 return err
1360 }
1361 // Reset the logical device graph
khenaidoo3d3b8c22019-05-22 18:10:39 -04001362 go agent.generateDeviceGraph()
khenaidoo0a822f92019-05-08 15:15:57 -04001363
1364 return nil
1365}
1366
khenaidoo19d7b632018-10-30 10:49:50 -04001367// enableLogicalPort enables the logical port
npujar1d86a522019-11-14 17:11:16 +05301368func (agent *LogicalDeviceAgent) enableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001369 agent.lockLogicalDevice.Lock()
1370 defer agent.lockLogicalDevice.Unlock()
1371
1372 // Get the most up to date logical device
1373 var logicaldevice *voltha.LogicalDevice
1374 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
npujar1d86a522019-11-14 17:11:16 +05301375 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "logicalPortId": lPortID})
khenaidoo19d7b632018-10-30 10:49:50 -04001376 return nil
1377 }
1378 index := -1
1379 for i, logicalPort := range logicaldevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301380 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001381 index = i
1382 break
1383 }
1384 }
1385 if index >= 0 {
1386 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1387 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
1388 }
npujar1d86a522019-11-14 17:11:16 +05301389 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001390}
1391
1392// disableLogicalPort disabled the logical port
npujar1d86a522019-11-14 17:11:16 +05301393func (agent *LogicalDeviceAgent) disableLogicalPort(lPortID string) error {
khenaidoo19d7b632018-10-30 10:49:50 -04001394 agent.lockLogicalDevice.Lock()
1395 defer agent.lockLogicalDevice.Unlock()
1396
1397 // Get the most up to date logical device
1398 var logicaldevice *voltha.LogicalDevice
1399 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
npujar1d86a522019-11-14 17:11:16 +05301400 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "logicalPortId": lPortID})
khenaidoo19d7b632018-10-30 10:49:50 -04001401 return nil
1402 }
1403 index := -1
1404 for i, logicalPort := range logicaldevice.Ports {
npujar1d86a522019-11-14 17:11:16 +05301405 if logicalPort.Id == lPortID {
khenaidoo19d7b632018-10-30 10:49:50 -04001406 index = i
1407 break
1408 }
1409 }
1410 if index >= 0 {
1411 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
1412 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
1413 }
npujar1d86a522019-11-14 17:11:16 +05301414 return status.Errorf(codes.NotFound, "Port %s on Logical Device %s", lPortID, agent.logicalDeviceID)
khenaidoo19d7b632018-10-30 10:49:50 -04001415}
1416
khenaidoo89b0e942018-10-21 21:11:33 -04001417func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -04001418 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -04001419 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001420 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -04001421 if ingress == routeLink.Ingress && egress == routeLink.Egress {
1422 return route
1423 }
1424 }
npujar1d86a522019-11-14 17:11:16 +05301425 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "ingress": ingress, "egress": egress})
khenaidoo89b0e942018-10-21 21:11:33 -04001426 return nil
1427}
1428
npujar1d86a522019-11-14 17:11:16 +05301429// GetRoute returns route
khenaidoo19d7b632018-10-30 10:49:50 -04001430func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -04001431 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001432 routes := make([]graph.RouteHop, 0)
khenaidoo2c6a0992019-04-29 13:46:56 -04001433
khenaidoo19d7b632018-10-30 10:49:50 -04001434 // Note: A port value of 0 is equivalent to a nil port
1435
khenaidoo89b0e942018-10-21 21:11:33 -04001436 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -04001437 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo2c6a0992019-04-29 13:46:56 -04001438 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
1439 if agent.isNNIPort(ingressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001440 //This is a trap on the NNI Port
khenaidoo8f474192019-04-03 17:20:44 -04001441 if len(agent.deviceGraph.Routes) == 0 {
1442 // 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 -04001443 // route with same IngressHop and EgressHop
npujar1d86a522019-11-14 17:11:16 +05301444 hop := graph.RouteHop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
khenaidoo8f474192019-04-03 17:20:44 -04001445 routes = append(routes, hop)
1446 routes = append(routes, hop)
1447 return routes
1448 }
khenaidoo89b0e942018-10-21 21:11:33 -04001449 //Return a 'half' route to make the flow decomposer logic happy
1450 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001451 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001452 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1453 routes = append(routes, route[1])
1454 return routes
1455 }
1456 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001457 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001458 return nil
1459 }
1460 //treat it as if the output port is the first NNI of the OLT
khenaidoo2c6a0992019-04-29 13:46:56 -04001461 var err error
1462 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
1463 log.Warnw("no-nni-port", log.Fields{"error": err})
1464 return nil
1465 }
khenaidoo89b0e942018-10-21 21:11:33 -04001466 }
1467 //If ingress port is not specified (nil), it may be a wildcarded
1468 //route if egress port is OFPP_CONTROLLER or a nni logical port,
1469 //in which case we need to create a half-route where only the egress
1470 //hop is filled, the first hop is nil
khenaidoo2c6a0992019-04-29 13:46:56 -04001471 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo89b0e942018-10-21 21:11:33 -04001472 // We can use the 2nd hop of any upstream route, so just find the first upstream:
1473 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo2c6a0992019-04-29 13:46:56 -04001474 if agent.isNNIPort(routeLink.Egress) {
khenaidoo89b0e942018-10-21 21:11:33 -04001475 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
1476 routes = append(routes, route[1])
1477 return routes
1478 }
1479 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001480 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001481 return nil
1482 }
1483 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -04001484 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -04001485 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -04001486 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -04001487 routes = append(routes, route[0])
1488 routes = append(routes, graph.RouteHop{})
1489 return routes
1490 }
1491 }
khenaidoo2c6a0992019-04-29 13:46:56 -04001492 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
khenaidoo89b0e942018-10-21 21:11:33 -04001493 return nil
1494 }
khenaidoo89b0e942018-10-21 21:11:33 -04001495 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -04001496 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -04001497}
1498
khenaidoo3d3b8c22019-05-22 18:10:39 -04001499//GetWildcardInputPorts filters out the logical port number from the set of logical ports on the device and
1500//returns their port numbers. This function is invoked only during flow decomposition where the lock on the logical
1501//device is already held. Therefore it is safe to retrieve the logical device without lock.
khenaidoo89b0e942018-10-21 21:11:33 -04001502func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
1503 lPorts := make([]uint32, 0)
1504 var exclPort uint32
1505 if len(excludePort) == 1 {
1506 exclPort = excludePort[0]
1507 }
khenaidoo3d3b8c22019-05-22 18:10:39 -04001508 if lDevice, _ := agent.getLogicalDeviceWithoutLock(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -04001509 for _, port := range lDevice.Ports {
1510 if port.OfpPort.PortNo != exclPort {
1511 lPorts = append(lPorts, port.OfpPort.PortNo)
1512 }
1513 }
1514 }
1515 return lPorts
1516}
khenaidoo19d7b632018-10-30 10:49:50 -04001517
npujar1d86a522019-11-14 17:11:16 +05301518// GetDeviceGraph returns device graph
khenaidoo19d7b632018-10-30 10:49:50 -04001519func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1520 return agent.deviceGraph
1521}
1522
khenaidoo3306c992019-05-24 16:57:35 -04001523//updateRoutes rebuilds the device graph if not done already
khenaidoo2c6a0992019-04-29 13:46:56 -04001524func (agent *LogicalDeviceAgent) updateRoutes(device *voltha.Device, port *voltha.Port) error {
npujar1d86a522019-11-14 17:11:16 +05301525 log.Debugf("updateRoutes", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "device": device.Id, "port": port})
khenaidoo910204f2019-04-08 17:56:40 -04001526 agent.lockLogicalDevice.Lock()
1527 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -04001528 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301529 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo2c6a0992019-04-29 13:46:56 -04001530 }
1531 // Get all the logical ports on that logical device
npujar1d86a522019-11-14 17:11:16 +05301532 lDevice, err := agent.getLogicalDeviceWithoutLock()
1533 if err != nil {
1534 log.Errorw("unknown-logical-device", log.Fields{"error": err, "logicalDeviceId": agent.logicalDeviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -04001535 return err
khenaidoo2c6a0992019-04-29 13:46:56 -04001536 }
npujar1d86a522019-11-14 17:11:16 +05301537 //TODO: Find a better way to refresh only missing routes
1538 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
khenaidoo2c6a0992019-04-29 13:46:56 -04001539 agent.deviceGraph.Print()
1540 return nil
khenaidoo19d7b632018-10-30 10:49:50 -04001541}
1542
khenaidoo2c6a0992019-04-29 13:46:56 -04001543//updateDeviceGraph updates the device graph if not done already and setup the default rules as well
khenaidoo910204f2019-04-08 17:56:40 -04001544func (agent *LogicalDeviceAgent) updateDeviceGraph(lp *voltha.LogicalPort) {
npujar1d86a522019-11-14 17:11:16 +05301545 log.Debugf("updateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo2c6a0992019-04-29 13:46:56 -04001546 agent.lockLogicalDevice.Lock()
1547 defer agent.lockLogicalDevice.Unlock()
khenaidoo910204f2019-04-08 17:56:40 -04001548 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301549 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo910204f2019-04-08 17:56:40 -04001550 }
1551 agent.deviceGraph.AddPort(lp)
khenaidoo2c6a0992019-04-29 13:46:56 -04001552 agent.deviceGraph.Print()
khenaidoo19d7b632018-10-30 10:49:50 -04001553}
khenaidoofdbad6e2018-11-06 22:26:38 -05001554
khenaidoo3d3b8c22019-05-22 18:10:39 -04001555//generateDeviceGraph regenerates the device graph
1556func (agent *LogicalDeviceAgent) generateDeviceGraph() {
npujar1d86a522019-11-14 17:11:16 +05301557 log.Debugw("generateDeviceGraph", log.Fields{"logicalDeviceId": agent.logicalDeviceID})
khenaidoo0a822f92019-05-08 15:15:57 -04001558 agent.lockLogicalDevice.Lock()
1559 defer agent.lockLogicalDevice.Unlock()
1560 // Get the latest logical device
1561 if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
npujar1d86a522019-11-14 17:11:16 +05301562 log.Errorw("logical-device-not-present", log.Fields{"logicalDeviceId": agent.logicalDeviceID, "error": err})
khenaidoo0a822f92019-05-08 15:15:57 -04001563 } else {
npujar1d86a522019-11-14 17:11:16 +05301564 log.Debugw("generating-graph", log.Fields{"lDeviceId": agent.logicalDeviceID, "lPorts": len(ld.Ports)})
khenaidoo3d3b8c22019-05-22 18:10:39 -04001565 if agent.deviceGraph == nil {
npujar1d86a522019-11-14 17:11:16 +05301566 agent.deviceGraph = graph.NewDeviceGraph(agent.logicalDeviceID, agent.deviceMgr.GetDevice)
khenaidoo3d3b8c22019-05-22 18:10:39 -04001567 }
khenaidoo0a822f92019-05-08 15:15:57 -04001568 agent.deviceGraph.ComputeRoutes(ld.Ports)
khenaidoo3d3b8c22019-05-22 18:10:39 -04001569 agent.deviceGraph.Print()
khenaidoo0a822f92019-05-08 15:15:57 -04001570 }
1571}
1572
khenaidoofc1314d2019-03-14 09:34:21 -04001573// 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 -04001574func diff(oldList, newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
khenaidoofc1314d2019-03-14 09:34:21 -04001575 newPorts = make([]*voltha.LogicalPort, 0)
1576 changedPorts = make([]*voltha.LogicalPort, 0)
1577 deletedPorts = make([]*voltha.LogicalPort, 0)
1578 for _, o := range oldList {
1579 found := false
khenaidoofc1314d2019-03-14 09:34:21 -04001580 for _, n := range newList {
1581 if o.Id == n.Id {
khenaidoofc1314d2019-03-14 09:34:21 -04001582 found = true
1583 break
1584 }
1585 }
1586 if !found {
1587 deletedPorts = append(deletedPorts, o)
1588 }
khenaidoofc1314d2019-03-14 09:34:21 -04001589 }
1590 for _, n := range newList {
1591 found := false
khenaidoo2bc48282019-07-16 18:13:46 -04001592 changed := false
khenaidoofc1314d2019-03-14 09:34:21 -04001593 for _, o := range oldList {
1594 if o.Id == n.Id {
khenaidoo2bc48282019-07-16 18:13:46 -04001595 changed = !reflect.DeepEqual(o, n)
khenaidoofc1314d2019-03-14 09:34:21 -04001596 found = true
1597 break
1598 }
1599 }
1600 if !found {
1601 newPorts = append(newPorts, n)
1602 }
khenaidoo2bc48282019-07-16 18:13:46 -04001603 if changed {
1604 changedPorts = append(changedPorts, n)
1605 }
khenaidoofc1314d2019-03-14 09:34:21 -04001606 }
1607 return
1608}
1609
1610// portUpdated is invoked when a port is updated on the logical device. Until
1611// the POST_ADD notification is fixed, we will use the logical device to
1612// update that data.
1613func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1614 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1615
1616 var oldLD *voltha.LogicalDevice
1617 var newlD *voltha.LogicalDevice
1618
1619 var ok bool
1620 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1621 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1622 return nil
1623 }
1624 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1625 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1626 return nil
1627 }
1628
1629 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1630 log.Debug("ports-have-not-changed")
1631 return nil
1632 }
1633
1634 // Get the difference between the two list
1635 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1636
1637 // Send the port change events to the OF controller
khenaidoo2c6a0992019-04-29 13:46:56 -04001638 for _, newP := range newPorts {
npujar1d86a522019-11-14 17:11:16 +05301639 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo2c6a0992019-04-29 13:46:56 -04001640 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_ADD, Desc: newP.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001641 }
1642 for _, change := range changedPorts {
npujar1d86a522019-11-14 17:11:16 +05301643 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001644 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_MODIFY, Desc: change.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001645 }
1646 for _, del := range deletedPorts {
npujar1d86a522019-11-14 17:11:16 +05301647 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceID,
khenaidoo910204f2019-04-08 17:56:40 -04001648 &ofp.OfpPortStatus{Reason: ofp.OfpPortReason_OFPPR_DELETE, Desc: del.OfpPort})
khenaidoofc1314d2019-03-14 09:34:21 -04001649 }
1650
1651 return nil
1652}
1653
khenaidoo8f474192019-04-03 17:20:44 -04001654// addNNILogicalPort adds an NNI port to the logical device. It returns a bool representing whether a port has been
1655// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1656// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1657// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001658func (agent *LogicalDeviceAgent) addNNILogicalPort(device *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001659 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
khenaidoo8f474192019-04-03 17:20:44 -04001660 if device.AdminState != voltha.AdminState_ENABLED || device.OperStatus != voltha.OperStatus_ACTIVE {
1661 log.Infow("device-not-ready", log.Fields{"deviceId": device.Id, "admin": device.AdminState, "oper": device.OperStatus})
1662 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001663 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001664 agent.lockLogicalDevice.RLock()
1665 if agent.portExist(device, port) {
1666 log.Debugw("port-already-exist", log.Fields{"port": port})
1667 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001668 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001669 }
1670 agent.lockLogicalDevice.RUnlock()
1671
khenaidoofc1314d2019-03-14 09:34:21 -04001672 var portCap *ic.PortCapability
1673 var err error
1674 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301675 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), device.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001676 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001677 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001678 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001679
1680 agent.lockLogicalDevice.Lock()
1681 defer agent.lockLogicalDevice.Unlock()
1682 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1683 if agent.portExist(device, port) {
1684 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001685 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001686 }
1687
khenaidoofc1314d2019-03-14 09:34:21 -04001688 portCap.Port.RootPort = true
1689 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1690 lp.DeviceId = device.Id
1691 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1692 lp.OfpPort.PortNo = port.PortNo
1693 lp.OfpPort.Name = lp.Id
1694 lp.DevicePortNo = port.PortNo
1695
khenaidoofc1314d2019-03-14 09:34:21 -04001696 var ld *voltha.LogicalDevice
1697 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1698 log.Errorw("error-retrieving-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001699 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001700 }
1701 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1702 if cloned.Ports == nil {
1703 cloned.Ports = make([]*voltha.LogicalPort, 0)
1704 }
1705 cloned.Ports = append(cloned.Ports, lp)
1706
1707 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1708 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001709 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001710 }
khenaidoo910204f2019-04-08 17:56:40 -04001711
1712 // Update the device graph with this new logical port
1713 clonedLP := (proto.Clone(lp)).(*voltha.LogicalPort)
1714 go agent.updateDeviceGraph(clonedLP)
1715
khenaidoo8f474192019-04-03 17:20:44 -04001716 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001717}
1718
khenaidoo910204f2019-04-08 17:56:40 -04001719func (agent *LogicalDeviceAgent) portExist(device *voltha.Device, port *voltha.Port) bool {
khenaidoo54544ae2019-03-18 13:22:39 -04001720 if ldevice, _ := agent.getLogicalDeviceWithoutLock(); ldevice != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001721 for _, lPort := range ldevice.Ports {
khenaidoo54544ae2019-03-18 13:22:39 -04001722 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
khenaidoofc1314d2019-03-14 09:34:21 -04001723 return true
1724 }
1725 }
1726 }
1727 return false
1728}
1729
khenaidoo8f474192019-04-03 17:20:44 -04001730// addUNILogicalPort adds an UNI port to the logical device. It returns a bool representing whether a port has been
1731// added and an eror in case a valid error is encountered. If the port was successfully added it will return
1732// (true, nil). If the device is not in the correct state it will return (false, nil) as this is a valid
1733// scenario. This also applies to the case where the port was already added.
khenaidoo910204f2019-04-08 17:56:40 -04001734func (agent *LogicalDeviceAgent) addUNILogicalPort(childDevice *voltha.Device, port *voltha.Port) (bool, error) {
khenaidoofc1314d2019-03-14 09:34:21 -04001735 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001736 if childDevice.AdminState != voltha.AdminState_ENABLED || childDevice.OperStatus != voltha.OperStatus_ACTIVE {
1737 log.Infow("device-not-ready", log.Fields{"deviceId": childDevice.Id, "admin": childDevice.AdminState, "oper": childDevice.OperStatus})
1738 return false, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001739 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001740 agent.lockLogicalDevice.RLock()
1741 if agent.portExist(childDevice, port) {
1742 log.Debugw("port-already-exist", log.Fields{"port": port})
1743 agent.lockLogicalDevice.RUnlock()
khenaidoo8f474192019-04-03 17:20:44 -04001744 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001745 }
1746 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001747 var portCap *ic.PortCapability
1748 var err error
1749 // First get the port capability
npujar1d86a522019-11-14 17:11:16 +05301750 if portCap, err = agent.deviceMgr.getPortCapability(context.TODO(), childDevice.Id, port.PortNo); err != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001751 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
khenaidoo8f474192019-04-03 17:20:44 -04001752 return false, err
khenaidoofc1314d2019-03-14 09:34:21 -04001753 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001754 agent.lockLogicalDevice.Lock()
1755 defer agent.lockLogicalDevice.Unlock()
1756 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1757 if agent.portExist(childDevice, port) {
1758 log.Debugw("port-already-exist", log.Fields{"port": port})
khenaidoo8f474192019-04-03 17:20:44 -04001759 return false, nil
khenaidoo1ce37ad2019-03-24 22:07:24 -04001760 }
khenaidoofc1314d2019-03-14 09:34:21 -04001761 // Get stored logical device
npujar1d86a522019-11-14 17:11:16 +05301762 ldevice, err := agent.getLogicalDeviceWithoutLock()
1763 if err != nil {
1764 return false, status.Error(codes.NotFound, agent.logicalDeviceID)
khenaidoofc1314d2019-03-14 09:34:21 -04001765 }
npujar1d86a522019-11-14 17:11:16 +05301766 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1767 portCap.Port.RootPort = false
1768 portCap.Port.Id = port.Label
1769 portCap.Port.OfpPort.PortNo = port.PortNo
1770 portCap.Port.DeviceId = childDevice.Id
1771 portCap.Port.DevicePortNo = port.PortNo
1772 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1773 if cloned.Ports == nil {
1774 cloned.Ports = make([]*voltha.LogicalPort, 0)
1775 }
1776 cloned.Ports = append(cloned.Ports, portCap.Port)
1777 if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1778 return false, err
1779 }
1780 // Update the device graph with this new logical port
1781 clonedLP := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1782 go agent.updateDeviceGraph(clonedLP)
1783 return true, nil
khenaidoofc1314d2019-03-14 09:34:21 -04001784}
1785
khenaidoo43c82122018-11-22 18:38:28 -05001786func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001787 log.Debugw("packet-out", log.Fields{
1788 "packet": hex.EncodeToString(packet.Data),
1789 "inPort": packet.GetInPort(),
1790 })
khenaidoo68c930b2019-05-13 11:46:51 -04001791 outPort := fu.GetPacketOutPort(packet)
khenaidoofdbad6e2018-11-06 22:26:38 -05001792 //frame := packet.GetData()
1793 //TODO: Use a channel between the logical agent and the device agent
npujar1d86a522019-11-14 17:11:16 +05301794 if err := agent.deviceMgr.packetOut(agent.rootDeviceID, outPort, packet); err != nil {
1795 log.Error("packetout-failed", log.Fields{"logicalDeviceID": agent.rootDeviceID})
khenaidooca301322019-01-09 23:06:32 -05001796 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001797}
1798
npujar1d86a522019-11-14 17:11:16 +05301799func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionID string, packet []byte) {
Matteo Scandolo360605d2019-11-05 18:29:17 -08001800 log.Debugw("packet-in", log.Fields{
1801 "port": port,
1802 "packet": hex.EncodeToString(packet),
npujar1d86a522019-11-14 17:11:16 +05301803 "transactionId": transactionID,
Matteo Scandolo360605d2019-11-05 18:29:17 -08001804 })
khenaidoo68c930b2019-05-13 11:46:51 -04001805 packetIn := fu.MkPacketIn(port, packet)
npujar1d86a522019-11-14 17:11:16 +05301806 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceID, transactionID, packetIn)
Matteo Scandolo360605d2019-11-05 18:29:17 -08001807 log.Debugw("sending-packet-in", log.Fields{"packet": hex.EncodeToString(packetIn.Data)})
khenaidoofdbad6e2018-11-06 22:26:38 -05001808}
khenaidoo2c6a0992019-04-29 13:46:56 -04001809
1810func (agent *LogicalDeviceAgent) addLogicalPortToMap(portNo uint32, nniPort bool) {
1811 agent.lockLogicalPortsNo.Lock()
1812 defer agent.lockLogicalPortsNo.Unlock()
1813 if exist := agent.logicalPortsNo[portNo]; !exist {
1814 agent.logicalPortsNo[portNo] = nniPort
1815 }
1816}
1817
khenaidoo3d3b8c22019-05-22 18:10:39 -04001818func (agent *LogicalDeviceAgent) addLogicalPortsToMap(lps []*voltha.LogicalPort) {
1819 agent.lockLogicalPortsNo.Lock()
1820 defer agent.lockLogicalPortsNo.Unlock()
1821 for _, lp := range lps {
1822 if exist := agent.logicalPortsNo[lp.DevicePortNo]; !exist {
1823 agent.logicalPortsNo[lp.DevicePortNo] = lp.RootPort
1824 }
1825 }
1826}
1827
khenaidoo2c6a0992019-04-29 13:46:56 -04001828func (agent *LogicalDeviceAgent) isNNIPort(portNo uint32) bool {
1829 agent.lockLogicalPortsNo.RLock()
1830 defer agent.lockLogicalPortsNo.RUnlock()
1831 if exist := agent.logicalPortsNo[portNo]; exist {
1832 return agent.logicalPortsNo[portNo]
1833 }
1834 return false
1835}
1836
1837func (agent *LogicalDeviceAgent) getFirstNNIPort() (uint32, error) {
1838 agent.lockLogicalPortsNo.RLock()
1839 defer agent.lockLogicalPortsNo.RUnlock()
1840 for portNo, nni := range agent.logicalPortsNo {
1841 if nni {
1842 return portNo, nil
1843 }
1844 }
1845 return 0, status.Error(codes.NotFound, "No NNI port found")
1846}