blob: 9d05757c900560418c5b8651b69d42b25df6514c [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
khenaidoo297cd252019-02-07 22:10:23 -050069func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
70 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId, "loadFromdB": loadFromdB})
71 var ld *voltha.LogicalDevice
72 if !loadFromdB {
73 //Build the logical device based on information retrieved from the device adapter
74 var switchCap *ic.SwitchCapability
75 var err error
76 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
khenaidoob9203542018-09-17 22:56:37 -040077 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
78 return err
79 }
khenaidoo297cd252019-02-07 22:10:23 -050080
81 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
82
83 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
84 var datapathID uint64
85 if datapathID, err = CreateDataPathId(agent.logicalDeviceId); err != nil {
86 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
87 return err
88 }
khenaidoo6d055132019-02-12 16:51:19 -050089
khenaidoo297cd252019-02-07 22:10:23 -050090 ld.DatapathId = datapathID
91 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
khenaidoo6d055132019-02-12 16:51:19 -050092 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo297cd252019-02-07 22:10:23 -050093 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
94 ld.Flows = &ofp.Flows{Items: nil}
95 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
96
97 //Add logical ports to the logical device based on the number of NNI ports discovered
98 //First get the default port capability - TODO: each NNI port may have different capabilities,
99 //hence. may need to extract the port by the NNI port id defined by the adapter during device
100 //creation
101 var nniPorts *voltha.Ports
102 if nniPorts, err = agent.deviceMgr.getPorts(ctx, agent.rootDeviceId, voltha.Port_ETHERNET_NNI); err != nil {
103 log.Errorw("error-creating-logical-port", log.Fields{"error": err})
104 }
105 var portCap *ic.PortCapability
106 for _, port := range nniPorts.Items {
107 log.Infow("!!!!!!!NNI PORTS", log.Fields{"NNI": port})
108 if portCap, err = agent.deviceMgr.getPortCapability(ctx, agent.rootDeviceId, port.PortNo); err != nil {
109 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
110 return err
111 }
112 portCap.Port.RootPort = true
113 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
114 lp.DeviceId = agent.rootDeviceId
115 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
116 lp.OfpPort.PortNo = port.PortNo
117 lp.OfpPort.Name = lp.Id
118 lp.DevicePortNo = port.PortNo
119 ld.Ports = append(ld.Ports, lp)
120 }
121 agent.lockLogicalDevice.Lock()
122 //defer agent.lockLogicalDevice.Unlock()
123 // Save the logical device
124 if added := agent.clusterDataProxy.AddWithID("/logical_devices", ld.Id, ld, ""); added == nil {
125 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
126 } else {
127 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
128 }
129 agent.lockLogicalDevice.Unlock()
130 } 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 {
135 log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
136 return err
137 }
khenaidoob9203542018-09-17 22:56:37 -0400138 }
khenaidoo92e62c52018-10-03 14:02:54 -0400139 agent.lockLogicalDevice.Lock()
khenaidoo43c82122018-11-22 18:38:28 -0500140 agent.flowProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400141 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceId),
142 false)
khenaidoo43c82122018-11-22 18:38:28 -0500143 agent.groupProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400144 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceId),
145 false)
146
147 agent.flowProxy.RegisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
khenaidoo43c82122018-11-22 18:38:28 -0500148 agent.groupProxy.RegisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
khenaidoo19d7b632018-10-30 10:49:50 -0400149
khenaidoobcf205b2019-01-25 22:21:14 -0500150 agent.lockLogicalDevice.Unlock()
151
152 // Setup the device graph
153 go agent.setupDeviceGraph()
154
khenaidoob9203542018-09-17 22:56:37 -0400155 return nil
156}
157
khenaidoo4d4802d2018-10-04 21:59:49 -0400158// stop stops the logical devuce agent. This removes the logical device from the data model.
159func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
160 log.Info("stopping-logical_device-agent")
161 agent.lockLogicalDevice.Lock()
162 defer agent.lockLogicalDevice.Unlock()
163 //Remove the logical device from the model
164 if removed := agent.clusterDataProxy.Remove("/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
165 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
166 } else {
167 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
168 }
169 agent.exitChannel <- 1
170 log.Info("logical_device-agent-stopped")
171}
172
khenaidoo19d7b632018-10-30 10:49:50 -0400173// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
174func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
175 log.Debug("GetLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400176 agent.lockLogicalDevice.Lock()
177 defer agent.lockLogicalDevice.Unlock()
178 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
179 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500180 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400181 }
182 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
183}
184
khenaidoo19d7b632018-10-30 10:49:50 -0400185func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
186 log.Debug("!!!!!ListLogicalDevicePorts")
187 agent.lockLogicalDevice.Lock()
188 defer agent.lockLogicalDevice.Unlock()
189 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
190 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
191 lPorts := make([]*voltha.LogicalPort, 0)
192 for _, port := range lDevice.Ports {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500193 lPorts = append(lPorts, port)
khenaidoo19d7b632018-10-30 10:49:50 -0400194 }
195 return &voltha.LogicalPorts{Items: lPorts}, nil
196 }
197 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
198}
199
200// listFlows locks the logical device model and then retrieves the latest flow information
201func (agent *LogicalDeviceAgent) listFlows() []*ofp.OfpFlowStats {
202 log.Debug("listFlows")
203 agent.lockLogicalDevice.Lock()
204 defer agent.lockLogicalDevice.Unlock()
205 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
206 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
207 return lDevice.Flows.Items
208 }
209 return nil
210}
211
212// listFlowGroups locks the logical device model and then retrieves the latest flow groups information
213func (agent *LogicalDeviceAgent) listFlowGroups() []*ofp.OfpGroupEntry {
214 log.Debug("listFlowGroups")
215 agent.lockLogicalDevice.Lock()
216 defer agent.lockLogicalDevice.Unlock()
217 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
218 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
219 return lDevice.FlowGroups.Items
220 }
221 return nil
222}
223
khenaidoo43c82122018-11-22 18:38:28 -0500224//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
225func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500226 afterUpdate := agent.flowProxy.Update("/", flows, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500227 if afterUpdate == nil {
228 return status.Errorf(codes.Internal, "failed-updating-logical-device-flows:%s", agent.logicalDeviceId)
229 }
khenaidoo43c82122018-11-22 18:38:28 -0500230 return nil
231}
232
233//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
234func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500235 afterUpdate := agent.groupProxy.Update("/", flowGroups, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500236 if afterUpdate == nil {
237 return status.Errorf(codes.Internal, "failed-updating-logical-device-flow-groups:%s", agent.logicalDeviceId)
238 }
khenaidoo43c82122018-11-22 18:38:28 -0500239 return nil
240}
241
khenaidoo4d4802d2018-10-04 21:59:49 -0400242// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
243// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400244func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
245 log.Debug("getLogicalDeviceWithoutLock")
246 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 1, false, "")
247 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500248 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400249 }
250 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
251}
252
khenaidoo4d4802d2018-10-04 21:59:49 -0400253// addUNILogicalPort creates a UNI port on the logical device that represents a child device
khenaidoo19d7b632018-10-30 10:49:50 -0400254func (agent *LogicalDeviceAgent) addUNILogicalPort(ctx context.Context, childDevice *voltha.Device) error {
khenaidoo92e62c52018-10-03 14:02:54 -0400255 log.Infow("addUNILogicalPort-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400256 // Build the logical device based on information retrieved from the device adapter
khenaidoo79232702018-12-04 11:00:41 -0500257 var portCap *ic.PortCapability
khenaidoob9203542018-09-17 22:56:37 -0400258 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400259
260 //Get UNI port number
261 var uniPort uint32
262 for _, port := range childDevice.Ports {
263 if port.Type == voltha.Port_ETHERNET_UNI {
264 uniPort = port.PortNo
265 }
266 }
267 if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, uniPort); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400268 log.Errorw("error-creating-logical-port", log.Fields{"error": err})
269 return err
270 }
khenaidoo92e62c52018-10-03 14:02:54 -0400271 agent.lockLogicalDevice.Lock()
272 defer agent.lockLogicalDevice.Unlock()
khenaidoob9203542018-09-17 22:56:37 -0400273 // Get stored logical device
khenaidoo92e62c52018-10-03 14:02:54 -0400274 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
khenaidoob9203542018-09-17 22:56:37 -0400275 return status.Error(codes.NotFound, agent.logicalDeviceId)
276 } else {
khenaidoobcf205b2019-01-25 22:21:14 -0500277 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
khenaidoo19d7b632018-10-30 10:49:50 -0400278 portCap.Port.RootPort = false
279 //TODO: For now use the channel id assigned by the OLT as logical port number
280 lPortNo := childDevice.ProxyAddress.ChannelId
281 portCap.Port.Id = fmt.Sprintf("uni-%d", lPortNo)
282 portCap.Port.OfpPort.PortNo = lPortNo
283 portCap.Port.OfpPort.Name = portCap.Port.Id
284 portCap.Port.DeviceId = childDevice.Id
285 portCap.Port.DevicePortNo = uniPort
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500286 portCap.Port.DeviceId = childDevice.Id
khenaidoobcf205b2019-01-25 22:21:14 -0500287
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500288 ldevice.Ports = append(ldevice.Ports, portCap.Port)
289 return agent.updateLogicalDeviceWithoutLock(ldevice)
khenaidoo92e62c52018-10-03 14:02:54 -0400290 }
291}
292
293//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
294func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500295 afterUpdate := agent.clusterDataProxy.Update("/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400296 if afterUpdate == nil {
297 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
298 }
299 return nil
300}
301
khenaidoo19d7b632018-10-30 10:49:50 -0400302//updateFlowTable updates the flow table of that logical device
303func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
304 log.Debug("updateFlowTable")
305 if flow == nil {
306 return nil
307 }
308 switch flow.GetCommand() {
309 case ofp.OfpFlowModCommand_OFPFC_ADD:
310 return agent.flowAdd(flow)
311 case ofp.OfpFlowModCommand_OFPFC_DELETE:
312 return agent.flowDelete(flow)
313 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
314 return agent.flowDeleteStrict(flow)
315 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
316 return agent.flowModify(flow)
317 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
318 return agent.flowModifyStrict(flow)
319 }
320 return status.Errorf(codes.Internal,
321 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
322}
323
324//updateGroupTable updates the group table of that logical device
325func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
326 log.Debug("updateGroupTable")
327 if groupMod == nil {
328 return nil
329 }
330 switch groupMod.GetCommand() {
331 case ofp.OfpGroupModCommand_OFPGC_ADD:
332 return agent.groupAdd(groupMod)
333 case ofp.OfpGroupModCommand_OFPGC_DELETE:
334 return agent.groupDelete(groupMod)
335 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
336 return agent.groupModify(groupMod)
337 }
338 return status.Errorf(codes.Internal,
339 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
340}
341
khenaidoo19d7b632018-10-30 10:49:50 -0400342//updateFlowGroupsWithoutLock updates the flows in the logical device without locking the logical device. This function
343//must only be called by a function that is holding the lock on the logical device
344func (agent *LogicalDeviceAgent) updateFlowGroupsWithoutLock(groups []*ofp.OfpGroupEntry) error {
khenaidoo43c82122018-11-22 18:38:28 -0500345 groupsCloned := make([]*ofp.OfpGroupEntry, len(groups))
346 copy(groupsCloned, groups)
347 if afterUpdate := agent.groupProxy.Update("/", groupsCloned, true, ""); afterUpdate == nil {
348 return errors.New(fmt.Sprintf("update-flow-group-failed:%s", agent.logicalDeviceId))
khenaidoo19d7b632018-10-30 10:49:50 -0400349 }
khenaidoo43c82122018-11-22 18:38:28 -0500350 return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400351}
352
353//flowAdd adds a flow to the flow table of that logical device
354func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
355 log.Debug("flowAdd")
356 if mod == nil {
357 return nil
358 }
khenaidoo92e62c52018-10-03 14:02:54 -0400359 agent.lockLogicalDevice.Lock()
360 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400361
362 var lDevice *voltha.LogicalDevice
363 var err error
364 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
365 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
366 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
367 }
368
369 var flows []*ofp.OfpFlowStats
370 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
371 flows = lDevice.Flows.Items
372 }
373
khenaidoo43c82122018-11-22 18:38:28 -0500374 //oldData := proto.Clone(lDevice.Flows).(*voltha.Flows)
khenaidoo19d7b632018-10-30 10:49:50 -0400375 changed := false
376 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
377 if checkOverlap {
378 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
379 // TODO: should this error be notified other than being logged?
380 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
381 } else {
382 // Add flow
383 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
384 flows = append(flows, flow)
385 changed = true
386 }
387 } else {
388 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
389 idx := fu.FindFlows(flows, flow)
390 if idx >= 0 {
391 oldFlow := flows[idx]
392 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
393 flow.ByteCount = oldFlow.ByteCount
394 flow.PacketCount = oldFlow.PacketCount
395 }
396 flows[idx] = flow
397 } else {
398 flows = append(flows, flow)
399 }
400 changed = true
401 }
402 if changed {
403 // Update model
khenaidoo43c82122018-11-22 18:38:28 -0500404 flowsToUpdate := &ofp.Flows{}
405 if lDevice.Flows != nil {
406 flowsToUpdate = &ofp.Flows{Items: flows}
khenaidoo19d7b632018-10-30 10:49:50 -0400407 }
khenaidoo43c82122018-11-22 18:38:28 -0500408 if err := agent.updateLogicalDeviceFlowsWithoutLock(flowsToUpdate); err != nil {
409 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400410 return err
411 }
412 }
khenaidoo19d7b632018-10-30 10:49:50 -0400413 return nil
414}
415
416//flowDelete deletes a flow from the flow table of that logical device
417func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
418 log.Debug("flowDelete")
419 if mod == nil {
420 return nil
421 }
422 agent.lockLogicalDevice.Lock()
423 defer agent.lockLogicalDevice.Unlock()
424
425 var lDevice *voltha.LogicalDevice
426 var err error
427 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
428 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
429 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
430 }
431 flows := lDevice.Flows.Items
432
433 //build a list of what to keep vs what to delete
434 toKeep := make([]*ofp.OfpFlowStats, 0)
435 for _, f := range flows {
436 if !fu.FlowMatchesMod(f, mod) {
437 toKeep = append(toKeep, f)
438 }
439 }
440
441 //Update flows
442 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500443 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
444 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400445 return err
446 }
447 }
448
449 //TODO: send announcement on delete
450 return nil
451}
452
453//flowStatsDelete deletes a flow from the flow table of that logical device
454func (agent *LogicalDeviceAgent) flowStatsDelete(flow *ofp.OfpFlowStats) error {
455 log.Debug("flowStatsDelete")
456 if flow == nil {
457 return nil
458 }
459 agent.lockLogicalDevice.Lock()
460 defer agent.lockLogicalDevice.Unlock()
461
462 var lDevice *voltha.LogicalDevice
463 var err error
464 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
465 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
466 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
467 }
468 flows := lDevice.Flows.Items
469
470 //build a list of what to keep vs what to delete
471 toKeep := make([]*ofp.OfpFlowStats, 0)
472 for _, f := range flows {
473 if !fu.FlowMatch(f, flow) {
474 toKeep = append(toKeep, f)
475 }
476 }
477
478 //Update flows
479 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500480 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400481 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
482 return err
483 }
484 }
485 return nil
486}
487
488//flowDeleteStrict deletes a flow from the flow table of that logical device
489func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
490 log.Debug("flowDeleteStrict")
491 if mod == nil {
492 return nil
493 }
494 agent.lockLogicalDevice.Lock()
495 defer agent.lockLogicalDevice.Unlock()
496
497 var lDevice *voltha.LogicalDevice
498 var err error
499 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
500 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
501 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
502 }
503 flows := lDevice.Flows.Items
504 changed := false
505 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
506 idx := fu.FindFlows(flows, flow)
507 if idx >= 0 {
508 flows = append(flows[:idx], flows[idx+1:]...)
509 changed = true
510 } else {
511 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
512 }
513
514 if changed {
khenaidoo43c82122018-11-22 18:38:28 -0500515 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400516 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
517 return err
518 }
519 }
520
521 return nil
522}
523
524//flowModify modifies a flow from the flow table of that logical device
525func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
526 return errors.New("flowModify not implemented")
527}
528
529//flowModifyStrict deletes a flow from the flow table of that logical device
530func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
531 return errors.New("flowModifyStrict not implemented")
532}
533
534func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
535 log.Debug("groupAdd")
536 if groupMod == nil {
537 return nil
538 }
539 agent.lockLogicalDevice.Lock()
540 defer agent.lockLogicalDevice.Unlock()
541
542 var lDevice *voltha.LogicalDevice
543 var err error
544 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
545 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
546 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
547 }
548 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -0400549 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
550 groups = append(groups, fd.GroupEntryFromGroupMod(groupMod))
khenaidoo43c82122018-11-22 18:38:28 -0500551 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
552 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400553 return err
554 }
555 } else {
556 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
557 }
khenaidoo19d7b632018-10-30 10:49:50 -0400558 return nil
559}
560
561func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
562 log.Debug("groupDelete")
563 if groupMod == nil {
564 return nil
565 }
566 agent.lockLogicalDevice.Lock()
567 defer agent.lockLogicalDevice.Unlock()
568
569 var lDevice *voltha.LogicalDevice
570 var err error
571 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
572 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
573 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
574 }
575 groups := lDevice.FlowGroups.Items
576 flows := lDevice.Flows.Items
577 groupsChanged := false
578 flowsChanged := false
579 groupId := groupMod.GroupId
580 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
581 //TODO we must delete all flows that point to this group and
582 //signal controller as requested by flow's flag
583 groups = []*ofp.OfpGroupEntry{}
584 groupsChanged = true
585 } else {
586 if idx := fu.FindGroup(groups, groupId); idx == -1 {
587 return nil // Valid case
588 } else {
589 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
590 groups = append(groups[:idx], groups[idx+1:]...)
591 groupsChanged = true
592 }
593 }
khenaidoo43c82122018-11-22 18:38:28 -0500594 if groupsChanged {
595 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
596 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400597 return err
598 }
599 }
khenaidoo43c82122018-11-22 18:38:28 -0500600 if flowsChanged {
601 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
602 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
603 return err
604 }
605 }
606
khenaidoo19d7b632018-10-30 10:49:50 -0400607 return nil
608}
609
610func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
611 log.Debug("groupModify")
612 if groupMod == nil {
613 return nil
614 }
615 agent.lockLogicalDevice.Lock()
616 defer agent.lockLogicalDevice.Unlock()
617
618 var lDevice *voltha.LogicalDevice
619 var err error
620 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
621 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
622 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
623 }
624 groups := lDevice.FlowGroups.Items
625 groupsChanged := false
626 groupId := groupMod.GroupId
627 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -0500628 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -0400629 } else {
630 //replace existing group entry with new group definition
631 groupEntry := fd.GroupEntryFromGroupMod(groupMod)
632 groups[idx] = groupEntry
633 groupsChanged = true
634 }
635 if groupsChanged {
khenaidoo43c82122018-11-22 18:38:28 -0500636 //lDevice.FlowGroups.Items = groups
637 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400638 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
639 return err
640 }
641 }
642 return nil
643}
644
645// deleteLogicalPort removes the logical port
646func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
647 agent.lockLogicalDevice.Lock()
648 defer agent.lockLogicalDevice.Unlock()
649
khenaidoo92e62c52018-10-03 14:02:54 -0400650 // Get the most up to date logical device
651 var logicaldevice *voltha.LogicalDevice
652 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400653 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -0400654 return nil
655 }
khenaidoo92e62c52018-10-03 14:02:54 -0400656 index := -1
657 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -0400658 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -0400659 index = i
660 break
661 }
662 }
663 if index >= 0 {
664 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
665 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
666 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
667 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
668 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
669 }
670 return nil
khenaidoob9203542018-09-17 22:56:37 -0400671}
672
khenaidoo19d7b632018-10-30 10:49:50 -0400673// enableLogicalPort enables the logical port
674func (agent *LogicalDeviceAgent) enableLogicalPort(lPort *voltha.LogicalPort) error {
675 agent.lockLogicalDevice.Lock()
676 defer agent.lockLogicalDevice.Unlock()
677
678 // Get the most up to date logical device
679 var logicaldevice *voltha.LogicalDevice
680 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
681 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
682 return nil
683 }
684 index := -1
685 for i, logicalPort := range logicaldevice.Ports {
686 if logicalPort.Id == lPort.Id {
687 index = i
688 break
689 }
690 }
691 if index >= 0 {
692 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
693 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
694 }
695 //TODO: Trigger subsequent actions on the device
696 return nil
697}
698
699// disableLogicalPort disabled the logical port
700func (agent *LogicalDeviceAgent) disableLogicalPort(lPort *voltha.LogicalPort) error {
701 agent.lockLogicalDevice.Lock()
702 defer agent.lockLogicalDevice.Unlock()
703
704 // Get the most up to date logical device
705 var logicaldevice *voltha.LogicalDevice
706 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
707 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
708 return nil
709 }
710 index := -1
711 for i, logicalPort := range logicaldevice.Ports {
712 if logicalPort.Id == lPort.Id {
713 index = i
714 break
715 }
716 }
717 if index >= 0 {
718 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
719 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
720 }
721 //TODO: Trigger subsequent actions on the device
722 return nil
723}
724
khenaidoo89b0e942018-10-21 21:11:33 -0400725func isNNIPort(portNo uint32, nniPortsNo []uint32) bool {
726 for _, pNo := range nniPortsNo {
727 if pNo == portNo {
728 return true
729 }
730 }
731 return false
732}
khenaidoo4d4802d2018-10-04 21:59:49 -0400733
khenaidoo89b0e942018-10-21 21:11:33 -0400734func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -0400735 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -0400736 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400737 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -0400738 if ingress == routeLink.Ingress && egress == routeLink.Egress {
739 return route
740 }
741 }
742 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
743 return nil
744}
745
khenaidoo19d7b632018-10-30 10:49:50 -0400746func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400747 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
748 // Get the updated logical device
khenaidoo79232702018-12-04 11:00:41 -0500749 var ld *ic.LogicalDevice
khenaidoo89b0e942018-10-21 21:11:33 -0400750 routes := make([]graph.RouteHop, 0)
751 var err error
752 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
753 return nil
754 }
755 nniLogicalPortsNo := make([]uint32, 0)
756 for _, logicalPort := range ld.Ports {
757 if logicalPort.RootPort {
758 nniLogicalPortsNo = append(nniLogicalPortsNo, logicalPort.OfpPort.PortNo)
759 }
760 }
761 if len(nniLogicalPortsNo) == 0 {
762 log.Errorw("no-nni-ports", log.Fields{"LogicalDeviceId": ld.Id})
763 return nil
764 }
khenaidoo19d7b632018-10-30 10:49:50 -0400765 // Note: A port value of 0 is equivalent to a nil port
766
khenaidoo89b0e942018-10-21 21:11:33 -0400767 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -0400768 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo89b0e942018-10-21 21:11:33 -0400769 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
khenaidoo19d7b632018-10-30 10:49:50 -0400770 if isNNIPort(ingressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400771 log.Debug("returning-half-route")
772 //This is a trap on the NNI Port
773 //Return a 'half' route to make the flow decomposer logic happy
774 for routeLink, route := range agent.deviceGraph.Routes {
775 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
776 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
777 routes = append(routes, route[1])
778 return routes
779 }
780 }
781 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
782 return nil
783 }
784 //treat it as if the output port is the first NNI of the OLT
khenaidoo19d7b632018-10-30 10:49:50 -0400785 egressPortNo = nniLogicalPortsNo[0]
khenaidoo89b0e942018-10-21 21:11:33 -0400786 }
787 //If ingress port is not specified (nil), it may be a wildcarded
788 //route if egress port is OFPP_CONTROLLER or a nni logical port,
789 //in which case we need to create a half-route where only the egress
790 //hop is filled, the first hop is nil
khenaidoo19d7b632018-10-30 10:49:50 -0400791 if ingressPortNo == 0 && isNNIPort(egressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400792 // We can use the 2nd hop of any upstream route, so just find the first upstream:
793 for routeLink, route := range agent.deviceGraph.Routes {
794 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
795 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
796 routes = append(routes, route[1])
797 return routes
798 }
799 }
800 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
801 return nil
802 }
803 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -0400804 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400805 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400806 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -0400807 routes = append(routes, route[0])
808 routes = append(routes, graph.RouteHop{})
809 return routes
810 }
811 }
812 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
813 return nil
814 }
815
816 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -0400817 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400818}
819
820// updateRoutes updates the device routes whenever there is a device or port changes relevant to this
821// logical device. TODO: Add more heuristics to this process to update the routes where a change has occurred
822// instead of rebuilding the entire set of routes
823func (agent *LogicalDeviceAgent) updateRoutes() {
khenaidoo19d7b632018-10-30 10:49:50 -0400824 if ld, err := agent.GetLogicalDevice(); err == nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400825 agent.deviceGraph.ComputeRoutes(ld.Ports)
826 }
827}
828
829func (agent *LogicalDeviceAgent) rootDeviceDefaultRules() *fu.FlowsAndGroups {
830 return fu.NewFlowsAndGroups()
831}
832
833func (agent *LogicalDeviceAgent) leafDeviceDefaultRules(deviceId string) *fu.FlowsAndGroups {
834 fg := fu.NewFlowsAndGroups()
835 var device *voltha.Device
836 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400837 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400838 return fg
839 }
840 //set the upstream and downstream ports
841 upstreamPorts := make([]*voltha.Port, 0)
842 downstreamPorts := make([]*voltha.Port, 0)
843 for _, port := range device.Ports {
844 if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_VENET_ONU {
845 upstreamPorts = append(upstreamPorts, port)
846 } else if port.Type == voltha.Port_ETHERNET_UNI {
847 downstreamPorts = append(downstreamPorts, port)
848 }
849 }
850 //it is possible that the downstream ports are not created, but the flow_decomposition has already
851 //kicked in. In such scenarios, cut short the processing and return.
khenaidoo6d055132019-02-12 16:51:19 -0500852 if len(downstreamPorts) == 0 || len(upstreamPorts) == 0{
khenaidoo89b0e942018-10-21 21:11:33 -0400853 return fg
854 }
855 // set up the default flows
856 var fa *fu.FlowArgs
857 fa = &fu.FlowArgs{
858 KV: fu.OfpFlowModArgs{"priority": 500},
859 MatchFields: []*ofp.OfpOxmOfbField{
860 fd.InPort(downstreamPorts[0].PortNo),
861 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
862 },
863 Actions: []*ofp.OfpAction{
864 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
khenaidoo19d7b632018-10-30 10:49:50 -0400865 fd.Output(upstreamPorts[0].PortNo),
khenaidoo89b0e942018-10-21 21:11:33 -0400866 },
867 }
868 fg.AddFlow(fd.MkFlowStat(fa))
869
870 fa = &fu.FlowArgs{
871 KV: fu.OfpFlowModArgs{"priority": 500},
872 MatchFields: []*ofp.OfpOxmOfbField{
873 fd.InPort(downstreamPorts[0].PortNo),
874 fd.VlanVid(0),
875 },
876 Actions: []*ofp.OfpAction{
877 fd.PushVlan(0x8100),
878 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
879 fd.Output(upstreamPorts[0].PortNo),
880 },
881 }
882 fg.AddFlow(fd.MkFlowStat(fa))
883
884 fa = &fu.FlowArgs{
885 KV: fu.OfpFlowModArgs{"priority": 500},
886 MatchFields: []*ofp.OfpOxmOfbField{
887 fd.InPort(upstreamPorts[0].PortNo),
888 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan),
889 },
890 Actions: []*ofp.OfpAction{
891 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
892 fd.Output(downstreamPorts[0].PortNo),
893 },
894 }
895 fg.AddFlow(fd.MkFlowStat(fa))
896
897 return fg
898}
899
900func (agent *LogicalDeviceAgent) generateDefaultRules() *fu.DeviceRules {
901 rules := fu.NewDeviceRules()
902 var ld *voltha.LogicalDevice
903 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400904 if ld, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400905 log.Warnw("no-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
906 return rules
907 }
908
909 deviceNodeIds := agent.deviceGraph.GetDeviceNodeIds()
khenaidooca301322019-01-09 23:06:32 -0500910 for deviceId := range deviceNodeIds {
khenaidoo89b0e942018-10-21 21:11:33 -0400911 if deviceId == ld.RootDeviceId {
912 rules.AddFlowsAndGroup(deviceId, agent.rootDeviceDefaultRules())
913 } else {
914 rules.AddFlowsAndGroup(deviceId, agent.leafDeviceDefaultRules(deviceId))
915 }
916 }
917 return rules
918}
919
920func (agent *LogicalDeviceAgent) GetAllDefaultRules() *fu.DeviceRules {
921 // Get latest
922 var lDevice *voltha.LogicalDevice
923 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400924 if lDevice, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400925 return fu.NewDeviceRules()
926 }
927 if agent.DefaultFlowRules == nil { // Nothing setup yet
khenaidoo19d7b632018-10-30 10:49:50 -0400928 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
khenaidoo89b0e942018-10-21 21:11:33 -0400929 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
930 agent.DefaultFlowRules = agent.generateDefaultRules()
931 }
932 return agent.DefaultFlowRules
933}
934
935func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
936 lPorts := make([]uint32, 0)
937 var exclPort uint32
938 if len(excludePort) == 1 {
939 exclPort = excludePort[0]
940 }
khenaidoo19d7b632018-10-30 10:49:50 -0400941 if lDevice, _ := agent.GetLogicalDevice(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400942 for _, port := range lDevice.Ports {
943 if port.OfpPort.PortNo != exclPort {
944 lPorts = append(lPorts, port.OfpPort.PortNo)
945 }
946 }
947 }
948 return lPorts
949}
khenaidoo19d7b632018-10-30 10:49:50 -0400950
951func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
952 return agent.deviceGraph
953}
954
955//setupDeviceGraph creates the device graph if not done already
956func (agent *LogicalDeviceAgent) setupDeviceGraph() {
957 if agent.deviceGraph == nil {
958 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
959 agent.updateRoutes()
960 }
961}
962
963func (agent *LogicalDeviceAgent) flowTableUpdated(args ...interface{}) interface{} {
964 log.Debugw("flowTableUpdated-callback", log.Fields{"argsLen": len(args)})
965
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500966 var previousData *ofp.Flows
967 var latestData *ofp.Flows
khenaidoo19d7b632018-10-30 10:49:50 -0400968
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500969 var ok bool
970 if previousData, ok = args[0].(*ofp.Flows); !ok {
971 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
972 }
973 if latestData, ok = args[1].(*ofp.Flows); !ok {
974 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
975 }
khenaidoo19d7b632018-10-30 10:49:50 -0400976
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500977 if reflect.DeepEqual(previousData.Items, latestData.Items) {
978 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -0400979 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500980 }
981
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500982 var groups *ofp.FlowGroups
983 lDevice, _ := agent.getLogicalDeviceWithoutLock()
984 groups = lDevice.FlowGroups
985 log.Debugw("flowsinfo", log.Fields{"flows": latestData, "groups": groups})
986 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *latestData, *groups)
987 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
988
khenaidooca301322019-01-09 23:06:32 -0500989 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500990 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -0500991 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
992 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
993 }
994 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
995 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
996 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500997 }
khenaidoo19d7b632018-10-30 10:49:50 -0400998
khenaidoo19d7b632018-10-30 10:49:50 -0400999 return nil
1000}
1001
1002func (agent *LogicalDeviceAgent) groupTableUpdated(args ...interface{}) interface{} {
1003 log.Debugw("groupTableUpdated-callback", log.Fields{"argsLen": len(args)})
1004
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001005 var previousData *ofp.FlowGroups
1006 var latestData *ofp.FlowGroups
khenaidoo19d7b632018-10-30 10:49:50 -04001007
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001008 var ok bool
1009 if previousData, ok = args[0].(*ofp.FlowGroups); !ok {
1010 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1011 }
1012 if latestData, ok = args[1].(*ofp.FlowGroups); !ok {
1013 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1014 }
khenaidoo19d7b632018-10-30 10:49:50 -04001015
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001016 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1017 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001018 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001019 }
1020
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001021 var flows *ofp.Flows
1022 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1023 flows = lDevice.Flows
1024 log.Debugw("groupsinfo", log.Fields{"groups": latestData, "flows": flows})
1025 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *flows, *latestData)
1026 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidooca301322019-01-09 23:06:32 -05001027 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001028 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001029 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1030 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1031 }
1032 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1033 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1034 }
khenaidoo19d7b632018-10-30 10:49:50 -04001035
khenaidooca301322019-01-09 23:06:32 -05001036 }
khenaidoo19d7b632018-10-30 10:49:50 -04001037 return nil
1038}
khenaidoofdbad6e2018-11-06 22:26:38 -05001039
khenaidoo43c82122018-11-22 18:38:28 -05001040func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
khenaidoofdbad6e2018-11-06 22:26:38 -05001041 log.Debugw("packet-out", log.Fields{"packet": packet.GetInPort()})
1042 outPort := fd.GetPacketOutPort(packet)
1043 //frame := packet.GetData()
1044 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001045 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
1046 log.Error("packetout-failed", log.Fields{"logicalDeviceID":agent.rootDeviceId})
1047 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001048}
1049
khenaidoo297cd252019-02-07 22:10:23 -05001050func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionId string, packet []byte) {
1051 log.Debugw("packet-in", log.Fields{"port": port, "packet": packet, "transactionId": transactionId})
khenaidooca301322019-01-09 23:06:32 -05001052 packetIn := fd.MkPacketIn(port, packet)
khenaidoo297cd252019-02-07 22:10:23 -05001053 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, transactionId, packetIn)
khenaidooca301322019-01-09 23:06:32 -05001054 log.Debugw("sending-packet-in", log.Fields{"packet-in": packetIn})
khenaidoofdbad6e2018-11-06 22:26:38 -05001055}