blob: a8e6a708f7044a2038cafb6ed47785787c4918bd [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")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400171 agent.lockLogicalDevice.RLock()
172 defer agent.lockLogicalDevice.RUnlock()
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) {
khenaidoo1ce37ad2019-03-24 22:07:24 -0400181 log.Debug("ListLogicalDevicePorts")
182 agent.lockLogicalDevice.RLock()
183 defer agent.lockLogicalDevice.RUnlock()
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")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400198 agent.lockLogicalDevice.RLock()
199 defer agent.lockLogicalDevice.RUnlock()
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")
khenaidoo1ce37ad2019-03-24 22:07:24 -0400210 agent.lockLogicalDevice.RLock()
211 defer agent.lockLogicalDevice.RUnlock()
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 {
khenaidoo1ce37ad2019-03-24 22:07:24 -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 err error
272
273 var device *voltha.Device
274 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
275 log.Errorw("error-retrieving-device", log.Fields{"error": err, "deviceId": device.Id})
276 return err
277 }
278
279 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400280 changesMade := false
281 for _, port := range device.Ports {
282 if port.Type == voltha.Port_ETHERNET_NNI {
283 if err = agent.addNNILogicalPort(device, port); err != nil {
284 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
285 } else {
286 changesMade = true
287 }
khenaidoofc1314d2019-03-14 09:34:21 -0400288 }
289 }
290 if changesMade {
291 go agent.setupDeviceGraph()
292 }
293 return err
294}
295
296
297// setupUNILogicalPorts creates a UNI port on the logical device that represents a child UNI interface
298func (agent *LogicalDeviceAgent) setupUNILogicalPorts(ctx context.Context, childDevice *voltha.Device) error {
299 log.Infow("setupUNILogicalPort-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
300 // Build the logical device based on information retrieved from the device adapter
khenaidoob9203542018-09-17 22:56:37 -0400301 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400302
303 //Get UNI port number
khenaidoofc1314d2019-03-14 09:34:21 -0400304 changesMade := false
khenaidoo19d7b632018-10-30 10:49:50 -0400305 for _, port := range childDevice.Ports {
306 if port.Type == voltha.Port_ETHERNET_UNI {
khenaidoofc1314d2019-03-14 09:34:21 -0400307 if err = agent.addUNILogicalPort(childDevice, port); err != nil {
308 log.Errorw("error-adding-UNI-port", log.Fields{"error": err})
309 } else {
310 changesMade = true
311 }
khenaidoo19d7b632018-10-30 10:49:50 -0400312 }
313 }
khenaidoofc1314d2019-03-14 09:34:21 -0400314 if changesMade {
315 go agent.setupDeviceGraph()
khenaidoob9203542018-09-17 22:56:37 -0400316 }
khenaidoofc1314d2019-03-14 09:34:21 -0400317 return err
khenaidoo92e62c52018-10-03 14:02:54 -0400318}
319
320//updateLogicalDeviceWithoutLock updates the model with the logical device. It clones the logicaldevice before saving it
321func (agent *LogicalDeviceAgent) updateLogicalDeviceWithoutLock(logicalDevice *voltha.LogicalDevice) error {
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500322 afterUpdate := agent.clusterDataProxy.Update("/logical_devices/"+agent.logicalDeviceId, logicalDevice, false, "")
khenaidoo92e62c52018-10-03 14:02:54 -0400323 if afterUpdate == nil {
324 return status.Errorf(codes.Internal, "failed-updating-logical-device:%s", agent.logicalDeviceId)
325 }
326 return nil
327}
328
khenaidoo19d7b632018-10-30 10:49:50 -0400329//updateFlowTable updates the flow table of that logical device
330func (agent *LogicalDeviceAgent) updateFlowTable(ctx context.Context, flow *ofp.OfpFlowMod) error {
331 log.Debug("updateFlowTable")
332 if flow == nil {
333 return nil
334 }
335 switch flow.GetCommand() {
336 case ofp.OfpFlowModCommand_OFPFC_ADD:
337 return agent.flowAdd(flow)
338 case ofp.OfpFlowModCommand_OFPFC_DELETE:
339 return agent.flowDelete(flow)
340 case ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT:
341 return agent.flowDeleteStrict(flow)
342 case ofp.OfpFlowModCommand_OFPFC_MODIFY:
343 return agent.flowModify(flow)
344 case ofp.OfpFlowModCommand_OFPFC_MODIFY_STRICT:
345 return agent.flowModifyStrict(flow)
346 }
347 return status.Errorf(codes.Internal,
348 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, flow.GetCommand())
349}
350
351//updateGroupTable updates the group table of that logical device
352func (agent *LogicalDeviceAgent) updateGroupTable(ctx context.Context, groupMod *ofp.OfpGroupMod) error {
353 log.Debug("updateGroupTable")
354 if groupMod == nil {
355 return nil
356 }
357 switch groupMod.GetCommand() {
358 case ofp.OfpGroupModCommand_OFPGC_ADD:
359 return agent.groupAdd(groupMod)
360 case ofp.OfpGroupModCommand_OFPGC_DELETE:
361 return agent.groupDelete(groupMod)
362 case ofp.OfpGroupModCommand_OFPGC_MODIFY:
363 return agent.groupModify(groupMod)
364 }
365 return status.Errorf(codes.Internal,
366 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceId, groupMod.GetCommand())
367}
368
khenaidoo19d7b632018-10-30 10:49:50 -0400369//updateFlowGroupsWithoutLock updates the flows in the logical device without locking the logical device. This function
370//must only be called by a function that is holding the lock on the logical device
371func (agent *LogicalDeviceAgent) updateFlowGroupsWithoutLock(groups []*ofp.OfpGroupEntry) error {
khenaidoo43c82122018-11-22 18:38:28 -0500372 groupsCloned := make([]*ofp.OfpGroupEntry, len(groups))
373 copy(groupsCloned, groups)
374 if afterUpdate := agent.groupProxy.Update("/", groupsCloned, true, ""); afterUpdate == nil {
375 return errors.New(fmt.Sprintf("update-flow-group-failed:%s", agent.logicalDeviceId))
khenaidoo19d7b632018-10-30 10:49:50 -0400376 }
khenaidoo43c82122018-11-22 18:38:28 -0500377 return nil
khenaidoo19d7b632018-10-30 10:49:50 -0400378}
379
380//flowAdd adds a flow to the flow table of that logical device
381func (agent *LogicalDeviceAgent) flowAdd(mod *ofp.OfpFlowMod) error {
382 log.Debug("flowAdd")
383 if mod == nil {
384 return nil
385 }
khenaidoo92e62c52018-10-03 14:02:54 -0400386 agent.lockLogicalDevice.Lock()
387 defer agent.lockLogicalDevice.Unlock()
khenaidoo19d7b632018-10-30 10:49:50 -0400388
389 var lDevice *voltha.LogicalDevice
390 var err error
391 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
392 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
393 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
394 }
395
396 var flows []*ofp.OfpFlowStats
397 if lDevice.Flows != nil && lDevice.Flows.Items != nil {
398 flows = lDevice.Flows.Items
399 }
400
khenaidoo43c82122018-11-22 18:38:28 -0500401 //oldData := proto.Clone(lDevice.Flows).(*voltha.Flows)
khenaidoo19d7b632018-10-30 10:49:50 -0400402 changed := false
403 checkOverlap := (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_CHECK_OVERLAP)) != 0
404 if checkOverlap {
405 if overlapped := fu.FindOverlappingFlows(flows, mod); len(overlapped) != 0 {
406 // TODO: should this error be notified other than being logged?
407 log.Warnw("overlapped-flows", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
408 } else {
409 // Add flow
410 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
411 flows = append(flows, flow)
412 changed = true
413 }
414 } else {
415 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
416 idx := fu.FindFlows(flows, flow)
417 if idx >= 0 {
418 oldFlow := flows[idx]
419 if (mod.Flags & uint32(ofp.OfpFlowModFlags_OFPFF_RESET_COUNTS)) != 0 {
420 flow.ByteCount = oldFlow.ByteCount
421 flow.PacketCount = oldFlow.PacketCount
422 }
423 flows[idx] = flow
424 } else {
425 flows = append(flows, flow)
426 }
427 changed = true
428 }
429 if changed {
430 // Update model
khenaidoo43c82122018-11-22 18:38:28 -0500431 flowsToUpdate := &ofp.Flows{}
432 if lDevice.Flows != nil {
433 flowsToUpdate = &ofp.Flows{Items: flows}
khenaidoo19d7b632018-10-30 10:49:50 -0400434 }
khenaidoo43c82122018-11-22 18:38:28 -0500435 if err := agent.updateLogicalDeviceFlowsWithoutLock(flowsToUpdate); err != nil {
436 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400437 return err
438 }
439 }
khenaidoo19d7b632018-10-30 10:49:50 -0400440 return nil
441}
442
443//flowDelete deletes a flow from the flow table of that logical device
444func (agent *LogicalDeviceAgent) flowDelete(mod *ofp.OfpFlowMod) error {
445 log.Debug("flowDelete")
446 if mod == nil {
447 return nil
448 }
449 agent.lockLogicalDevice.Lock()
450 defer agent.lockLogicalDevice.Unlock()
451
452 var lDevice *voltha.LogicalDevice
453 var err error
454 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
455 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
456 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
457 }
458 flows := lDevice.Flows.Items
459
460 //build a list of what to keep vs what to delete
461 toKeep := make([]*ofp.OfpFlowStats, 0)
462 for _, f := range flows {
463 if !fu.FlowMatchesMod(f, mod) {
464 toKeep = append(toKeep, f)
465 }
466 }
467
468 //Update flows
469 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500470 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
471 log.Errorw("Cannot-update-flows", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400472 return err
473 }
474 }
475
476 //TODO: send announcement on delete
477 return nil
478}
479
480//flowStatsDelete deletes a flow from the flow table of that logical device
481func (agent *LogicalDeviceAgent) flowStatsDelete(flow *ofp.OfpFlowStats) error {
482 log.Debug("flowStatsDelete")
483 if flow == nil {
484 return nil
485 }
486 agent.lockLogicalDevice.Lock()
487 defer agent.lockLogicalDevice.Unlock()
488
489 var lDevice *voltha.LogicalDevice
490 var err error
491 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
492 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
493 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
494 }
495 flows := lDevice.Flows.Items
496
497 //build a list of what to keep vs what to delete
498 toKeep := make([]*ofp.OfpFlowStats, 0)
499 for _, f := range flows {
500 if !fu.FlowMatch(f, flow) {
501 toKeep = append(toKeep, f)
502 }
503 }
504
505 //Update flows
506 if len(toKeep) < len(flows) {
khenaidoo43c82122018-11-22 18:38:28 -0500507 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: toKeep}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400508 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
509 return err
510 }
511 }
512 return nil
513}
514
515//flowDeleteStrict deletes a flow from the flow table of that logical device
516func (agent *LogicalDeviceAgent) flowDeleteStrict(mod *ofp.OfpFlowMod) error {
517 log.Debug("flowDeleteStrict")
518 if mod == nil {
519 return nil
520 }
521 agent.lockLogicalDevice.Lock()
522 defer agent.lockLogicalDevice.Unlock()
523
524 var lDevice *voltha.LogicalDevice
525 var err error
526 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
527 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
528 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
529 }
530 flows := lDevice.Flows.Items
531 changed := false
532 flow := fd.FlowStatsEntryFromFlowModMessage(mod)
533 idx := fu.FindFlows(flows, flow)
534 if idx >= 0 {
535 flows = append(flows[:idx], flows[idx+1:]...)
536 changed = true
537 } else {
538 return errors.New(fmt.Sprintf("Cannot delete flow - %s", flow))
539 }
540
541 if changed {
khenaidoo43c82122018-11-22 18:38:28 -0500542 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400543 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
544 return err
545 }
546 }
547
548 return nil
549}
550
551//flowModify modifies a flow from the flow table of that logical device
552func (agent *LogicalDeviceAgent) flowModify(mod *ofp.OfpFlowMod) error {
553 return errors.New("flowModify not implemented")
554}
555
556//flowModifyStrict deletes a flow from the flow table of that logical device
557func (agent *LogicalDeviceAgent) flowModifyStrict(mod *ofp.OfpFlowMod) error {
558 return errors.New("flowModifyStrict not implemented")
559}
560
561func (agent *LogicalDeviceAgent) groupAdd(groupMod *ofp.OfpGroupMod) error {
562 log.Debug("groupAdd")
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
khenaidoo19d7b632018-10-30 10:49:50 -0400576 if fu.FindGroup(groups, groupMod.GroupId) == -1 {
577 groups = append(groups, fd.GroupEntryFromGroupMod(groupMod))
khenaidoo43c82122018-11-22 18:38:28 -0500578 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
579 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400580 return err
581 }
582 } else {
583 return errors.New(fmt.Sprintf("Groups %d already present", groupMod.GroupId))
584 }
khenaidoo19d7b632018-10-30 10:49:50 -0400585 return nil
586}
587
588func (agent *LogicalDeviceAgent) groupDelete(groupMod *ofp.OfpGroupMod) error {
589 log.Debug("groupDelete")
590 if groupMod == nil {
591 return nil
592 }
593 agent.lockLogicalDevice.Lock()
594 defer agent.lockLogicalDevice.Unlock()
595
596 var lDevice *voltha.LogicalDevice
597 var err error
598 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
599 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
600 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
601 }
602 groups := lDevice.FlowGroups.Items
603 flows := lDevice.Flows.Items
604 groupsChanged := false
605 flowsChanged := false
606 groupId := groupMod.GroupId
607 if groupId == uint32(ofp.OfpGroup_OFPG_ALL) {
608 //TODO we must delete all flows that point to this group and
609 //signal controller as requested by flow's flag
610 groups = []*ofp.OfpGroupEntry{}
611 groupsChanged = true
612 } else {
613 if idx := fu.FindGroup(groups, groupId); idx == -1 {
614 return nil // Valid case
615 } else {
616 flowsChanged, flows = fu.FlowsDeleteByGroupId(flows, groupId)
617 groups = append(groups[:idx], groups[idx+1:]...)
618 groupsChanged = true
619 }
620 }
khenaidoo43c82122018-11-22 18:38:28 -0500621 if groupsChanged {
622 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
623 log.Errorw("Cannot-update-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
khenaidoo19d7b632018-10-30 10:49:50 -0400624 return err
625 }
626 }
khenaidoo43c82122018-11-22 18:38:28 -0500627 if flowsChanged {
628 if err := agent.updateLogicalDeviceFlowsWithoutLock(&ofp.Flows{Items: flows}); err != nil {
629 log.Errorw("Cannot-update-flow", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
630 return err
631 }
632 }
633
khenaidoo19d7b632018-10-30 10:49:50 -0400634 return nil
635}
636
637func (agent *LogicalDeviceAgent) groupModify(groupMod *ofp.OfpGroupMod) error {
638 log.Debug("groupModify")
639 if groupMod == nil {
640 return nil
641 }
642 agent.lockLogicalDevice.Lock()
643 defer agent.lockLogicalDevice.Unlock()
644
645 var lDevice *voltha.LogicalDevice
646 var err error
647 if lDevice, err = agent.getLogicalDeviceWithoutLock(); err != nil {
648 log.Errorw("no-logical-device-present", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
649 return errors.New(fmt.Sprintf("no-logical-device-present:%s", agent.logicalDeviceId))
650 }
651 groups := lDevice.FlowGroups.Items
652 groupsChanged := false
653 groupId := groupMod.GroupId
654 if idx := fu.FindGroup(groups, groupId); idx == -1 {
khenaidooca301322019-01-09 23:06:32 -0500655 return errors.New(fmt.Sprintf("group-absent:%d", groupId))
khenaidoo19d7b632018-10-30 10:49:50 -0400656 } else {
657 //replace existing group entry with new group definition
658 groupEntry := fd.GroupEntryFromGroupMod(groupMod)
659 groups[idx] = groupEntry
660 groupsChanged = true
661 }
662 if groupsChanged {
khenaidoo43c82122018-11-22 18:38:28 -0500663 //lDevice.FlowGroups.Items = groups
664 if err := agent.updateLogicalDeviceFlowGroupsWithoutLock(&ofp.FlowGroups{Items: groups}); err != nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400665 log.Errorw("Cannot-update-logical-group", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
666 return err
667 }
668 }
669 return nil
670}
671
672// deleteLogicalPort removes the logical port
673func (agent *LogicalDeviceAgent) deleteLogicalPort(lPort *voltha.LogicalPort) error {
674 agent.lockLogicalDevice.Lock()
675 defer agent.lockLogicalDevice.Unlock()
676
khenaidoo92e62c52018-10-03 14:02:54 -0400677 // Get the most up to date logical device
678 var logicaldevice *voltha.LogicalDevice
679 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
khenaidoo19d7b632018-10-30 10:49:50 -0400680 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
khenaidoob9203542018-09-17 22:56:37 -0400681 return nil
682 }
khenaidoo92e62c52018-10-03 14:02:54 -0400683 index := -1
684 for i, logicalPort := range logicaldevice.Ports {
khenaidoo19d7b632018-10-30 10:49:50 -0400685 if logicalPort.Id == lPort.Id {
khenaidoo92e62c52018-10-03 14:02:54 -0400686 index = i
687 break
688 }
689 }
690 if index >= 0 {
691 copy(logicaldevice.Ports[index:], logicaldevice.Ports[index+1:])
692 logicaldevice.Ports[len(logicaldevice.Ports)-1] = nil
693 logicaldevice.Ports = logicaldevice.Ports[:len(logicaldevice.Ports)-1]
694 log.Debugw("logical-port-deleted", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
695 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
696 }
697 return nil
khenaidoob9203542018-09-17 22:56:37 -0400698}
699
khenaidoo19d7b632018-10-30 10:49:50 -0400700// enableLogicalPort enables the logical port
701func (agent *LogicalDeviceAgent) enableLogicalPort(lPort *voltha.LogicalPort) error {
702 agent.lockLogicalDevice.Lock()
703 defer agent.lockLogicalDevice.Unlock()
704
705 // Get the most up to date logical device
706 var logicaldevice *voltha.LogicalDevice
707 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
708 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
709 return nil
710 }
711 index := -1
712 for i, logicalPort := range logicaldevice.Ports {
713 if logicalPort.Id == lPort.Id {
714 index = i
715 break
716 }
717 }
718 if index >= 0 {
719 logicaldevice.Ports[index].OfpPort.Config = logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
720 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
721 }
722 //TODO: Trigger subsequent actions on the device
723 return nil
724}
725
726// disableLogicalPort disabled the logical port
727func (agent *LogicalDeviceAgent) disableLogicalPort(lPort *voltha.LogicalPort) error {
728 agent.lockLogicalDevice.Lock()
729 defer agent.lockLogicalDevice.Unlock()
730
731 // Get the most up to date logical device
732 var logicaldevice *voltha.LogicalDevice
733 if logicaldevice, _ = agent.getLogicalDeviceWithoutLock(); logicaldevice == nil {
734 log.Debugw("no-logical-device", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "logicalPortId": lPort.Id})
735 return nil
736 }
737 index := -1
738 for i, logicalPort := range logicaldevice.Ports {
739 if logicalPort.Id == lPort.Id {
740 index = i
741 break
742 }
743 }
744 if index >= 0 {
745 logicaldevice.Ports[index].OfpPort.Config = (logicaldevice.Ports[index].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)) | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
746 return agent.updateLogicalDeviceWithoutLock(logicaldevice)
747 }
748 //TODO: Trigger subsequent actions on the device
749 return nil
750}
751
khenaidoo89b0e942018-10-21 21:11:33 -0400752func isNNIPort(portNo uint32, nniPortsNo []uint32) bool {
753 for _, pNo := range nniPortsNo {
754 if pNo == portNo {
755 return true
756 }
757 }
758 return false
759}
khenaidoo4d4802d2018-10-04 21:59:49 -0400760
khenaidoo89b0e942018-10-21 21:11:33 -0400761func (agent *LogicalDeviceAgent) getPreCalculatedRoute(ingress, egress uint32) []graph.RouteHop {
khenaidoo19d7b632018-10-30 10:49:50 -0400762 log.Debugw("ROUTE", log.Fields{"len": len(agent.deviceGraph.Routes)})
khenaidoo89b0e942018-10-21 21:11:33 -0400763 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400764 log.Debugw("ROUTELINKS", log.Fields{"ingress": ingress, "egress": egress, "routelink": routeLink})
khenaidoo89b0e942018-10-21 21:11:33 -0400765 if ingress == routeLink.Ingress && egress == routeLink.Egress {
766 return route
767 }
768 }
769 log.Warnw("no-route", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "ingress": ingress, "egress": egress})
770 return nil
771}
772
khenaidoo19d7b632018-10-30 10:49:50 -0400773func (agent *LogicalDeviceAgent) GetRoute(ingressPortNo uint32, egressPortNo uint32) []graph.RouteHop {
khenaidoo89b0e942018-10-21 21:11:33 -0400774 log.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
775 // Get the updated logical device
khenaidoo79232702018-12-04 11:00:41 -0500776 var ld *ic.LogicalDevice
khenaidoo89b0e942018-10-21 21:11:33 -0400777 routes := make([]graph.RouteHop, 0)
778 var err error
779 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
780 return nil
781 }
782 nniLogicalPortsNo := make([]uint32, 0)
783 for _, logicalPort := range ld.Ports {
784 if logicalPort.RootPort {
785 nniLogicalPortsNo = append(nniLogicalPortsNo, logicalPort.OfpPort.PortNo)
786 }
787 }
788 if len(nniLogicalPortsNo) == 0 {
789 log.Errorw("no-nni-ports", log.Fields{"LogicalDeviceId": ld.Id})
790 return nil
791 }
khenaidoo19d7b632018-10-30 10:49:50 -0400792 // Note: A port value of 0 is equivalent to a nil port
793
khenaidoo89b0e942018-10-21 21:11:33 -0400794 // Consider different possibilities
khenaidoo19d7b632018-10-30 10:49:50 -0400795 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
khenaidoo89b0e942018-10-21 21:11:33 -0400796 log.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
khenaidoo19d7b632018-10-30 10:49:50 -0400797 if isNNIPort(ingressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400798 log.Debug("returning-half-route")
799 //This is a trap on the NNI Port
800 //Return a 'half' route to make the flow decomposer logic happy
801 for routeLink, route := range agent.deviceGraph.Routes {
802 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
803 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
804 routes = append(routes, route[1])
805 return routes
806 }
807 }
808 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
809 return nil
810 }
811 //treat it as if the output port is the first NNI of the OLT
khenaidoo19d7b632018-10-30 10:49:50 -0400812 egressPortNo = nniLogicalPortsNo[0]
khenaidoo89b0e942018-10-21 21:11:33 -0400813 }
814 //If ingress port is not specified (nil), it may be a wildcarded
815 //route if egress port is OFPP_CONTROLLER or a nni logical port,
816 //in which case we need to create a half-route where only the egress
817 //hop is filled, the first hop is nil
khenaidoo19d7b632018-10-30 10:49:50 -0400818 if ingressPortNo == 0 && isNNIPort(egressPortNo, nniLogicalPortsNo) {
khenaidoo89b0e942018-10-21 21:11:33 -0400819 // We can use the 2nd hop of any upstream route, so just find the first upstream:
820 for routeLink, route := range agent.deviceGraph.Routes {
821 if isNNIPort(routeLink.Egress, nniLogicalPortsNo) {
822 routes = append(routes, graph.RouteHop{}) // first hop is set to empty
823 routes = append(routes, route[1])
824 return routes
825 }
826 }
827 log.Warnw("no-upstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
828 return nil
829 }
830 //If egress port is not specified (nil), we can also can return a "half" route
khenaidoo19d7b632018-10-30 10:49:50 -0400831 if egressPortNo == 0 {
khenaidoo89b0e942018-10-21 21:11:33 -0400832 for routeLink, route := range agent.deviceGraph.Routes {
khenaidoo19d7b632018-10-30 10:49:50 -0400833 if routeLink.Ingress == ingressPortNo {
khenaidoo89b0e942018-10-21 21:11:33 -0400834 routes = append(routes, route[0])
835 routes = append(routes, graph.RouteHop{})
836 return routes
837 }
838 }
839 log.Warnw("no-downstream-route", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "nniPortsNo": nniLogicalPortsNo})
840 return nil
841 }
842
843 // Return the pre-calculated route
khenaidoo19d7b632018-10-30 10:49:50 -0400844 return agent.getPreCalculatedRoute(ingressPortNo, egressPortNo)
khenaidoo89b0e942018-10-21 21:11:33 -0400845}
846
847// updateRoutes updates the device routes whenever there is a device or port changes relevant to this
848// logical device. TODO: Add more heuristics to this process to update the routes where a change has occurred
849// instead of rebuilding the entire set of routes
850func (agent *LogicalDeviceAgent) updateRoutes() {
khenaidoo19d7b632018-10-30 10:49:50 -0400851 if ld, err := agent.GetLogicalDevice(); err == nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400852 agent.deviceGraph.ComputeRoutes(ld.Ports)
853 }
854}
855
856func (agent *LogicalDeviceAgent) rootDeviceDefaultRules() *fu.FlowsAndGroups {
857 return fu.NewFlowsAndGroups()
858}
859
860func (agent *LogicalDeviceAgent) leafDeviceDefaultRules(deviceId string) *fu.FlowsAndGroups {
861 fg := fu.NewFlowsAndGroups()
862 var device *voltha.Device
863 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400864 if device, err = agent.deviceMgr.GetDevice(deviceId); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400865 return fg
866 }
867 //set the upstream and downstream ports
868 upstreamPorts := make([]*voltha.Port, 0)
869 downstreamPorts := make([]*voltha.Port, 0)
870 for _, port := range device.Ports {
871 if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_VENET_ONU {
872 upstreamPorts = append(upstreamPorts, port)
873 } else if port.Type == voltha.Port_ETHERNET_UNI {
874 downstreamPorts = append(downstreamPorts, port)
875 }
876 }
877 //it is possible that the downstream ports are not created, but the flow_decomposition has already
878 //kicked in. In such scenarios, cut short the processing and return.
khenaidoo6d055132019-02-12 16:51:19 -0500879 if len(downstreamPorts) == 0 || len(upstreamPorts) == 0{
khenaidoo89b0e942018-10-21 21:11:33 -0400880 return fg
881 }
882 // set up the default flows
883 var fa *fu.FlowArgs
884 fa = &fu.FlowArgs{
885 KV: fu.OfpFlowModArgs{"priority": 500},
886 MatchFields: []*ofp.OfpOxmOfbField{
887 fd.InPort(downstreamPorts[0].PortNo),
888 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0),
889 },
890 Actions: []*ofp.OfpAction{
891 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
khenaidoo19d7b632018-10-30 10:49:50 -0400892 fd.Output(upstreamPorts[0].PortNo),
khenaidoo89b0e942018-10-21 21:11:33 -0400893 },
894 }
895 fg.AddFlow(fd.MkFlowStat(fa))
896
897 fa = &fu.FlowArgs{
898 KV: fu.OfpFlowModArgs{"priority": 500},
899 MatchFields: []*ofp.OfpOxmOfbField{
900 fd.InPort(downstreamPorts[0].PortNo),
901 fd.VlanVid(0),
902 },
903 Actions: []*ofp.OfpAction{
904 fd.PushVlan(0x8100),
905 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan)),
906 fd.Output(upstreamPorts[0].PortNo),
907 },
908 }
909 fg.AddFlow(fd.MkFlowStat(fa))
910
911 fa = &fu.FlowArgs{
912 KV: fu.OfpFlowModArgs{"priority": 500},
913 MatchFields: []*ofp.OfpOxmOfbField{
914 fd.InPort(upstreamPorts[0].PortNo),
915 fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | device.Vlan),
916 },
917 Actions: []*ofp.OfpAction{
918 fd.SetField(fd.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 0)),
919 fd.Output(downstreamPorts[0].PortNo),
920 },
921 }
922 fg.AddFlow(fd.MkFlowStat(fa))
923
924 return fg
925}
926
927func (agent *LogicalDeviceAgent) generateDefaultRules() *fu.DeviceRules {
928 rules := fu.NewDeviceRules()
929 var ld *voltha.LogicalDevice
930 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400931 if ld, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400932 log.Warnw("no-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
933 return rules
934 }
935
936 deviceNodeIds := agent.deviceGraph.GetDeviceNodeIds()
khenaidooca301322019-01-09 23:06:32 -0500937 for deviceId := range deviceNodeIds {
khenaidoo89b0e942018-10-21 21:11:33 -0400938 if deviceId == ld.RootDeviceId {
939 rules.AddFlowsAndGroup(deviceId, agent.rootDeviceDefaultRules())
940 } else {
941 rules.AddFlowsAndGroup(deviceId, agent.leafDeviceDefaultRules(deviceId))
942 }
943 }
944 return rules
945}
946
947func (agent *LogicalDeviceAgent) GetAllDefaultRules() *fu.DeviceRules {
948 // Get latest
949 var lDevice *voltha.LogicalDevice
950 var err error
khenaidoo19d7b632018-10-30 10:49:50 -0400951 if lDevice, err = agent.GetLogicalDevice(); err != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400952 return fu.NewDeviceRules()
953 }
954 if agent.DefaultFlowRules == nil { // Nothing setup yet
khenaidoo19d7b632018-10-30 10:49:50 -0400955 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
khenaidoo89b0e942018-10-21 21:11:33 -0400956 agent.deviceGraph.ComputeRoutes(lDevice.Ports)
957 agent.DefaultFlowRules = agent.generateDefaultRules()
958 }
959 return agent.DefaultFlowRules
960}
961
962func (agent *LogicalDeviceAgent) GetWildcardInputPorts(excludePort ...uint32) []uint32 {
963 lPorts := make([]uint32, 0)
964 var exclPort uint32
965 if len(excludePort) == 1 {
966 exclPort = excludePort[0]
967 }
khenaidoo19d7b632018-10-30 10:49:50 -0400968 if lDevice, _ := agent.GetLogicalDevice(); lDevice != nil {
khenaidoo89b0e942018-10-21 21:11:33 -0400969 for _, port := range lDevice.Ports {
970 if port.OfpPort.PortNo != exclPort {
971 lPorts = append(lPorts, port.OfpPort.PortNo)
972 }
973 }
974 }
975 return lPorts
976}
khenaidoo19d7b632018-10-30 10:49:50 -0400977
978func (agent *LogicalDeviceAgent) GetDeviceGraph() *graph.DeviceGraph {
979 return agent.deviceGraph
980}
981
982//setupDeviceGraph creates the device graph if not done already
983func (agent *LogicalDeviceAgent) setupDeviceGraph() {
984 if agent.deviceGraph == nil {
985 agent.deviceGraph = graph.NewDeviceGraph(agent.deviceMgr.GetDevice)
986 agent.updateRoutes()
987 }
988}
989
990func (agent *LogicalDeviceAgent) flowTableUpdated(args ...interface{}) interface{} {
991 log.Debugw("flowTableUpdated-callback", log.Fields{"argsLen": len(args)})
992
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500993 var previousData *ofp.Flows
994 var latestData *ofp.Flows
khenaidoo19d7b632018-10-30 10:49:50 -0400995
Stephane Barbarie1ab43272018-12-08 21:42:13 -0500996 var ok bool
997 if previousData, ok = args[0].(*ofp.Flows); !ok {
998 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
999 }
1000 if latestData, ok = args[1].(*ofp.Flows); !ok {
1001 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1002 }
khenaidoo19d7b632018-10-30 10:49:50 -04001003
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001004 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1005 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001006 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001007 }
1008
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001009 var groups *ofp.FlowGroups
1010 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1011 groups = lDevice.FlowGroups
1012 log.Debugw("flowsinfo", log.Fields{"flows": latestData, "groups": groups})
1013 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *latestData, *groups)
1014 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
1015
khenaidooca301322019-01-09 23:06:32 -05001016 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001017 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001018 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1019 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1020 }
1021 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1022 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1023 }
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001024 }
khenaidoo19d7b632018-10-30 10:49:50 -04001025
khenaidoo19d7b632018-10-30 10:49:50 -04001026 return nil
1027}
1028
1029func (agent *LogicalDeviceAgent) groupTableUpdated(args ...interface{}) interface{} {
1030 log.Debugw("groupTableUpdated-callback", log.Fields{"argsLen": len(args)})
1031
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001032 var previousData *ofp.FlowGroups
1033 var latestData *ofp.FlowGroups
khenaidoo19d7b632018-10-30 10:49:50 -04001034
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001035 var ok bool
1036 if previousData, ok = args[0].(*ofp.FlowGroups); !ok {
1037 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1038 }
1039 if latestData, ok = args[1].(*ofp.FlowGroups); !ok {
1040 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1041 }
khenaidoo19d7b632018-10-30 10:49:50 -04001042
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001043 if reflect.DeepEqual(previousData.Items, latestData.Items) {
1044 log.Debug("flow-update-not-required")
khenaidoo19d7b632018-10-30 10:49:50 -04001045 return nil
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001046 }
1047
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001048 var flows *ofp.Flows
1049 lDevice, _ := agent.getLogicalDeviceWithoutLock()
1050 flows = lDevice.Flows
1051 log.Debugw("groupsinfo", log.Fields{"groups": latestData, "flows": flows})
1052 deviceRules := agent.flowDecomposer.DecomposeRules(agent, *flows, *latestData)
1053 log.Debugw("rules", log.Fields{"rules": deviceRules.String()})
khenaidooca301322019-01-09 23:06:32 -05001054 var err error
Stephane Barbarie1ab43272018-12-08 21:42:13 -05001055 for deviceId, value := range deviceRules.GetRules() {
khenaidooca301322019-01-09 23:06:32 -05001056 if err = agent.deviceMgr.updateFlows(deviceId, value.ListFlows()); err != nil {
1057 log.Error("update-flows-failed", log.Fields{"deviceID":deviceId})
1058 }
1059 if err = agent.deviceMgr.updateGroups(deviceId, value.ListGroups()); err != nil {
1060 log.Error("update-groups-failed", log.Fields{"deviceID":deviceId})
1061 }
khenaidoo19d7b632018-10-30 10:49:50 -04001062
khenaidooca301322019-01-09 23:06:32 -05001063 }
khenaidoo19d7b632018-10-30 10:49:50 -04001064 return nil
1065}
khenaidoofdbad6e2018-11-06 22:26:38 -05001066
khenaidoofc1314d2019-03-14 09:34:21 -04001067// portAdded is a callback invoked when a port is added to the logical device.
1068// TODO: To use when POST_ADD is fixed.
1069func (agent *LogicalDeviceAgent) portAdded(args ...interface{}) interface{} {
1070 log.Debugw("portAdded-callback", log.Fields{"argsLen": len(args)})
1071
1072 var port *voltha.LogicalPort
1073
1074 // Sanity check
1075 if args[0] != nil {
1076 log.Warnw("previous-data-not-nil", log.Fields{"args0": args[0]})
1077 }
1078 var ok bool
1079 if port, ok = args[1].(*voltha.LogicalPort); !ok {
1080 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1081 return nil
1082 }
1083
1084 // Set the proxy and callback for that port
1085 agent.portProxiesLock.Lock()
1086 agent.portProxies[port.Id] = agent.clusterDataProxy.Root.CreateProxy(
1087 fmt.Sprintf("/logical_devices/%s/ports/%s", agent.logicalDeviceId, port.Id),
1088 false)
1089 agent.portProxies[port.Id].RegisterCallback(model.POST_UPDATE, agent.portUpdated)
1090 agent.portProxiesLock.Unlock()
1091
1092 // Send the port change event to the OF controller
1093 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1094 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_ADD, Desc:port.OfpPort})
1095
1096 return nil
1097}
1098
1099// portRemoved is a callback invoked when a port is removed from the logical device.
1100// TODO: To use when POST_ADD is fixed.
1101func (agent *LogicalDeviceAgent) portRemoved(args ...interface{}) interface{} {
1102 log.Debugw("portRemoved-callback", log.Fields{"argsLen": len(args)})
1103
1104 var port *voltha.LogicalPort
1105
1106 // Sanity check
1107 if args[1] != nil {
1108 log.Warnw("data-not-nil", log.Fields{"args1": args[1]})
1109 }
1110 var ok bool
1111 if port, ok = args[0].(*voltha.LogicalPort); !ok {
1112 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1113 return nil
1114 }
1115
1116 // Remove the proxy and callback for that port
1117 agent.portProxiesLock.Lock()
1118 agent.portProxies[port.Id].UnregisterCallback(model.POST_UPDATE, agent.portUpdated)
1119 delete(agent.portProxies, port.Id)
1120 agent.portProxiesLock.Unlock()
1121
1122 // Send the port change event to the OF controller
1123 agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1124 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_DELETE, Desc:port.OfpPort})
1125
1126 return nil
1127}
1128
1129// diff go over two lists of logical ports and return what's new, what's changed and what's removed.
1130func diff(oldList , newList []*voltha.LogicalPort) (newPorts, changedPorts, deletedPorts []*voltha.LogicalPort) {
1131 newPorts = make([]*voltha.LogicalPort, 0)
1132 changedPorts = make([]*voltha.LogicalPort, 0)
1133 deletedPorts = make([]*voltha.LogicalPort, 0)
1134 for _, o := range oldList {
1135 found := false
1136 changed := false
1137 for _, n := range newList {
1138 if o.Id == n.Id {
1139 changed = !reflect.DeepEqual(o, n)
1140 found = true
1141 break
1142 }
1143 }
1144 if !found {
1145 deletedPorts = append(deletedPorts, o)
1146 }
1147 if changed {
1148 changedPorts = append(changedPorts, o)
1149 }
1150 }
1151 for _, n := range newList {
1152 found := false
1153 for _, o := range oldList {
1154 if o.Id == n.Id {
1155 found = true
1156 break
1157 }
1158 }
1159 if !found {
1160 newPorts = append(newPorts, n)
1161 }
1162 }
1163 return
1164}
1165
1166// portUpdated is invoked when a port is updated on the logical device. Until
1167// the POST_ADD notification is fixed, we will use the logical device to
1168// update that data.
1169func (agent *LogicalDeviceAgent) portUpdated(args ...interface{}) interface{} {
1170 log.Debugw("portUpdated-callback", log.Fields{"argsLen": len(args)})
1171
1172 var oldLD *voltha.LogicalDevice
1173 var newlD *voltha.LogicalDevice
1174
1175 var ok bool
1176 if oldLD, ok = args[0].(*voltha.LogicalDevice); !ok {
1177 log.Errorw("invalid-args", log.Fields{"args0": args[0]})
1178 return nil
1179 }
1180 if newlD, ok = args[1].(*voltha.LogicalDevice); !ok {
1181 log.Errorw("invalid-args", log.Fields{"args1": args[1]})
1182 return nil
1183 }
1184
1185 if reflect.DeepEqual(oldLD.Ports, newlD.Ports) {
1186 log.Debug("ports-have-not-changed")
1187 return nil
1188 }
1189
1190 // Get the difference between the two list
1191 newPorts, changedPorts, deletedPorts := diff(oldLD.Ports, newlD.Ports)
1192
1193 // Send the port change events to the OF controller
1194 for _, new := range newPorts {
1195 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1196 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_ADD, Desc:new.OfpPort})
1197 }
1198 for _, change := range changedPorts {
1199 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1200 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_MODIFY, Desc:change.OfpPort})
1201 }
1202 for _, del := range deletedPorts {
1203 go agent.ldeviceMgr.grpcNbiHdlr.sendChangeEvent(agent.logicalDeviceId,
1204 &ofp.OfpPortStatus{Reason:ofp.OfpPortReason_OFPPR_DELETE, Desc:del.OfpPort})
1205 }
1206
1207 return nil
1208}
1209
1210
1211func (agent *LogicalDeviceAgent) addNNILogicalPort (device *voltha.Device, port *voltha.Port) error {
khenaidoo1ce37ad2019-03-24 22:07:24 -04001212 log.Debugw("addNNILogicalPort", log.Fields{"NNI": port})
1213 if device.AdminState != voltha.AdminState_ENABLED {
1214 log.Infow("device-not-enabled", log.Fields{"deviceId": device.Id})
khenaidoofc1314d2019-03-14 09:34:21 -04001215 return nil
1216 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001217 agent.lockLogicalDevice.RLock()
1218 if agent.portExist(device, port) {
1219 log.Debugw("port-already-exist", log.Fields{"port": port})
1220 agent.lockLogicalDevice.RUnlock()
1221 return nil
1222 }
1223 agent.lockLogicalDevice.RUnlock()
1224
khenaidoofc1314d2019-03-14 09:34:21 -04001225 var portCap *ic.PortCapability
1226 var err error
1227 // First get the port capability
1228 if portCap, err = agent.deviceMgr.getPortCapability(nil, device.Id, port.PortNo); err != nil {
1229 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
1230 return err
1231 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001232
1233 agent.lockLogicalDevice.Lock()
1234 defer agent.lockLogicalDevice.Unlock()
1235 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1236 if agent.portExist(device, port) {
1237 log.Debugw("port-already-exist", log.Fields{"port": port})
1238 return nil
1239 }
1240
khenaidoofc1314d2019-03-14 09:34:21 -04001241 portCap.Port.RootPort = true
1242 lp := (proto.Clone(portCap.Port)).(*voltha.LogicalPort)
1243 lp.DeviceId = device.Id
1244 lp.Id = fmt.Sprintf("nni-%d", port.PortNo)
1245 lp.OfpPort.PortNo = port.PortNo
1246 lp.OfpPort.Name = lp.Id
1247 lp.DevicePortNo = port.PortNo
1248
khenaidoofc1314d2019-03-14 09:34:21 -04001249 var ld *voltha.LogicalDevice
1250 if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
1251 log.Errorw("error-retrieving-logical-device", log.Fields{"error": err})
1252 return err
1253 }
1254 cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
1255 if cloned.Ports == nil {
1256 cloned.Ports = make([]*voltha.LogicalPort, 0)
1257 }
1258 cloned.Ports = append(cloned.Ports, lp)
1259
1260 if err = agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
1261 log.Errorw("error-updating-logical-device", log.Fields{"error": err})
1262 return err
1263 }
1264 return nil
1265}
1266
1267func (agent *LogicalDeviceAgent) portExist (device *voltha.Device, port *voltha.Port) bool {
khenaidoo54544ae2019-03-18 13:22:39 -04001268 if ldevice, _ := agent.getLogicalDeviceWithoutLock(); ldevice != nil {
khenaidoofc1314d2019-03-14 09:34:21 -04001269 for _, lPort := range ldevice.Ports {
khenaidoo54544ae2019-03-18 13:22:39 -04001270 if lPort.DeviceId == device.Id && lPort.DevicePortNo == port.PortNo && lPort.Id == port.Label {
khenaidoofc1314d2019-03-14 09:34:21 -04001271 return true
1272 }
1273 }
1274 }
1275 return false
1276}
1277
1278func (agent *LogicalDeviceAgent) addUNILogicalPort (childDevice *voltha.Device, port *voltha.Port) error {
1279 log.Debugw("addUNILogicalPort", log.Fields{"port": port})
khenaidoo1ce37ad2019-03-24 22:07:24 -04001280 if childDevice.AdminState != voltha.AdminState_ENABLED {
1281 log.Infow("device-not-enabled", log.Fields{"deviceId": childDevice.Id})
khenaidoofc1314d2019-03-14 09:34:21 -04001282 return nil
1283 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001284 agent.lockLogicalDevice.RLock()
1285 if agent.portExist(childDevice, port) {
1286 log.Debugw("port-already-exist", log.Fields{"port": port})
1287 agent.lockLogicalDevice.RUnlock()
1288 return nil
1289 }
1290 agent.lockLogicalDevice.RUnlock()
khenaidoofc1314d2019-03-14 09:34:21 -04001291 var portCap *ic.PortCapability
1292 var err error
1293 // First get the port capability
1294 if portCap, err = agent.deviceMgr.getPortCapability(nil, childDevice.Id, port.PortNo); err != nil {
1295 log.Errorw("error-retrieving-port-capabilities", log.Fields{"error": err})
1296 return err
1297 }
khenaidoo1ce37ad2019-03-24 22:07:24 -04001298 agent.lockLogicalDevice.Lock()
1299 defer agent.lockLogicalDevice.Unlock()
1300 // Double check again if this port has been already added since the getPortCapability could have taken a long time
1301 if agent.portExist(childDevice, port) {
1302 log.Debugw("port-already-exist", log.Fields{"port": port})
1303 return nil
1304 }
khenaidoofc1314d2019-03-14 09:34:21 -04001305 // Get stored logical device
1306 if ldevice, err := agent.getLogicalDeviceWithoutLock(); err != nil {
1307 return status.Error(codes.NotFound, agent.logicalDeviceId)
1308 } else {
1309 log.Debugw("adding-uni", log.Fields{"deviceId": childDevice.Id})
1310 portCap.Port.RootPort = false
Matt Jeanneret3815e322019-03-12 19:15:49 -04001311 portCap.Port.Id = port.Label
1312 portCap.Port.OfpPort.PortNo = port.PortNo
khenaidoo1ce37ad2019-03-24 22:07:24 -04001313 portCap.Port.OfpPort.Name = childDevice.SerialNumber
khenaidoofc1314d2019-03-14 09:34:21 -04001314 portCap.Port.DeviceId = childDevice.Id
1315 portCap.Port.DevicePortNo = port.PortNo
1316 cloned := (proto.Clone(ldevice)).(*voltha.LogicalDevice)
1317 if cloned.Ports == nil {
1318 cloned.Ports = make([]*voltha.LogicalPort, 0)
1319 }
1320 cloned.Ports = append(cloned.Ports, portCap.Port)
1321 return agent.updateLogicalDeviceWithoutLock(cloned)
1322 }
1323}
1324
khenaidoo43c82122018-11-22 18:38:28 -05001325func (agent *LogicalDeviceAgent) packetOut(packet *ofp.OfpPacketOut) {
khenaidoofdbad6e2018-11-06 22:26:38 -05001326 log.Debugw("packet-out", log.Fields{"packet": packet.GetInPort()})
1327 outPort := fd.GetPacketOutPort(packet)
1328 //frame := packet.GetData()
1329 //TODO: Use a channel between the logical agent and the device agent
khenaidooca301322019-01-09 23:06:32 -05001330 if err := agent.deviceMgr.packetOut(agent.rootDeviceId, outPort, packet); err != nil {
1331 log.Error("packetout-failed", log.Fields{"logicalDeviceID":agent.rootDeviceId})
1332 }
khenaidoofdbad6e2018-11-06 22:26:38 -05001333}
1334
khenaidoo297cd252019-02-07 22:10:23 -05001335func (agent *LogicalDeviceAgent) packetIn(port uint32, transactionId string, packet []byte) {
1336 log.Debugw("packet-in", log.Fields{"port": port, "packet": packet, "transactionId": transactionId})
khenaidooca301322019-01-09 23:06:32 -05001337 packetIn := fd.MkPacketIn(port, packet)
khenaidoo297cd252019-02-07 22:10:23 -05001338 agent.ldeviceMgr.grpcNbiHdlr.sendPacketIn(agent.logicalDeviceId, transactionId, packetIn)
khenaidooca301322019-01-09 23:06:32 -05001339 log.Debugw("sending-packet-in", log.Fields{"packet-in": packetIn})
khenaidoofdbad6e2018-11-06 22:26:38 -05001340}