blob: 4a0488ada5c2b0f216e8daa355ac6c09620f1446 [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
khenaidoo8c3303d2019-02-13 14:59:39 -050039 //lastData *voltha.LogicalDevice
khenaidoo92e62c52018-10-03 14:02:54 -040040 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
khenaidoofc1314d2019-03-14 09:34:21 -040049 ldProxy *model.Proxy
50 portProxies map[string]*model.Proxy
51 portProxiesLock sync.RWMutex
khenaidoo92e62c52018-10-03 14:02:54 -040052 lockLogicalDevice sync.RWMutex
khenaidoo19d7b632018-10-30 10:49:50 -040053 flowDecomposer *fd.FlowDecomposer
khenaidoob9203542018-09-17 22:56:37 -040054}
55
Stephane Barbarie1ab43272018-12-08 21:42:13 -050056func newLogicalDeviceAgent(id string, deviceId string, ldeviceMgr *LogicalDeviceManager,
57 deviceMgr *DeviceManager,
khenaidoo9a468962018-09-19 15:33:13 -040058 cdProxy *model.Proxy) *LogicalDeviceAgent {
khenaidoob9203542018-09-17 22:56:37 -040059 var agent LogicalDeviceAgent
60 agent.exitChannel = make(chan int, 1)
61 agent.logicalDeviceId = id
Stephane Barbarie1ab43272018-12-08 21:42:13 -050062 agent.rootDeviceId = deviceId
khenaidoob9203542018-09-17 22:56:37 -040063 agent.deviceMgr = deviceMgr
khenaidoo9a468962018-09-19 15:33:13 -040064 agent.clusterDataProxy = cdProxy
khenaidoob9203542018-09-17 22:56:37 -040065 agent.ldeviceMgr = ldeviceMgr
khenaidoo19d7b632018-10-30 10:49:50 -040066 agent.flowDecomposer = fd.NewFlowDecomposer(agent.deviceMgr)
khenaidoo92e62c52018-10-03 14:02:54 -040067 agent.lockLogicalDevice = sync.RWMutex{}
khenaidoofc1314d2019-03-14 09:34:21 -040068 agent.portProxies = make(map[string]*model.Proxy)
69 agent.portProxiesLock = sync.RWMutex{}
khenaidoob9203542018-09-17 22:56:37 -040070 return &agent
71}
72
khenaidoo4d4802d2018-10-04 21:59:49 -040073// start creates the logical device and add it to the data model
khenaidoo297cd252019-02-07 22:10:23 -050074func (agent *LogicalDeviceAgent) start(ctx context.Context, loadFromdB bool) error {
75 log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId, "loadFromdB": loadFromdB})
76 var ld *voltha.LogicalDevice
77 if !loadFromdB {
78 //Build the logical device based on information retrieved from the device adapter
79 var switchCap *ic.SwitchCapability
80 var err error
81 if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
khenaidoob9203542018-09-17 22:56:37 -040082 log.Errorw("error-creating-logical-device", log.Fields{"error": err})
83 return err
84 }
khenaidoo297cd252019-02-07 22:10:23 -050085 ld = &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
86
87 // Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
88 var datapathID uint64
89 if datapathID, err = CreateDataPathId(agent.logicalDeviceId); err != nil {
90 log.Errorw("error-creating-datapath-id", log.Fields{"error": err})
91 return err
92 }
93 ld.DatapathId = datapathID
94 ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
khenaidoo6d055132019-02-12 16:51:19 -050095 log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
khenaidoo297cd252019-02-07 22:10:23 -050096 ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
97 ld.Flows = &ofp.Flows{Items: nil}
98 ld.FlowGroups = &ofp.FlowGroups{Items: nil}
99
khenaidoo297cd252019-02-07 22:10:23 -0500100 agent.lockLogicalDevice.Lock()
khenaidoo297cd252019-02-07 22:10:23 -0500101 // Save the logical device
102 if added := agent.clusterDataProxy.AddWithID("/logical_devices", ld.Id, ld, ""); added == nil {
103 log.Errorw("failed-to-add-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
104 } else {
105 log.Debugw("logicaldevice-created", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
106 }
107 agent.lockLogicalDevice.Unlock()
khenaidoofc1314d2019-03-14 09:34:21 -0400108
109 // TODO: Set the NNI ports in a separate call once the port update issue is fixed.
110 go agent.setupNNILogicalPorts(ctx, agent.rootDeviceId)
khenaidoo297cd252019-02-07 22:10:23 -0500111 } else {
112 // load from dB - the logical may not exist at this time. On error, just return and the calling function
113 // will destroy this agent.
114 var err error
115 if ld, err = agent.GetLogicalDevice(); err != nil {
116 log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
117 return err
118 }
khenaidoo8c3303d2019-02-13 14:59:39 -0500119 // Update the root device Id
120 agent.rootDeviceId = ld.RootDeviceId
khenaidoob9203542018-09-17 22:56:37 -0400121 }
khenaidoo92e62c52018-10-03 14:02:54 -0400122 agent.lockLogicalDevice.Lock()
khenaidoofc1314d2019-03-14 09:34:21 -0400123
khenaidoo43c82122018-11-22 18:38:28 -0500124 agent.flowProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400125 fmt.Sprintf("/logical_devices/%s/flows", agent.logicalDeviceId),
126 false)
khenaidoo43c82122018-11-22 18:38:28 -0500127 agent.groupProxy = agent.clusterDataProxy.Root.CreateProxy(
khenaidoo19d7b632018-10-30 10:49:50 -0400128 fmt.Sprintf("/logical_devices/%s/flow_groups", agent.logicalDeviceId),
129 false)
khenaidoofc1314d2019-03-14 09:34:21 -0400130 agent.ldProxy = agent.clusterDataProxy.Root.CreateProxy(
131 fmt.Sprintf("/logical_devices/%s", agent.logicalDeviceId),
132 false)
khenaidoo19d7b632018-10-30 10:49:50 -0400133
134 agent.flowProxy.RegisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
khenaidoo43c82122018-11-22 18:38:28 -0500135 agent.groupProxy.RegisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
khenaidoo19d7b632018-10-30 10:49:50 -0400136
khenaidoofc1314d2019-03-14 09:34:21 -0400137 // TODO: Use a port proxy once the POST_ADD is fixed
138 agent.ldProxy.RegisterCallback(model.POST_UPDATE, agent.portUpdated)
khenaidoobcf205b2019-01-25 22:21:14 -0500139
khenaidoofc1314d2019-03-14 09:34:21 -0400140 agent.lockLogicalDevice.Unlock()
khenaidoobcf205b2019-01-25 22:21:14 -0500141
khenaidoob9203542018-09-17 22:56:37 -0400142 return nil
143}
144
khenaidoo4d4802d2018-10-04 21:59:49 -0400145// stop stops the logical devuce agent. This removes the logical device from the data model.
146func (agent *LogicalDeviceAgent) stop(ctx context.Context) {
147 log.Info("stopping-logical_device-agent")
148 agent.lockLogicalDevice.Lock()
149 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500150
151 // Unregister to teh callbacks
152 if agent.flowProxy != nil {
153 agent.flowProxy.UnregisterCallback(model.POST_UPDATE, agent.flowTableUpdated)
154 }
155 if agent.groupProxy != nil {
156 agent.groupProxy.UnregisterCallback(model.POST_UPDATE, agent.groupTableUpdated)
157 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400158 //Remove the logical device from the model
159 if removed := agent.clusterDataProxy.Remove("/logical_devices/"+agent.logicalDeviceId, ""); removed == nil {
160 log.Errorw("failed-to-remove-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
161 } else {
162 log.Debugw("logicaldevice-removed", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
163 }
164 agent.exitChannel <- 1
165 log.Info("logical_device-agent-stopped")
166}
167
khenaidoo19d7b632018-10-30 10:49:50 -0400168// GetLogicalDevice locks the logical device model and then retrieves the latest logical device information
169func (agent *LogicalDeviceAgent) GetLogicalDevice() (*voltha.LogicalDevice, error) {
170 log.Debug("GetLogicalDevice")
khenaidoo92e62c52018-10-03 14:02:54 -0400171 agent.lockLogicalDevice.Lock()
172 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500173 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400174 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500175 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400176 }
177 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
178}
179
khenaidoo19d7b632018-10-30 10:49:50 -0400180func (agent *LogicalDeviceAgent) ListLogicalDevicePorts() (*voltha.LogicalPorts, error) {
181 log.Debug("!!!!!ListLogicalDevicePorts")
182 agent.lockLogicalDevice.Lock()
183 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500184 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400185 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
186 lPorts := make([]*voltha.LogicalPort, 0)
187 for _, port := range lDevice.Ports {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500188 lPorts = append(lPorts, port)
khenaidoo19d7b632018-10-30 10:49:50 -0400189 }
190 return &voltha.LogicalPorts{Items: lPorts}, nil
191 }
192 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
193}
194
195// listFlows locks the logical device model and then retrieves the latest flow information
196func (agent *LogicalDeviceAgent) listFlows() []*ofp.OfpFlowStats {
197 log.Debug("listFlows")
198 agent.lockLogicalDevice.Lock()
199 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500200 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400201 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
202 return lDevice.Flows.Items
203 }
204 return nil
205}
206
207// listFlowGroups locks the logical device model and then retrieves the latest flow groups information
208func (agent *LogicalDeviceAgent) listFlowGroups() []*ofp.OfpGroupEntry {
209 log.Debug("listFlowGroups")
210 agent.lockLogicalDevice.Lock()
211 defer agent.lockLogicalDevice.Unlock()
khenaidoo8c3303d2019-02-13 14:59:39 -0500212 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo19d7b632018-10-30 10:49:50 -0400213 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
214 return lDevice.FlowGroups.Items
215 }
216 return nil
217}
218
khenaidoo43c82122018-11-22 18:38:28 -0500219//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
220func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowsWithoutLock(flows *ofp.Flows) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500221 afterUpdate := agent.flowProxy.Update("/", flows, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500222 if afterUpdate == nil {
223 return status.Errorf(codes.Internal, "failed-updating-logical-device-flows:%s", agent.logicalDeviceId)
224 }
khenaidoo43c82122018-11-22 18:38:28 -0500225 return nil
226}
227
228//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
229func (agent *LogicalDeviceAgent) updateLogicalDeviceFlowGroupsWithoutLock(flowGroups *ofp.FlowGroups) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500230 afterUpdate := agent.groupProxy.Update("/", flowGroups, false, "")
khenaidoo43c82122018-11-22 18:38:28 -0500231 if afterUpdate == nil {
232 return status.Errorf(codes.Internal, "failed-updating-logical-device-flow-groups:%s", agent.logicalDeviceId)
233 }
khenaidoo43c82122018-11-22 18:38:28 -0500234 return nil
235}
236
khenaidoo4d4802d2018-10-04 21:59:49 -0400237// getLogicalDeviceWithoutLock retrieves a logical device from the model without locking it. This is used only by
238// functions that have already acquired the logical device lock to the model
khenaidoo92e62c52018-10-03 14:02:54 -0400239func (agent *LogicalDeviceAgent) getLogicalDeviceWithoutLock() (*voltha.LogicalDevice, error) {
240 log.Debug("getLogicalDeviceWithoutLock")
khenaidoo8c3303d2019-02-13 14:59:39 -0500241 logicalDevice := agent.clusterDataProxy.Get("/logical_devices/"+agent.logicalDeviceId, 0, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400242 if lDevice, ok := logicalDevice.(*voltha.LogicalDevice); ok {
khenaidoofc1314d2019-03-14 09:34:21 -0400243 log.Debug("getLogicalDeviceWithoutLock", log.Fields{"ldevice": lDevice})
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500244 return lDevice, nil
khenaidoo92e62c52018-10-03 14:02:54 -0400245 }
246 return nil, status.Errorf(codes.NotFound, "logical_device-%s", agent.logicalDeviceId)
247}
248
khenaidoofc1314d2019-03-14 09:34:21 -0400249
250func (agent *LogicalDeviceAgent) addLogicalPort (device *voltha.Device, port *voltha.Port) error {
251 if port.Type == voltha.Port_ETHERNET_NNI {
252 if err := agent.addNNILogicalPort(device, port); err != nil {
253 return err
254 }
255 } else if port.Type == voltha.Port_ETHERNET_UNI {
256 if err := agent.addUNILogicalPort(device, port); err != nil {
257 return err
258 }
259 } else {
260 log.Debugw("invalid-port-type", log.Fields{"deviceId": device.Id, "port": port})
261 return nil
262 }
263 go agent.setupDeviceGraph()
264 return nil
265}
266
267// setupNNILogicalPorts creates an NNI port on the logical device that represents an NNI interface on a root device
268func (agent *LogicalDeviceAgent) setupNNILogicalPorts(ctx context.Context, deviceId string) error {
269 log.Infow("setupNNILogicalPorts-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoob9203542018-09-17 22:56:37 -0400270 // Build the logical device based on information retrieved from the device adapter
khenaidoofc1314d2019-03-14 09:34:21 -0400271 //var portCap *ic.PortCapability
272 var err error
273
274 var device *voltha.Device
275 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
276 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": device.Id})
277 return err
278 }
279
280 //Get UNI port number
281 //var uniPort uint32
282 changesMade := false
283 for _, port := range device.Ports {
284 if port.Type == voltha.Port_ETHERNET_NNI {
285 if err = agent.addNNILogicalPort(device, port); err != nil {
286 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
287 } else {
288 changesMade = true
289 }
290 //uniPort = port.PortNo
291 }
292 }
293 if changesMade {
294 go agent.setupDeviceGraph()
295 }
296 return err
297}
298
299
300// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
301func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
302 log.Infow("setupUNILogicalPort-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
303 // Build the logical device based on information retrieved from the device adapter
304 //var portCap *ic.PortCapability
khenaidoob9203542018-09-17 22:56:37 -0400305 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400306
307 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400308 //var uniPort uint32
309 changesMade := false
khenaidoo19d7b632018-10-30 10:49:50 -0400310 for _, port := range childDevice.Ports {
311 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoofc1314d2019-03-14 09:34:21 -0400312 if err = agent.addUNILogicalPort(childDevice, port); err != nil {
313 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
314 } else {
315 changesMade = true
316 }
317 //uniPort = port.PortNo
khenaidoo19d7b632018-10-30 10:49:50 -0400318 }
319 }
khenaidoofc1314d2019-03-14 09:34:21 -0400320 if changesMade {
321 go agent.setupDeviceGraph()
khenaidoob9203542018-09-17 22:56:37 -0400322 }
khenaidoofc1314d2019-03-14 09:34:21 -0400323 //if portCap, err = agent.deviceMgr.getPortCapability(ctx, childDevice.Id, uniPort); err != nil {
324 // log.Errorw("error-creating-logical-port", log.Fields{"error": err})
325 // return err
326 //}
327 //agent.lockLogicalDevice.Lock()
328 //defer agent.lockLogicalDevice.Unlock()
329 //// Get stored logical device
330 //if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
331 // return status.Error(codes.NotFound, agent.logicalDeviceId)
332 //} else {
333 // log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
334 // portCap.Port.RootPort = false
335 // //TODO: For now use the channel id assigned by the OLT as logical port number
336 // lPortNo := childDevice.ProxyAddress.ChannelId
337 // portCap.Port.Id = fmt.Sprintf("uni-%d", lPortNo)
338 // portCap.Port.OfpPort.PortNo = lPortNo
339 // portCap.Port.OfpPort.Name = portCap.Port.Id
340 // portCap.Port.DeviceId = childDevice.Id
341 // portCap.Port.DevicePortNo = uniPort
342 // portCap.Port.DeviceId = childDevice.Id
343 //
344 // ldevice.Ports = append(ldevice.Ports, portCap.Port)
345 // return agent.updateLogicalDeviceWithoutLock(ldevice)
346 //}
347 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400348}
349
350//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
351func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500352 afterUpdate := agent.clusterDataProxy.Update("/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400353 if afterUpdate == nil {
354 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
355 }
khenaidoofc1314d2019-03-14 09:34:21 -0400356 //if a, ok := afterUpdate.(*voltha.LogicalDevice); ok {
357 // log.Debugw("AFTER UPDATE", log.Fields{"logical": a})
358 //}
khenaidoo92e62c52018-10-03 14:02:54 -0400359 return nil
360}
361
khenaidoo19d7b632018-10-30 10:49:50 -0400362//updateFlowTable updates the flow table of that logical device
363func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
364 log.Debug("updateFlowTable")
365 if flow == nil {
366 return nil
367 }
368 switch flow.GetCommand() {
369 case ofp.OfpFlowModCommand_OFPFC_ADD:
370 return agent.flowAdd(flow)
371 case ofp.OfpFlowModCommand_OFPFC_DELETE:
372 return agent.flowDelete(flow)
373 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
374 return agent.flowDeleteStrict(flow)
375 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
376 return agent.flowModify(flow)
377 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
378 return agent.flowModifyStrict(flow)
379 }
380 return status.Errorf(codes.Internal,
381 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
382}
383
384//updateGroupTable updates the group table of that logical device
385func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
386 log.Debug("updateGroupTable")
387 if groupMod == nil {
388 return nil
389 }
390 switch groupMod.GetCommand() {
391 case ofp.OfpGroupModCommand_OFPGC_ADD:
392 return agent.groupAdd(groupMod)
393 case ofp.OfpGroupModCommand_OFPGC_DELETE:
394 return agent.groupDelete(groupMod)
395 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
396 return agent.groupModify(groupMod)
397 }
398 return status.Errorf(codes.Internal,
399 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
400}
401
khenaidoo19d7b632018-10-30 10:49:50 -0400402//updateFlowGroupsWithoutLock updates the flows in the logical device without locking the logical device. This function
403//must only be called by a function that is holding the lock on the logical device
404func (agent *LogicalDeviceAgent) updateFlowGroupsWithoutLock(groups []*ofp.OfpGroupEntry) error {
khenaidoo43c82122018-11-22 18:38:28 -0500405 groupsCloned := make([]*ofp.OfpGroupEntry, len(groups))
406 copy(groupsCloned, groups)
407 if afterUpdate := agent.groupProxy.Update("/", groupsCloned, true, ""); afterUpdate == nil {
408 return errors.New(fmt.Sprintf("update-flow-group-failed:%s", agent.logicalDeviceId))
khenaidoo19d7b632018-10-30 10:49:50 -0400409 }
khenaidoo43c82122018-11-22 18:38:28 -0500410 return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400411}
412
413//flowAdd adds a flow to the flow table of that logical device
414func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
415 log.Debug("flowAdd")
416 if mod == nil {
417 return nil
418 }
khenaidoo92e62c52018-10-03 14:02:54 -0400419 agent.lockLogicalDevice.Lock()
420 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400421
422 var lDevice *voltha.LogicalDevice
423 var err error
424 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
425 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
426 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
427 }
428
429 var flows []*ofp.OfpFlowStats
430 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
431 flows = lDevice.Flows.Items
432 }
433
khenaidoo43c82122018-11-22 18:38:28 -0500434 //oldData := proto.Clone(lDevice.Flows).(*voltha.Flows)
khenaidoo19d7b632018-10-30 10:49:50 -0400435 changed := false
436 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
437 if checkOverlap {
438 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
439 // TODO: should this error be notified other than being logged?
440 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
441 } else {
442 // Add flow
443 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
444 flows = append(flows, flow)
445 changed = true
446 }
447 } else {
448 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
449 idx := fu.FindFlows(flows, flow)
450 if idx >= 0 {
451 oldFlow := flows[idx]
452 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
453 flow.ByteCount = oldFlow.ByteCount
454 flow.PacketCount = oldFlow.PacketCount
455 }
456 flows[idx] = flow
457 } else {
458 flows = append(flows, flow)
459 }
460 changed = true
461 }
462 if changed {
463 // Update model
khenaidoo43c82122018-11-22 18:38:28 -0500464 flowsToUpdate := &ofp.Flows{}
465 if lDevice.Flows != nil {
466 flowsToUpdate = &ofp.Flows{Items: flows}
khenaidoo19d7b632018-10-30 10:49:50 -0400467 }
khenaidoo43c82122018-11-22 18:38:28 -0500468 if err := agent.updateLogicalDeviceFlowsWithoutLock(flowsToUpdate); err != nil {
469 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400470 return err
471 }
472 }
khenaidoo19d7b632018-10-30 10:49:50 -0400473 return nil
474}
475
476//flowDelete deletes a flow from the flow table of that logical device
477func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
478 log.Debug("flowDelete")
479 if mod == nil {
480 return nil
481 }
482 agent.lockLogicalDevice.Lock()
483 defer agent.lockLogicalDevice.Unlock()
484
485 var lDevice *voltha.LogicalDevice
486 var err error
487 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
488 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
489 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
490 }
491 flows := lDevice.Flows.Items
492
493 //build a list of what to keep vs what to delete
494 toKeep := make([]*ofp.OfpFlowStats, 0)
495 for _, f := range flows {
496 if !fu.FlowMatchesMod(f, mod) {
497 toKeep = append(toKeep, f)
498 }
499 }
500
501 //Update flows
502 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500503 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
504 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400505 return err
506 }
507 }
508
509 //TODO: send announcement on delete
510 return nil
511}
512
513//flowStatsDelete deletes a flow from the flow table of that logical device
514func (agent *LogicalDeviceAgent) flowStatsDelete(flow *ofp.OfpFlowStats) error {
515 log.Debug("flowStatsDelete")
516 if flow == 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 flows := lDevice.Flows.Items
529
530 //build a list of what to keep vs what to delete
531 toKeep := make([]*ofp.OfpFlowStats, 0)
532 for _, f := range flows {
533 if !fu.FlowMatch(f, flow) {
534 toKeep = append(toKeep, f)
535 }
536 }
537
538 //Update flows
539 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500540 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400541 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
542 return err
543 }
544 }
545 return nil
546}
547
548//flowDeleteStrict deletes a flow from the flow table of that logical device
549func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
550 log.Debug("flowDeleteStrict")
551 if mod == nil {
552 return nil
553 }
554 agent.lockLogicalDevice.Lock()
555 defer agent.lockLogicalDevice.Unlock()
556
557 var lDevice *voltha.LogicalDevice
558 var err error
559 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
560 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
561 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
562 }
563 flows := lDevice.Flows.Items
564 changed := false
565 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
566 idx := fu.FindFlows(flows, flow)
567 if idx >= 0 {
568 flows = append(flows[:idx], flows[idx+1:]...)
569 changed = true
570 } else {
571 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
572 }
573
574 if changed {
khenaidoo43c82122018-11-22 18:38:28 -0500575 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400576 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
577 return err
578 }
579 }
580
581 return nil
582}
583
584//flowModify modifies a flow from the flow table of that logical device
585func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
586 return errors.New("flowModify not implemented")
587}
588
589//flowModifyStrict deletes a flow from the flow table of that logical device
590func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
591 return errors.New("flowModifyStrict not implemented")
592}
593
594func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
595 log.Debug("groupAdd")
596 if groupMod == nil {
597 return nil
598 }
599 agent.lockLogicalDevice.Lock()
600 defer agent.lockLogicalDevice.Unlock()
601
602 var lDevice *voltha.LogicalDevice
603 var err error
604 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
605 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
606 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
607 }
608 groups := lDevice.FlowGroups.Items
khenaidoo19d7b632018-10-30 10:49:50 -0400609 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
610 groups = append(groups, fd.GroupEntryFromGroupMod(groupMod))
khenaidoo43c82122018-11-22 18:38:28 -0500611 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
612 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400613 return err
614 }
615 } else {
616 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
617 }
khenaidoo19d7b632018-10-30 10:49:50 -0400618 return nil
619}
620
621func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
622 log.Debug("groupDelete")
623 if groupMod == nil {
624 return nil
625 }
626 agent.lockLogicalDevice.Lock()
627 defer agent.lockLogicalDevice.Unlock()
628
629 var lDevice *voltha.LogicalDevice
630 var err error
631 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
632 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
633 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
634 }
635 groups := lDevice.FlowGroups.Items
636 flows := lDevice.Flows.Items
637 groupsChanged := false
638 flowsChanged := false
639 groupId := groupMod.GroupId
640 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
641 //TODO we must delete all flows that point to this group and
642 //signal controller as requested by flow's flag
643 groups = []*ofp.OfpGroupEntry{}
644 groupsChanged = true
645 } else {
646 if idx := fu.FindGroup(groups, groupId); idx == -1 {
647 return nil // Valid case
648 } else {
649 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
650 groups = append(groups[:idx], groups[idx+1:]...)
651 groupsChanged = true
652 }
653 }
khenaidoo43c82122018-11-22 18:38:28 -0500654 if groupsChanged {
655 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
656 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400657 return err
658 }
659 }
khenaidoo43c82122018-11-22 18:38:28 -0500660 if flowsChanged {
661 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
662 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
663 return err
664 }
665 }
666
khenaidoo19d7b632018-10-30 10:49:50 -0400667 return nil
668}
669
670func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
671 log.Debug("groupModify")
672 if groupMod == nil {
673 return nil
674 }
675 agent.lockLogicalDevice.Lock()
676 defer agent.lockLogicalDevice.Unlock()
677
678 var lDevice *voltha.LogicalDevice
679 var err error
680 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
681 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
682 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
683 }
684 groups := lDevice.FlowGroups.Items
685 groupsChanged := false
686 groupId := groupMod.GroupId
687 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -0500688 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -0400689 } else {
690 //replace existing group entry with new group definition
691 groupEntry := fd.GroupEntryFromGroupMod(groupMod)
692 groups[idx] = groupEntry
693 groupsChanged = true
694 }
695 if groupsChanged {
khenaidoo43c82122018-11-22 18:38:28 -0500696 //lDevice.FlowGroups.Items = groups
697 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400698 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
699 return err
700 }
701 }
702 return nil
703}
704
705// deleteLogicalPort removes the logical port
706func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
707 agent.lockLogicalDevice.Lock()
708 defer agent.lockLogicalDevice.Unlock()
709
khenaidoo92e62c52018-10-03 14:02:54 -0400710 // Get the most up to date logical device
711 var logicaldevice *voltha.LogicalDevice
712 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400713 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -0400714 return nil
715 }
khenaidoo92e62c52018-10-03 14:02:54 -0400716 index := -1
717 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -0400718 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -0400719 index = i
720 break
721 }
722 }
723 if index >= 0 {
724 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
725 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
726 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
727 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
728 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
729 }
730 return nil
khenaidoob9203542018-09-17 22:56:37 -0400731}
732
khenaidoo19d7b632018-10-30 10:49:50 -0400733// enableLogicalPort enables the logical port
734func (agent *LogicalDeviceAgent) enableLogicalPort(lPort *voltha.LogicalPort) error {
735 agent.lockLogicalDevice.Lock()
736 defer agent.lockLogicalDevice.Unlock()
737
738 // Get the most up to date logical device
739 var logicaldevice *voltha.LogicalDevice
740 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
741 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
742 return nil
743 }
744 index := -1
745 for i, logicalPort := range logicaldevice.Ports {
746 if logicalPort.Id == lPort.Id {
747 index = i
748 break
749 }
750 }
751 if index >= 0 {
752 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
753 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
754 }
755 //TODO: Trigger subsequent actions on the device
756 return nil
757}
758
759// disableLogicalPort disabled the logical port
760func (agent *LogicalDeviceAgent) disableLogicalPort(lPort *voltha.LogicalPort) error {
761 agent.lockLogicalDevice.Lock()
762 defer agent.lockLogicalDevice.Unlock()
763
764 // Get the most up to date logical device
765 var logicaldevice *voltha.LogicalDevice
766 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
767 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
768 return nil
769 }
770 index := -1
771 for i, logicalPort := range logicaldevice.Ports {
772 if logicalPort.Id == lPort.Id {
773 index = i
774 break
775 }
776 }
777 if index >= 0 {
778 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
779 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
780 }
781 //TODO: Trigger subsequent actions on the device
782 return nil
783}
784
khenaidoo89b0e942018-10-21 21:11:33 -0400785func isNNIPort(portNo uint32, nniPortsNo []uint32) bool {
786 for _, pNo := range nniPortsNo {
787 if pNo == portNo {
788 return true
789 }
790 }
791 return false
792}
khenaidoo4d4802d2018-10-04 21:59:49 -0400793
khenaidoo89b0e942018-10-21 21:11:33 -0400794func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -0400795 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -0400796 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400797 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -0400798 if ingress == routeLink.Ingress && egress == routeLink.Egress {
799 return route
800 }
801 }
802 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
803 return nil
804}
805
khenaidoo19d7b632018-10-30 10:49:50 -0400806func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400807 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
808 // Get the updated logical device
khenaidoo79232702018-12-04 11:00:41 -0500809 var ld *ic.LogicalDevice
khenaidoo89b0e942018-10-21 21:11:33 -0400810 routes := make([]graph.RouteHop, 0)
811 var err error
812 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
813 return nil
814 }
815 nniLogicalPortsNo := make([]uint32, 0)
816 for _, logicalPort := range ld.Ports {
817 if logicalPort.RootPort {
818 nniLogicalPortsNo = append(nniLogicalPortsNo, logicalPort.OfpPort.PortNo)
819 }
820 }
821 if len(nniLogicalPortsNo) == 0 {
822 log.Errorw("no-nni-ports", log.Fields{"LogicalDeviceId": ld.Id})
823 return nil
824 }
khenaidoo19d7b632018-10-30 10:49:50 -0400825 // Note: A port value of 0 is equivalent to a nil port
826
khenaidoo89b0e942018-10-21 21:11:33 -0400827 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -0400828 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo89b0e942018-10-21 21:11:33 -0400829 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
khenaidoo19d7b632018-10-30 10:49:50 -0400830 if isNNIPort(ingressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400831 log.Debug("returning-half-route")
832 //This is a trap on the NNI Port
833 //Return a 'half' route to make the flow decomposer logic happy
834 for routeLink, route := range agent.deviceGraph.Routes {
835 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
836 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
837 routes = append(routes, route[1])
838 return routes
839 }
840 }
841 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
842 return nil
843 }
844 //treat it as if the output port is the first NNI of the OLT
khenaidoo19d7b632018-10-30 10:49:50 -0400845 egressPortNo = nniLogicalPortsNo[0]
khenaidoo89b0e942018-10-21 21:11:33 -0400846 }
847 //If ingress port is not specified (nil), it may be a wildcarded
848 //route if egress port is OFPP_CONTROLLER or a nni logical port,
849 //in which case we need to create a half-route where only the egress
850 //hop is filled, the first hop is nil
khenaidoo19d7b632018-10-30 10:49:50 -0400851 if ingressPortNo == 0 && isNNIPort(egressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400852 // We can use the 2nd hop of any upstream route, so just find the first upstream:
853 for routeLink, route := range agent.deviceGraph.Routes {
854 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
855 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
856 routes = append(routes, route[1])
857 return routes
858 }
859 }
860 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
861 return nil
862 }
863 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -0400864 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400865 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400866 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -0400867 routes = append(routes, route[0])
868 routes = append(routes, graph.RouteHop{})
869 return routes
870 }
871 }
872 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
873 return nil
874 }
875
876 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -0400877 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400878}
879
880// updateRoutes updates the device routes whenever there is a device or port changes relevant to this
881// logical device. TODO: Add more heuristics to this process to update the routes where a change has occurred
882// instead of rebuilding the entire set of routes
883func (agent *LogicalDeviceAgent) updateRoutes() {
khenaidoo19d7b632018-10-30 10:49:50 -0400884 if ld, err := agent.GetLogicalDevice(); err == nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400885 agent.deviceGraph.ComputeRoutes(ld.Ports)
886 }
887}
888
889func (agent *LogicalDeviceAgent) rootDeviceDefaultRules() *fu.FlowsAndGroups {
890 return fu.NewFlowsAndGroups()
891}
892
893func (agent *LogicalDeviceAgent) leafDeviceDefaultRules(deviceId string) *fu.FlowsAndGroups {
894 fg := fu.NewFlowsAndGroups()
895 var device *voltha.Device
896 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400897 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400898 return fg
899 }
900 //set the upstream and downstream ports
901 upstreamPorts := make([]*voltha.Port, 0)
902 downstreamPorts := make([]*voltha.Port, 0)
903 for _, port := range device.Ports {
904 if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_VENET_ONU {
905 upstreamPorts = append(upstreamPorts, port)
906 } else if port.Type == voltha.Port_ETHERNET_UNI {
907 downstreamPorts = append(downstreamPorts, port)
908 }
909 }
910 //it is possible that the downstream ports are not created, but the flow_decomposition has already
911 //kicked in. In such scenarios, cut short the processing and return.
khenaidoo6d055132019-02-12 16:51:19 -0500912 if len(downstreamPorts) == 0 || len(upstreamPorts) == 0{
khenaidoo89b0e942018-10-21 21:11:33 -0400913 return fg
914 }
915 // set up the default flows
916 var fa *fu.FlowArgs
917 fa = &fu.FlowArgs{
918 KV: fu.OfpFlowModArgs{"priority": 500},
919 MatchFields: []*ofp.OfpOxmOfbField{
920 fd.InPort(downstreamPorts[0].PortNo),
921 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
922 },
923 Actions: []*ofp.OfpAction{
924 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
khenaidoo19d7b632018-10-30 10:49:50 -0400925 fd.Output(upstreamPorts[0].PortNo),
khenaidoo89b0e942018-10-21 21:11:33 -0400926 },
927 }
928 fg.AddFlow(fd.MkFlowStat(fa))
929
930 fa = &fu.FlowArgs{
931 KV: fu.OfpFlowModArgs{"priority": 500},
932 MatchFields: []*ofp.OfpOxmOfbField{
933 fd.InPort(downstreamPorts[0].PortNo),
934 fd.VlanVid(0),
935 },
936 Actions: []*ofp.OfpAction{
937 fd.PushVlan(0x8100),
938 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
939 fd.Output(upstreamPorts[0].PortNo),
940 },
941 }
942 fg.AddFlow(fd.MkFlowStat(fa))
943
944 fa = &fu.FlowArgs{
945 KV: fu.OfpFlowModArgs{"priority": 500},
946 MatchFields: []*ofp.OfpOxmOfbField{
947 fd.InPort(upstreamPorts[0].PortNo),
948 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan),
949 },
950 Actions: []*ofp.OfpAction{
951 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
952 fd.Output(downstreamPorts[0].PortNo),
953 },
954 }
955 fg.AddFlow(fd.MkFlowStat(fa))
956
957 return fg
958}
959
960func (agent *LogicalDeviceAgent) generateDefaultRules() *fu.DeviceRules {
961 rules := fu.NewDeviceRules()
962 var ld *voltha.LogicalDevice
963 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400964 if ld, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400965 log.Warnw("no-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
966 return rules
967 }
968
969 deviceNodeIds := agent.deviceGraph.GetDeviceNodeIds()
khenaidooca301322019-01-09 23:06:32 -0500970 for deviceId := range deviceNodeIds {
khenaidoo89b0e942018-10-21 21:11:33 -0400971 if deviceId == ld.RootDeviceId {
972 rules.AddFlowsAndGroup(deviceId, agent.rootDeviceDefaultRules())
973 } else {
974 rules.AddFlowsAndGroup(deviceId, agent.leafDeviceDefaultRules(deviceId))
975 }
976 }
977 return rules
978}
979
980func (agent *LogicalDeviceAgent) GetAllDefaultRules() *fu.DeviceRules {
981 // Get latest
982 var lDevice *voltha.LogicalDevice
983 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400984 if lDevice, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400985 return fu.NewDeviceRules()
986 }
987 if agent.DefaultFlowRules == nil { // Nothing setup yet
khenaidoo19d7b632018-10-30 10:49:50 -0400988 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
khenaidoo89b0e942018-10-21 21:11:33 -0400989 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
990 agent.DefaultFlowRules = agent.generateDefaultRules()
991 }
992 return agent.DefaultFlowRules
993}
994
995func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
996 lPorts := make([]uint32, 0)
997 var exclPort uint32
998 if len(excludePort) == 1 {
999 exclPort = excludePort[0]
1000 }
khenaidoo19d7b632018-10-30 10:49:50 -04001001 if lDevice, _ := agent.GetLogicalDevice(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -04001002 for _, port := range lDevice.Ports {
1003 if port.OfpPort.PortNo != exclPort {
1004 lPorts = append(lPorts, port.OfpPort.PortNo)
1005 }
1006 }
1007 }
1008 return lPorts
1009}
khenaidoo19d7b632018-10-30 10:49:50 -04001010
1011func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
1012 return agent.deviceGraph
1013}
1014
1015//setupDeviceGraph creates the device graph if not done already
1016func (agent *LogicalDeviceAgent) setupDeviceGraph() {
1017 if agent.deviceGraph == nil {
1018 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
1019 agent.updateRoutes()
1020 }
1021}
1022
1023func (agent *LogicalDeviceAgent) flowTableUpdated(args ...interface{}) interface{} {
1024 log.Debugw("flowTableUpdated-callback", log.Fields{"argsLen": len(args)})
1025
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001026 var previousData *ofp.Flows
1027 var latestData *ofp.Flows
khenaidoo19d7b632018-10-30 10:49:50 -04001028
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001029 var ok bool
1030 if previousData, ok = args[0].(*ofp.Flows); !ok {
1031 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1032 }
1033 if latestData, ok = args[1].(*ofp.Flows); !ok {
1034 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1035 }
khenaidoo19d7b632018-10-30 10:49:50 -04001036
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001037 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1038 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001039 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001040 }
1041
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001042 var groups *ofp.FlowGroups
1043 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1044 groups = lDevice.FlowGroups
1045 log.Debugw("flowsinfo", log.Fields{"flows": latestData, "groups": groups})
1046 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *latestData, *groups)
1047 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1048
khenaidooca301322019-01-09 23:06:32 -05001049 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001050 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001051 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1052 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1053 }
1054 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1055 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1056 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001057 }
khenaidoo19d7b632018-10-30 10:49:50 -04001058
khenaidoo19d7b632018-10-30 10:49:50 -04001059 return nil
1060}
1061
1062func (agent *LogicalDeviceAgent) groupTableUpdated(args ...interface{}) interface{} {
1063 log.Debugw("groupTableUpdated-callback", log.Fields{"argsLen": len(args)})
1064
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001065 var previousData *ofp.FlowGroups
1066 var latestData *ofp.FlowGroups
khenaidoo19d7b632018-10-30 10:49:50 -04001067
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001068 var ok bool
1069 if previousData, ok = args[0].(*ofp.FlowGroups); !ok {
1070 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1071 }
1072 if latestData, ok = args[1].(*ofp.FlowGroups); !ok {
1073 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1074 }
khenaidoo19d7b632018-10-30 10:49:50 -04001075
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001076 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1077 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001078 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001079 }
1080
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001081 var flows *ofp.Flows
1082 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1083 flows = lDevice.Flows
1084 log.Debugw("groupsinfo", log.Fields{"groups": latestData, "flows": flows})
1085 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *flows, *latestData)
1086 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidooca301322019-01-09 23:06:32 -05001087 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001088 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001089 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1090 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1091 }
1092 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1093 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1094 }
khenaidoo19d7b632018-10-30 10:49:50 -04001095
khenaidooca301322019-01-09 23:06:32 -05001096 }
khenaidoo19d7b632018-10-30 10:49:50 -04001097 return nil
1098}
khenaidoofdbad6e2018-11-06 22:26:38 -05001099
khenaidoofc1314d2019-03-14 09:34:21 -04001100// portAdded is a callback invoked when a port is added to the logical device.
1101// TODO: To use when POST_ADD is fixed.
1102func (agent *LogicalDeviceAgent) portAdded(args ...interface{}) interface{} {
1103 log.Debugw("portAdded-callback", log.Fields{"argsLen": len(args)})
1104
1105 var port *voltha.LogicalPort
1106
1107 // Sanity check
1108 if args[0] != nil {
1109 log.Warnw("previous-data-not-nil", log.Fields{"args0": args[0]})
1110 }
1111 var ok bool
1112 if port, ok = args[1].(*voltha.LogicalPort); !ok {
1113 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1114 return nil
1115 }
1116
1117 // Set the proxy and callback for that port
1118 agent.portProxiesLock.Lock()
1119 agent.portProxies[port.Id] = agent.clusterDataProxy.Root.CreateProxy(
1120 fmt.Sprintf("/logical_devices/%s/ports/%s", agent.logicalDeviceId, port.Id),
1121 false)
1122 agent.portProxies[port.Id].RegisterCallback(model.POST_UPDATE, agent.portUpdated)
1123 agent.portProxiesLock.Unlock()
1124
1125 // Send the port change event to the OF controller
1126 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1127 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_ADD, Desc:port.OfpPort})
1128
1129 return nil
1130}
1131
1132// portRemoved is a callback invoked when a port is removed from the logical device.
1133// TODO: To use when POST_ADD is fixed.
1134func (agent *LogicalDeviceAgent) portRemoved(args ...interface{}) interface{} {
1135 log.Debugw("portRemoved-callback", log.Fields{"argsLen": len(args)})
1136
1137 var port *voltha.LogicalPort
1138
1139 // Sanity check
1140 if args[1] != nil {
1141 log.Warnw("data-not-nil", log.Fields{"args1": args[1]})
1142 }
1143 var ok bool
1144 if port, ok = args[0].(*voltha.LogicalPort); !ok {
1145 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1146 return nil
1147 }
1148
1149 // Remove the proxy and callback for that port
1150 agent.portProxiesLock.Lock()
1151 agent.portProxies[port.Id].UnregisterCallback(model.POST_UPDATE, agent.portUpdated)
1152 delete(agent.portProxies, port.Id)
1153 agent.portProxiesLock.Unlock()
1154
1155 // Send the port change event to the OF controller
1156 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1157 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_DELETE, Desc:port.OfpPort})
1158
1159 return nil
1160}
1161
1162// diff go over two lists of logical ports and return what's new, what's changed and what's removed.
1163func diff(oldList , newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
1164 newPorts = make([]*voltha.LogicalPort, 0)
1165 changedPorts = make([]*voltha.LogicalPort, 0)
1166 deletedPorts = make([]*voltha.LogicalPort, 0)
1167 for _, o := range oldList {
1168 found := false
1169 changed := false
1170 for _, n := range newList {
1171 if o.Id == n.Id {
1172 changed = !reflect.DeepEqual(o, n)
1173 found = true
1174 break
1175 }
1176 }
1177 if !found {
1178 deletedPorts = append(deletedPorts, o)
1179 }
1180 if changed {
1181 changedPorts = append(changedPorts, o)
1182 }
1183 }
1184 for _, n := range newList {
1185 found := false
1186 for _, o := range oldList {
1187 if o.Id == n.Id {
1188 found = true
1189 break
1190 }
1191 }
1192 if !found {
1193 newPorts = append(newPorts, n)
1194 }
1195 }
1196 return
1197}
1198
1199// portUpdated is invoked when a port is updated on the logical device. Until
1200// the POST_ADD notification is fixed, we will use the logical device to
1201// update that data.
1202func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1203 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1204
1205 var oldLD *voltha.LogicalDevice
1206 var newlD *voltha.LogicalDevice
1207
1208 var ok bool
1209 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1210 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1211 return nil
1212 }
1213 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1214 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1215 return nil
1216 }
1217
1218 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1219 log.Debug("ports-have-not-changed")
1220 return nil
1221 }
1222
1223 // Get the difference between the two list
1224 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1225
1226 // Send the port change events to the OF controller
1227 for _, new := range newPorts {
1228 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1229 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_ADD, Desc:new.OfpPort})
1230 }
1231 for _, change := range changedPorts {
1232 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1233 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_MODIFY, Desc:change.OfpPort})
1234 }
1235 for _, del := range deletedPorts {
1236 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1237 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_DELETE, Desc:del.OfpPort})
1238 }
1239
1240 return nil
1241}
1242
1243
1244func (agent *LogicalDeviceAgent) addNNILogicalPort (device *voltha.Device, port *voltha.Port) error {
1245 log.Infow("addNNILogicalPort", log.Fields{"NNI": port})
1246 if agent.portExist(device, port) {
1247 log.Debugw("port-already-exist", log.Fields{"port": port})
1248 return nil
1249 }
1250 var portCap *ic.PortCapability
1251 var err error
1252 // First get the port capability
1253 if portCap, err = agent.deviceMgr.getPortCapability(nil, device.Id, port.PortNo); err != nil {
1254 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
1255 return err
1256 }
1257 portCap.Port.RootPort = true
1258 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1259 lp.DeviceId = device.Id
1260 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1261 lp.OfpPort.PortNo = port.PortNo
1262 lp.OfpPort.Name = lp.Id
1263 lp.DevicePortNo = port.PortNo
1264
1265 agent.lockLogicalDevice.Lock()
1266 defer agent.lockLogicalDevice.Unlock()
1267 var ld *voltha.LogicalDevice
1268 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1269 log.Errorw("error-retrieving-logical-device", log.Fields{"error": err})
1270 return err
1271 }
1272 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1273 if cloned.Ports == nil {
1274 cloned.Ports = make([]*voltha.LogicalPort, 0)
1275 }
1276 cloned.Ports = append(cloned.Ports, lp)
1277
1278 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1279 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
1280 return err
1281 }
1282 return nil
1283}
1284
1285func (agent *LogicalDeviceAgent) portExist (device *voltha.Device, port *voltha.Port) bool {
1286 if ldevice, _ := agent.GetLogicalDevice(); ldevice != nil {
1287 for _, lPort := range ldevice.Ports {
1288 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo {
1289 if lPort.OfpPort != nil && device.ProxyAddress != nil {
1290 return lPort.OfpPort.PortNo == device.ProxyAddress.ChannelId
1291 } else if lPort.OfpPort != nil || device.ProxyAddress != nil {
1292 return false
1293 }
1294 return true
1295 }
1296 }
1297 }
1298 return false
1299}
1300
1301func (agent *LogicalDeviceAgent) addUNILogicalPort (childDevice *voltha.Device, port *voltha.Port) error {
1302 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
1303 if agent.portExist(childDevice, port) {
1304 log.Debugw("port-already-exist", log.Fields{"port": port})
1305 return nil
1306 }
1307 var portCap *ic.PortCapability
1308 var err error
1309 // First get the port capability
1310 if portCap, err = agent.deviceMgr.getPortCapability(nil, childDevice.Id, port.PortNo); err != nil {
1311 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
1312 return err
1313 }
1314 agent.lockLogicalDevice.Lock()
1315 defer agent.lockLogicalDevice.Unlock()
1316 // Get stored logical device
1317 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
1318 return status.Error(codes.NotFound, agent.logicalDeviceId)
1319 } else {
1320 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1321 portCap.Port.RootPort = false
1322 //TODO: For now use the channel id assigned by the OLT as logical port number
1323 lPortNo := childDevice.ProxyAddress.ChannelId
1324 portCap.Port.Id = fmt.Sprintf("uni-%d", lPortNo)
1325 portCap.Port.OfpPort.PortNo = lPortNo
1326 portCap.Port.OfpPort.Name = portCap.Port.Id
1327 portCap.Port.DeviceId = childDevice.Id
1328 portCap.Port.DevicePortNo = port.PortNo
1329 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1330 if cloned.Ports == nil {
1331 cloned.Ports = make([]*voltha.LogicalPort, 0)
1332 }
1333 cloned.Ports = append(cloned.Ports, portCap.Port)
1334 return agent.updateLogicalDeviceWithoutLock(cloned)
1335 }
1336}
1337
khenaidoo43c82122018-11-22 18:38:28 -05001338func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
khenaidoofdbad6e2018-11-06 22:26:38 -05001339 log.Debugw("packet-out", log.Fields{"packet": packet.GetInPort()})
1340 outPort := fd.GetPacketOutPort(packet)
1341 //frame := packet.GetData()
1342 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001343 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
1344 log.Error("packetout-failed", log.Fields{"logicalDeviceID":agent.rootDeviceId})
1345 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001346}
1347
khenaidoo297cd252019-02-07 22:10:23 -05001348func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionId string, packet []byte) {
1349 log.Debugw("packet-in", log.Fields{"port": port, "packet": packet, "transactionId": transactionId})
khenaidooca301322019-01-09 23:06:32 -05001350 packetIn := fd.MkPacketIn(port, packet)
khenaidoo297cd252019-02-07 22:10:23 -05001351 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, transactionId, packetIn)
khenaidooca301322019-01-09 23:06:32 -05001352 log.Debugw("sending-packet-in", log.Fields{"packet-in": packetIn})
khenaidoofdbad6e2018-11-06 22:26:38 -05001353}