blob: ee3d82ad3c5a6feb4bcba209e24f27f9baa86aab [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 */
16package core
17
18import (
19 "context"
khenaidoo19d7b632018-10-30 10:49:50 -040020 "errors"
21 "fmt"
khenaidoob9203542018-09-17 22:56:37 -040022 "github.com/gogo/protobuf/proto"
23 "github.com/opencord/voltha-go/common/log"
24 "github.com/opencord/voltha-go/db/model"
khenaidoo79232702018-12-04 11:00:41 -050025 ic "github.com/opencord/voltha-go/protos/inter_container"
khenaidoo89b0e942018-10-21 21:11:33 -040026 ofp "github.com/opencord/voltha-go/protos/openflow_13"
khenaidoob9203542018-09-17 22:56:37 -040027 "github.com/opencord/voltha-go/protos/voltha"
khenaidoo89b0e942018-10-21 21:11:33 -040028 fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
29 "github.com/opencord/voltha-go/rw_core/graph"
30 fu "github.com/opencord/voltha-go/rw_core/utils"
khenaidoob9203542018-09-17 22:56:37 -040031 "google.golang.org/grpc/codes"
32 "google.golang.org/grpc/status"
khenaidoo19d7b632018-10-30 10:49:50 -040033 "reflect"
khenaidoo92e62c52018-10-03 14:02:54 -040034 "sync"
khenaidoob9203542018-09-17 22:56:37 -040035)
36
37type LogicalDeviceAgent struct {
khenaidoo92e62c52018-10-03 14:02:54 -040038 logicalDeviceId string
39 lastData *voltha.LogicalDevice
40 rootDeviceId string
41 deviceMgr *DeviceManager
42 ldeviceMgr *LogicalDeviceManager
43 clusterDataProxy *model.Proxy
44 exitChannel chan int
khenaidoo89b0e942018-10-21 21:11:33 -040045 deviceGraph *graph.DeviceGraph
46 DefaultFlowRules *fu.DeviceRules
khenaidoo19d7b632018-10-30 10:49:50 -040047 flowProxy *model.Proxy
48 groupProxy *model.Proxy
khenaidoo92e62c52018-10-03 14:02:54 -040049 lockLogicalDevice sync.RWMutex
khenaidoo19d7b632018-10-30 10:49:50 -040050 flowDecomposer *fd.FlowDecomposer
khenaidoob9203542018-09-17 22:56:37 -040051}
52
Stephane Barbarie1ab43272018-12-08 21:42:13 -050053func newLogicalDeviceAgent(id string, deviceId string, ldeviceMgr *LogicalDeviceManager,
54 deviceMgr *DeviceManager,
khenaidoo9a468962018-09-19 15:33:13 -040055 cdProxy *model.Proxy) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040056 var agent LogicalDeviceAgent
57 agent.exitChannel = make(chan int, 1)
58 agent.logicalDeviceId = id
Stephane Barbarie1ab43272018-12-08 21:42:13 -050059 agent.rootDeviceId = deviceId
khenaidoob9203542018-09-17 22:56:37 -040060 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040061 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040062 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040063 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040064 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoob9203542018-09-17 22:56:37 -040065 return &agent
66}
67
khenaidoo4d4802d2018-10-04 21:59:49 -040068// start creates the logical device and add it to the data model
69func (agent *LogicalDeviceAgent) start(ctx context.Context) error {
khenaidoo92e62c52018-10-03 14:02:54 -040070 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -040071 //Build the logical device based on information retrieved from the device adapter
khenaidoo79232702018-12-04 11:00:41 -050072 var switchCap *ic.SwitchCapability
khenaidoob9203542018-09-17 22:56:37 -040073 var err error
74 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
75 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
76 return err
77 }
khenaidooca301322019-01-09 23:06:32 -050078
khenaidoob9203542018-09-17 22:56:37 -040079 ld := &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
khenaidooca301322019-01-09 23:06:32 -050080
81 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
82 var datapathID uint64
83 if datapathID, err = CreateDataPathId(agent.logicalDeviceId); err != nil {
84 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
85 return err
86 }
87 ld.DatapathId = datapathID
khenaidoo89b0e942018-10-21 21:11:33 -040088 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
89 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
khenaidoo19d7b632018-10-30 10:49:50 -040090 ld.Flows = &ofp.Flows{Items: nil}
91 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
khenaidoob9203542018-09-17 22:56:37 -040092
93 //Add logical ports to the logical device based on the number of NNI ports discovered
94 //First get the default port capability - TODO: each NNI port may have different capabilities,
95 //hence. may need to extract the port by the NNI port id defined by the adapter during device
96 //creation
97 var nniPorts *voltha.Ports
khenaidoo92e62c52018-10-03 14:02:54 -040098 if nniPorts, err = agent.deviceMgr.getPorts(ctx, agent.rootDeviceId, voltha.Port_ETHERNET_NNI); err != nil {
khenaidoob9203542018-09-17 22:56:37 -040099 log.Errorw("error-creating-logical-port", log.Fields{"error": err})
100 }
khenaidoo79232702018-12-04 11:00:41 -0500101 var portCap *ic.PortCapability
khenaidoob9203542018-09-17 22:56:37 -0400102 for _, port := range nniPorts.Items {
khenaidoo19d7b632018-10-30 10:49:50 -0400103 log.Infow("!!!!!!!NNI PORTS", log.Fields{"NNI": port})
khenaidoob9203542018-09-17 22:56:37 -0400104 if portCap, err = agent.deviceMgr.getPortCapability(ctx, agent.rootDeviceId, port.PortNo); err != nil {
105 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
106 return err
107 }
khenaidoo19d7b632018-10-30 10:49:50 -0400108 portCap.Port.RootPort = true
khenaidoob9203542018-09-17 22:56:37 -0400109 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
khenaidoo92e62c52018-10-03 14:02:54 -0400110 lp.DeviceId = agent.rootDeviceId
khenaidoo19d7b632018-10-30 10:49:50 -0400111 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
112 lp.OfpPort.PortNo = port.PortNo
113 lp.OfpPort.Name = portCap.Port.Id
114 lp.DevicePortNo = port.PortNo
khenaidoob9203542018-09-17 22:56:37 -0400115 ld.Ports = append(ld.Ports, lp)
116 }
khenaidoo92e62c52018-10-03 14:02:54 -0400117 agent.lockLogicalDevice.Lock()
118 defer agent.lockLogicalDevice.Unlock()
khenaidoob9203542018-09-17 22:56:37 -0400119 // Save the logical device
khenaidoo43c82122018-11-22 18:38:28 -0500120 if added := agent.clusterDataProxy.AddWithID("/logical_devices", ld.Id, ld, ""); added == nil {
khenaidoob9203542018-09-17 22:56:37 -0400121 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
122 } else {
123 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
124 }
125
khenaidoo43c82122018-11-22 18:38:28 -0500126 agent.flowProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400127 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceId),
128 false)
khenaidoo43c82122018-11-22 18:38:28 -0500129 agent.groupProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400130 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceId),
131 false)
132
133 agent.flowProxy.RegisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
khenaidoo43c82122018-11-22 18:38:28 -0500134 agent.groupProxy.RegisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
khenaidoo19d7b632018-10-30 10:49:50 -0400135
khenaidoob9203542018-09-17 22:56:37 -0400136 return nil
137}
138
khenaidoo4d4802d2018-10-04 21:59:49 -0400139// stop stops the logical devuce agent. This removes the logical device from the data model.
140func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
141 log.Info("stopping-logical_device-agent")
142 agent.lockLogicalDevice.Lock()
143 defer agent.lockLogicalDevice.Unlock()
144 //Remove the logical device from the model
145 if removed := agent.clusterDataProxy.Remove("/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
146 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
147 } else {
148 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
149 }
150 agent.exitChannel <- 1
151 log.Info("logical_device-agent-stopped")
152}
153
khenaidoo19d7b632018-10-30 10:49:50 -0400154// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
155func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
156 log.Debug("GetLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400157 agent.lockLogicalDevice.Lock()
158 defer agent.lockLogicalDevice.Unlock()
159 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
160 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500161 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400162 }
163 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
164}
165
khenaidoo19d7b632018-10-30 10:49:50 -0400166func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
167 log.Debug("!!!!!ListLogicalDevicePorts")
168 agent.lockLogicalDevice.Lock()
169 defer agent.lockLogicalDevice.Unlock()
170 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
171 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
172 lPorts := make([]*voltha.LogicalPort, 0)
173 for _, port := range lDevice.Ports {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500174 lPorts = append(lPorts, port)
khenaidoo19d7b632018-10-30 10:49:50 -0400175 }
176 return &voltha.LogicalPorts{Items: lPorts}, nil
177 }
178 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
179}
180
181// listFlows locks the logical device model and then retrieves the latest flow information
182func (agent *LogicalDeviceAgent) listFlows() []*ofp.OfpFlowStats {
183 log.Debug("listFlows")
184 agent.lockLogicalDevice.Lock()
185 defer agent.lockLogicalDevice.Unlock()
186 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
187 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
188 return lDevice.Flows.Items
189 }
190 return nil
191}
192
193// listFlowGroups locks the logical device model and then retrieves the latest flow groups information
194func (agent *LogicalDeviceAgent) listFlowGroups() []*ofp.OfpGroupEntry {
195 log.Debug("listFlowGroups")
196 agent.lockLogicalDevice.Lock()
197 defer agent.lockLogicalDevice.Unlock()
198 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
199 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
200 return lDevice.FlowGroups.Items
201 }
202 return nil
203}
204
khenaidoo43c82122018-11-22 18:38:28 -0500205//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
206func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500207 afterUpdate := agent.flowProxy.Update("/", flows, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500208 if afterUpdate == nil {
209 return status.Errorf(codes.Internal, "failed-updating-logical-device-flows:%s", agent.logicalDeviceId)
210 }
khenaidoo43c82122018-11-22 18:38:28 -0500211 return nil
212}
213
214//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
215func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500216 afterUpdate := agent.groupProxy.Update("/", flowGroups, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500217 if afterUpdate == nil {
218 return status.Errorf(codes.Internal, "failed-updating-logical-device-flow-groups:%s", agent.logicalDeviceId)
219 }
khenaidoo43c82122018-11-22 18:38:28 -0500220 return nil
221}
222
khenaidoo4d4802d2018-10-04 21:59:49 -0400223// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
224// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400225func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
226 log.Debug("getLogicalDeviceWithoutLock")
227 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
228 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500229 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400230 }
231 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
232}
233
khenaidoo4d4802d2018-10-04 21:59:49 -0400234// addUNILogicalPort creates a UNI port on the logical device that represents a child device
khenaidoo19d7b632018-10-30 10:49:50 -0400235func (agent *LogicalDeviceAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400236 log.Infow("addUNILogicalPort-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400237 // Build the logical device based on information retrieved from the device adapter
khenaidoo79232702018-12-04 11:00:41 -0500238 var portCap *ic.PortCapability
khenaidoob9203542018-09-17 22:56:37 -0400239 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400240
241 //Get UNI port number
242 var uniPort uint32
243 for _, port := range childDevice.Ports {
244 if port.Type == voltha.Port_ETHERNET_UNI {
245 uniPort = port.PortNo
246 }
247 }
248 if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, uniPort); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400249 log.Errorw("error-creating-logical-port", log.Fields{"error": err})
250 return err
251 }
khenaidoo92e62c52018-10-03 14:02:54 -0400252 agent.lockLogicalDevice.Lock()
253 defer agent.lockLogicalDevice.Unlock()
khenaidoob9203542018-09-17 22:56:37 -0400254 // Get stored logical device
khenaidoo92e62c52018-10-03 14:02:54 -0400255 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400256 return status.Error(codes.NotFound, agent.logicalDeviceId)
257 } else {
khenaidoo19d7b632018-10-30 10:49:50 -0400258 log.Infow("!!!!!!!!!!!ADDING-UNI", log.Fields{"deviceId": childDevice.Id})
khenaidoo19d7b632018-10-30 10:49:50 -0400259 portCap.Port.RootPort = false
260 //TODO: For now use the channel id assigned by the OLT as logical port number
261 lPortNo := childDevice.ProxyAddress.ChannelId
262 portCap.Port.Id = fmt.Sprintf("uni-%d", lPortNo)
263 portCap.Port.OfpPort.PortNo = lPortNo
264 portCap.Port.OfpPort.Name = portCap.Port.Id
265 portCap.Port.DeviceId = childDevice.Id
266 portCap.Port.DevicePortNo = uniPort
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500267 portCap.Port.DeviceId = childDevice.Id
268 ldevice.Ports = append(ldevice.Ports, portCap.Port)
269 return agent.updateLogicalDeviceWithoutLock(ldevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400270 }
271}
272
273//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
274func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500275 afterUpdate := agent.clusterDataProxy.Update("/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400276 if afterUpdate == nil {
277 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
278 }
279 return nil
280}
281
khenaidoo19d7b632018-10-30 10:49:50 -0400282//updateFlowTable updates the flow table of that logical device
283func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
284 log.Debug("updateFlowTable")
285 if flow == nil {
286 return nil
287 }
288 switch flow.GetCommand() {
289 case ofp.OfpFlowModCommand_OFPFC_ADD:
290 return agent.flowAdd(flow)
291 case ofp.OfpFlowModCommand_OFPFC_DELETE:
292 return agent.flowDelete(flow)
293 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
294 return agent.flowDeleteStrict(flow)
295 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
296 return agent.flowModify(flow)
297 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
298 return agent.flowModifyStrict(flow)
299 }
300 return status.Errorf(codes.Internal,
301 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
302}
303
304//updateGroupTable updates the group table of that logical device
305func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
306 log.Debug("updateGroupTable")
307 if groupMod == nil {
308 return nil
309 }
310 switch groupMod.GetCommand() {
311 case ofp.OfpGroupModCommand_OFPGC_ADD:
312 return agent.groupAdd(groupMod)
313 case ofp.OfpGroupModCommand_OFPGC_DELETE:
314 return agent.groupDelete(groupMod)
315 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
316 return agent.groupModify(groupMod)
317 }
318 return status.Errorf(codes.Internal,
319 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
320}
321
khenaidoo19d7b632018-10-30 10:49:50 -0400322//updateFlowGroupsWithoutLock updates the flows in the logical device without locking the logical device. This function
323//must only be called by a function that is holding the lock on the logical device
324func (agent *LogicalDeviceAgent) updateFlowGroupsWithoutLock(groups []*ofp.OfpGroupEntry) error {
khenaidoo43c82122018-11-22 18:38:28 -0500325 groupsCloned := make([]*ofp.OfpGroupEntry, len(groups))
326 copy(groupsCloned, groups)
327 if afterUpdate := agent.groupProxy.Update("/", groupsCloned, true, ""); afterUpdate == nil {
328 return errors.New(fmt.Sprintf("update-flow-group-failed:%s", agent.logicalDeviceId))
khenaidoo19d7b632018-10-30 10:49:50 -0400329 }
khenaidoo43c82122018-11-22 18:38:28 -0500330 return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400331}
332
333//flowAdd adds a flow to the flow table of that logical device
334func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
335 log.Debug("flowAdd")
336 if mod == nil {
337 return nil
338 }
khenaidoo92e62c52018-10-03 14:02:54 -0400339 agent.lockLogicalDevice.Lock()
340 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400341
342 var lDevice *voltha.LogicalDevice
343 var err error
344 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
345 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
346 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
347 }
348
349 var flows []*ofp.OfpFlowStats
350 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
351 flows = lDevice.Flows.Items
352 }
353
khenaidoo43c82122018-11-22 18:38:28 -0500354 //oldData := proto.Clone(lDevice.Flows).(*voltha.Flows)
khenaidoo19d7b632018-10-30 10:49:50 -0400355 changed := false
356 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
357 if checkOverlap {
358 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
359 // TODO: should this error be notified other than being logged?
360 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
361 } else {
362 // Add flow
363 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
364 flows = append(flows, flow)
365 changed = true
366 }
367 } else {
368 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
369 idx := fu.FindFlows(flows, flow)
370 if idx >= 0 {
371 oldFlow := flows[idx]
372 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
373 flow.ByteCount = oldFlow.ByteCount
374 flow.PacketCount = oldFlow.PacketCount
375 }
376 flows[idx] = flow
377 } else {
378 flows = append(flows, flow)
379 }
380 changed = true
381 }
382 if changed {
383 // Update model
khenaidoo43c82122018-11-22 18:38:28 -0500384 flowsToUpdate := &ofp.Flows{}
385 if lDevice.Flows != nil {
386 flowsToUpdate = &ofp.Flows{Items: flows}
khenaidoo19d7b632018-10-30 10:49:50 -0400387 }
khenaidoo43c82122018-11-22 18:38:28 -0500388 if err := agent.updateLogicalDeviceFlowsWithoutLock(flowsToUpdate); err != nil {
389 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400390 return err
391 }
392 }
khenaidoo19d7b632018-10-30 10:49:50 -0400393 return nil
394}
395
396//flowDelete deletes a flow from the flow table of that logical device
397func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
398 log.Debug("flowDelete")
399 if mod == nil {
400 return nil
401 }
402 agent.lockLogicalDevice.Lock()
403 defer agent.lockLogicalDevice.Unlock()
404
405 var lDevice *voltha.LogicalDevice
406 var err error
407 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
408 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
409 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
410 }
411 flows := lDevice.Flows.Items
412
413 //build a list of what to keep vs what to delete
414 toKeep := make([]*ofp.OfpFlowStats, 0)
415 for _, f := range flows {
416 if !fu.FlowMatchesMod(f, mod) {
417 toKeep = append(toKeep, f)
418 }
419 }
420
421 //Update flows
422 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500423 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
424 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400425 return err
426 }
427 }
428
429 //TODO: send announcement on delete
430 return nil
431}
432
433//flowStatsDelete deletes a flow from the flow table of that logical device
434func (agent *LogicalDeviceAgent) flowStatsDelete(flow *ofp.OfpFlowStats) error {
435 log.Debug("flowStatsDelete")
436 if flow == nil {
437 return nil
438 }
439 agent.lockLogicalDevice.Lock()
440 defer agent.lockLogicalDevice.Unlock()
441
442 var lDevice *voltha.LogicalDevice
443 var err error
444 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
445 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
446 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
447 }
448 flows := lDevice.Flows.Items
449
450 //build a list of what to keep vs what to delete
451 toKeep := make([]*ofp.OfpFlowStats, 0)
452 for _, f := range flows {
453 if !fu.FlowMatch(f, flow) {
454 toKeep = append(toKeep, f)
455 }
456 }
457
458 //Update flows
459 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500460 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400461 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
462 return err
463 }
464 }
465 return nil
466}
467
468//flowDeleteStrict deletes a flow from the flow table of that logical device
469func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
470 log.Debug("flowDeleteStrict")
471 if mod == nil {
472 return nil
473 }
474 agent.lockLogicalDevice.Lock()
475 defer agent.lockLogicalDevice.Unlock()
476
477 var lDevice *voltha.LogicalDevice
478 var err error
479 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
480 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
481 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
482 }
483 flows := lDevice.Flows.Items
484 changed := false
485 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
486 idx := fu.FindFlows(flows, flow)
487 if idx >= 0 {
488 flows = append(flows[:idx], flows[idx+1:]...)
489 changed = true
490 } else {
491 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
492 }
493
494 if changed {
khenaidoo43c82122018-11-22 18:38:28 -0500495 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400496 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
497 return err
498 }
499 }
500
501 return nil
502}
503
504//flowModify modifies a flow from the flow table of that logical device
505func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
506 return errors.New("flowModify not implemented")
507}
508
509//flowModifyStrict deletes a flow from the flow table of that logical device
510func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
511 return errors.New("flowModifyStrict not implemented")
512}
513
514func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
515 log.Debug("groupAdd")
516 if groupMod == nil {
517 return nil
518 }
519 agent.lockLogicalDevice.Lock()
520 defer agent.lockLogicalDevice.Unlock()
521
522 var lDevice *voltha.LogicalDevice
523 var err error
524 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
525 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
526 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
527 }
528 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -0400529 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
530 groups = append(groups, fd.GroupEntryFromGroupMod(groupMod))
khenaidoo43c82122018-11-22 18:38:28 -0500531 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
532 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400533 return err
534 }
535 } else {
536 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
537 }
khenaidoo19d7b632018-10-30 10:49:50 -0400538 return nil
539}
540
541func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
542 log.Debug("groupDelete")
543 if groupMod == nil {
544 return nil
545 }
546 agent.lockLogicalDevice.Lock()
547 defer agent.lockLogicalDevice.Unlock()
548
549 var lDevice *voltha.LogicalDevice
550 var err error
551 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
552 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
553 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
554 }
555 groups := lDevice.FlowGroups.Items
556 flows := lDevice.Flows.Items
557 groupsChanged := false
558 flowsChanged := false
559 groupId := groupMod.GroupId
560 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
561 //TODO we must delete all flows that point to this group and
562 //signal controller as requested by flow's flag
563 groups = []*ofp.OfpGroupEntry{}
564 groupsChanged = true
565 } else {
566 if idx := fu.FindGroup(groups, groupId); idx == -1 {
567 return nil // Valid case
568 } else {
569 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
570 groups = append(groups[:idx], groups[idx+1:]...)
571 groupsChanged = true
572 }
573 }
khenaidoo43c82122018-11-22 18:38:28 -0500574 if groupsChanged {
575 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
576 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400577 return err
578 }
579 }
khenaidoo43c82122018-11-22 18:38:28 -0500580 if flowsChanged {
581 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
582 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
583 return err
584 }
585 }
586
khenaidoo19d7b632018-10-30 10:49:50 -0400587 return nil
588}
589
590func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
591 log.Debug("groupModify")
592 if groupMod == nil {
593 return nil
594 }
595 agent.lockLogicalDevice.Lock()
596 defer agent.lockLogicalDevice.Unlock()
597
598 var lDevice *voltha.LogicalDevice
599 var err error
600 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
601 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
602 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
603 }
604 groups := lDevice.FlowGroups.Items
605 groupsChanged := false
606 groupId := groupMod.GroupId
607 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -0500608 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -0400609 } else {
610 //replace existing group entry with new group definition
611 groupEntry := fd.GroupEntryFromGroupMod(groupMod)
612 groups[idx] = groupEntry
613 groupsChanged = true
614 }
615 if groupsChanged {
khenaidoo43c82122018-11-22 18:38:28 -0500616 //lDevice.FlowGroups.Items = groups
617 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400618 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
619 return err
620 }
621 }
622 return nil
623}
624
625// deleteLogicalPort removes the logical port
626func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
627 agent.lockLogicalDevice.Lock()
628 defer agent.lockLogicalDevice.Unlock()
629
khenaidoo92e62c52018-10-03 14:02:54 -0400630 // Get the most up to date logical device
631 var logicaldevice *voltha.LogicalDevice
632 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400633 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -0400634 return nil
635 }
khenaidoo92e62c52018-10-03 14:02:54 -0400636 index := -1
637 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -0400638 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -0400639 index = i
640 break
641 }
642 }
643 if index >= 0 {
644 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
645 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
646 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
647 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
648 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
649 }
650 return nil
khenaidoob9203542018-09-17 22:56:37 -0400651}
652
khenaidoo19d7b632018-10-30 10:49:50 -0400653// enableLogicalPort enables the logical port
654func (agent *LogicalDeviceAgent) enableLogicalPort(lPort *voltha.LogicalPort) error {
655 agent.lockLogicalDevice.Lock()
656 defer agent.lockLogicalDevice.Unlock()
657
658 // Get the most up to date logical device
659 var logicaldevice *voltha.LogicalDevice
660 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
661 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
662 return nil
663 }
664 index := -1
665 for i, logicalPort := range logicaldevice.Ports {
666 if logicalPort.Id == lPort.Id {
667 index = i
668 break
669 }
670 }
671 if index >= 0 {
672 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
673 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
674 }
675 //TODO: Trigger subsequent actions on the device
676 return nil
677}
678
679// disableLogicalPort disabled the logical port
680func (agent *LogicalDeviceAgent) disableLogicalPort(lPort *voltha.LogicalPort) error {
681 agent.lockLogicalDevice.Lock()
682 defer agent.lockLogicalDevice.Unlock()
683
684 // Get the most up to date logical device
685 var logicaldevice *voltha.LogicalDevice
686 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
687 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
688 return nil
689 }
690 index := -1
691 for i, logicalPort := range logicaldevice.Ports {
692 if logicalPort.Id == lPort.Id {
693 index = i
694 break
695 }
696 }
697 if index >= 0 {
698 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
699 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
700 }
701 //TODO: Trigger subsequent actions on the device
702 return nil
703}
704
khenaidoo89b0e942018-10-21 21:11:33 -0400705func isNNIPort(portNo uint32, nniPortsNo []uint32) bool {
706 for _, pNo := range nniPortsNo {
707 if pNo == portNo {
708 return true
709 }
710 }
711 return false
712}
khenaidoo4d4802d2018-10-04 21:59:49 -0400713
khenaidoo89b0e942018-10-21 21:11:33 -0400714func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -0400715 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -0400716 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400717 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -0400718 if ingress == routeLink.Ingress && egress == routeLink.Egress {
719 return route
720 }
721 }
722 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
723 return nil
724}
725
khenaidoo19d7b632018-10-30 10:49:50 -0400726func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400727 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
728 // Get the updated logical device
khenaidoo79232702018-12-04 11:00:41 -0500729 var ld *ic.LogicalDevice
khenaidoo89b0e942018-10-21 21:11:33 -0400730 routes := make([]graph.RouteHop, 0)
731 var err error
732 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
733 return nil
734 }
735 nniLogicalPortsNo := make([]uint32, 0)
736 for _, logicalPort := range ld.Ports {
737 if logicalPort.RootPort {
738 nniLogicalPortsNo = append(nniLogicalPortsNo, logicalPort.OfpPort.PortNo)
739 }
740 }
741 if len(nniLogicalPortsNo) == 0 {
742 log.Errorw("no-nni-ports", log.Fields{"LogicalDeviceId": ld.Id})
743 return nil
744 }
khenaidoo19d7b632018-10-30 10:49:50 -0400745 // Note: A port value of 0 is equivalent to a nil port
746
khenaidoo89b0e942018-10-21 21:11:33 -0400747 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -0400748 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo89b0e942018-10-21 21:11:33 -0400749 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
khenaidoo19d7b632018-10-30 10:49:50 -0400750 if isNNIPort(ingressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400751 log.Debug("returning-half-route")
752 //This is a trap on the NNI Port
753 //Return a 'half' route to make the flow decomposer logic happy
754 for routeLink, route := range agent.deviceGraph.Routes {
755 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
756 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
757 routes = append(routes, route[1])
758 return routes
759 }
760 }
761 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
762 return nil
763 }
764 //treat it as if the output port is the first NNI of the OLT
khenaidoo19d7b632018-10-30 10:49:50 -0400765 egressPortNo = nniLogicalPortsNo[0]
khenaidoo89b0e942018-10-21 21:11:33 -0400766 }
767 //If ingress port is not specified (nil), it may be a wildcarded
768 //route if egress port is OFPP_CONTROLLER or a nni logical port,
769 //in which case we need to create a half-route where only the egress
770 //hop is filled, the first hop is nil
khenaidoo19d7b632018-10-30 10:49:50 -0400771 if ingressPortNo == 0 && isNNIPort(egressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400772 // We can use the 2nd hop of any upstream route, so just find the first upstream:
773 for routeLink, route := range agent.deviceGraph.Routes {
774 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
775 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
776 routes = append(routes, route[1])
777 return routes
778 }
779 }
780 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
781 return nil
782 }
783 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -0400784 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400785 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400786 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -0400787 routes = append(routes, route[0])
788 routes = append(routes, graph.RouteHop{})
789 return routes
790 }
791 }
792 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
793 return nil
794 }
795
796 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -0400797 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400798}
799
800// updateRoutes updates the device routes whenever there is a device or port changes relevant to this
801// logical device. TODO: Add more heuristics to this process to update the routes where a change has occurred
802// instead of rebuilding the entire set of routes
803func (agent *LogicalDeviceAgent) updateRoutes() {
khenaidoo19d7b632018-10-30 10:49:50 -0400804 if ld, err := agent.GetLogicalDevice(); err == nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400805 agent.deviceGraph.ComputeRoutes(ld.Ports)
806 }
807}
808
809func (agent *LogicalDeviceAgent) rootDeviceDefaultRules() *fu.FlowsAndGroups {
810 return fu.NewFlowsAndGroups()
811}
812
813func (agent *LogicalDeviceAgent) leafDeviceDefaultRules(deviceId string) *fu.FlowsAndGroups {
814 fg := fu.NewFlowsAndGroups()
815 var device *voltha.Device
816 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400817 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400818 return fg
819 }
820 //set the upstream and downstream ports
821 upstreamPorts := make([]*voltha.Port, 0)
822 downstreamPorts := make([]*voltha.Port, 0)
823 for _, port := range device.Ports {
824 if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_VENET_ONU {
825 upstreamPorts = append(upstreamPorts, port)
826 } else if port.Type == voltha.Port_ETHERNET_UNI {
827 downstreamPorts = append(downstreamPorts, port)
828 }
829 }
830 //it is possible that the downstream ports are not created, but the flow_decomposition has already
831 //kicked in. In such scenarios, cut short the processing and return.
832 if len(downstreamPorts) == 0 {
833 return fg
834 }
835 // set up the default flows
836 var fa *fu.FlowArgs
837 fa = &fu.FlowArgs{
838 KV: fu.OfpFlowModArgs{"priority": 500},
839 MatchFields: []*ofp.OfpOxmOfbField{
840 fd.InPort(downstreamPorts[0].PortNo),
841 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
842 },
843 Actions: []*ofp.OfpAction{
844 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
khenaidoo19d7b632018-10-30 10:49:50 -0400845 fd.Output(upstreamPorts[0].PortNo),
khenaidoo89b0e942018-10-21 21:11:33 -0400846 },
847 }
848 fg.AddFlow(fd.MkFlowStat(fa))
849
850 fa = &fu.FlowArgs{
851 KV: fu.OfpFlowModArgs{"priority": 500},
852 MatchFields: []*ofp.OfpOxmOfbField{
853 fd.InPort(downstreamPorts[0].PortNo),
854 fd.VlanVid(0),
855 },
856 Actions: []*ofp.OfpAction{
857 fd.PushVlan(0x8100),
858 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
859 fd.Output(upstreamPorts[0].PortNo),
860 },
861 }
862 fg.AddFlow(fd.MkFlowStat(fa))
863
864 fa = &fu.FlowArgs{
865 KV: fu.OfpFlowModArgs{"priority": 500},
866 MatchFields: []*ofp.OfpOxmOfbField{
867 fd.InPort(upstreamPorts[0].PortNo),
868 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan),
869 },
870 Actions: []*ofp.OfpAction{
871 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
872 fd.Output(downstreamPorts[0].PortNo),
873 },
874 }
875 fg.AddFlow(fd.MkFlowStat(fa))
876
877 return fg
878}
879
880func (agent *LogicalDeviceAgent) generateDefaultRules() *fu.DeviceRules {
881 rules := fu.NewDeviceRules()
882 var ld *voltha.LogicalDevice
883 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400884 if ld, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400885 log.Warnw("no-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
886 return rules
887 }
888
889 deviceNodeIds := agent.deviceGraph.GetDeviceNodeIds()
khenaidooca301322019-01-09 23:06:32 -0500890 for deviceId := range deviceNodeIds {
khenaidoo89b0e942018-10-21 21:11:33 -0400891 if deviceId == ld.RootDeviceId {
892 rules.AddFlowsAndGroup(deviceId, agent.rootDeviceDefaultRules())
893 } else {
894 rules.AddFlowsAndGroup(deviceId, agent.leafDeviceDefaultRules(deviceId))
895 }
896 }
897 return rules
898}
899
900func (agent *LogicalDeviceAgent) GetAllDefaultRules() *fu.DeviceRules {
901 // Get latest
902 var lDevice *voltha.LogicalDevice
903 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400904 if lDevice, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400905 return fu.NewDeviceRules()
906 }
907 if agent.DefaultFlowRules == nil { // Nothing setup yet
khenaidoo19d7b632018-10-30 10:49:50 -0400908 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
khenaidoo89b0e942018-10-21 21:11:33 -0400909 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
910 agent.DefaultFlowRules = agent.generateDefaultRules()
911 }
912 return agent.DefaultFlowRules
913}
914
915func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
916 lPorts := make([]uint32, 0)
917 var exclPort uint32
918 if len(excludePort) == 1 {
919 exclPort = excludePort[0]
920 }
khenaidoo19d7b632018-10-30 10:49:50 -0400921 if lDevice, _ := agent.GetLogicalDevice(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400922 for _, port := range lDevice.Ports {
923 if port.OfpPort.PortNo != exclPort {
924 lPorts = append(lPorts, port.OfpPort.PortNo)
925 }
926 }
927 }
928 return lPorts
929}
khenaidoo19d7b632018-10-30 10:49:50 -0400930
931func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
932 return agent.deviceGraph
933}
934
935//setupDeviceGraph creates the device graph if not done already
936func (agent *LogicalDeviceAgent) setupDeviceGraph() {
937 if agent.deviceGraph == nil {
938 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
939 agent.updateRoutes()
940 }
941}
942
943func (agent *LogicalDeviceAgent) flowTableUpdated(args ...interface{}) interface{} {
944 log.Debugw("flowTableUpdated-callback", log.Fields{"argsLen": len(args)})
945
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500946 var previousData *ofp.Flows
947 var latestData *ofp.Flows
khenaidoo19d7b632018-10-30 10:49:50 -0400948
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500949 var ok bool
950 if previousData, ok = args[0].(*ofp.Flows); !ok {
951 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
952 }
953 if latestData, ok = args[1].(*ofp.Flows); !ok {
954 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
955 }
khenaidoo19d7b632018-10-30 10:49:50 -0400956
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500957 if reflect.DeepEqual(previousData.Items, latestData.Items) {
958 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -0400959 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500960 }
961
962 // Ensure the device graph has been setup
963 agent.setupDeviceGraph()
964
965 var groups *ofp.FlowGroups
966 lDevice, _ := agent.getLogicalDeviceWithoutLock()
967 groups = lDevice.FlowGroups
968 log.Debugw("flowsinfo", log.Fields{"flows": latestData, "groups": groups})
969 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *latestData, *groups)
970 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
971
khenaidooca301322019-01-09 23:06:32 -0500972 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500973 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -0500974 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
975 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
976 }
977 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
978 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
979 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500980 }
khenaidoo19d7b632018-10-30 10:49:50 -0400981
khenaidoo19d7b632018-10-30 10:49:50 -0400982 return nil
983}
984
985func (agent *LogicalDeviceAgent) groupTableUpdated(args ...interface{}) interface{} {
986 log.Debugw("groupTableUpdated-callback", log.Fields{"argsLen": len(args)})
987
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500988 var previousData *ofp.FlowGroups
989 var latestData *ofp.FlowGroups
khenaidoo19d7b632018-10-30 10:49:50 -0400990
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500991 var ok bool
992 if previousData, ok = args[0].(*ofp.FlowGroups); !ok {
993 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
994 }
995 if latestData, ok = args[1].(*ofp.FlowGroups); !ok {
996 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
997 }
khenaidoo19d7b632018-10-30 10:49:50 -0400998
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500999 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1000 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001001 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001002 }
1003
1004 // Ensure the device graph has been setup
1005 agent.setupDeviceGraph()
1006
1007 var flows *ofp.Flows
1008 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1009 flows = lDevice.Flows
1010 log.Debugw("groupsinfo", log.Fields{"groups": latestData, "flows": flows})
1011 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *flows, *latestData)
1012 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidooca301322019-01-09 23:06:32 -05001013 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001014 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001015 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1016 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1017 }
1018 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1019 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1020 }
khenaidoo19d7b632018-10-30 10:49:50 -04001021
khenaidooca301322019-01-09 23:06:32 -05001022 }
khenaidoo19d7b632018-10-30 10:49:50 -04001023 return nil
1024}
khenaidoofdbad6e2018-11-06 22:26:38 -05001025
khenaidoo43c82122018-11-22 18:38:28 -05001026func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
khenaidoofdbad6e2018-11-06 22:26:38 -05001027 log.Debugw("packet-out", log.Fields{"packet": packet.GetInPort()})
1028 outPort := fd.GetPacketOutPort(packet)
1029 //frame := packet.GetData()
1030 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001031 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
1032 log.Error("packetout-failed", log.Fields{"logicalDeviceID":agent.rootDeviceId})
1033 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001034}
1035
khenaidoofdbad6e2018-11-06 22:26:38 -05001036func (agent *LogicalDeviceAgent) packetIn(port uint32, packet []byte) {
1037 log.Debugw("packet-in", log.Fields{"port": port, "packet": packet})
khenaidooca301322019-01-09 23:06:32 -05001038 packetIn := fd.MkPacketIn(port, packet)
1039 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, packetIn)
1040 log.Debugw("sending-packet-in", log.Fields{"packet-in": packetIn})
khenaidoofdbad6e2018-11-06 22:26:38 -05001041}