blob: 7e1a7265794f50a4209b18c592d63668190929d5 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14 */
15
16package controller
17
18import (
19 "context"
20 "errors"
21 "sync"
22 "time"
23
24 "encoding/hex"
25
26 "voltha-go-controller/database"
27 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
28 "voltha-go-controller/internal/pkg/intf"
29 "voltha-go-controller/internal/pkg/of"
30 "voltha-go-controller/internal/pkg/tasks"
31 "voltha-go-controller/internal/pkg/util"
32 "voltha-go-controller/internal/pkg/vpagent"
33
Tinoj Joseph1d108322022-07-13 10:07:39 +053034 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053035)
36
37var logger log.CLogger
38var ctx = context.TODO()
39
40func init() {
41 // Setup this package so that it's log level can be modified at run time
42 var err error
Tinoj Joseph1d108322022-07-13 10:07:39 +053043 logger, err = log.AddPackageWithDefaultParam()
Naveen Sampath04696f72022-06-13 15:19:14 +053044 if err != nil {
45 panic(err)
46 }
47}
48
49var db database.DBIntf
50
Akash Soni6f369452023-09-19 11:18:28 +053051type VoltControllerInterface interface {
52 GetDevice(id string) (*Device, error)
53 GetAllPendingFlows() ([]*of.VoltSubFlow, error)
54 GetAllFlows() ([]*of.VoltSubFlow, error)
55 GetFlows(deviceID string) ([]*of.VoltSubFlow, error)
56 GetFlow(deviceID string, cookie uint64) (*of.VoltSubFlow, error)
57 GetGroups(cntx context.Context, id uint32) (*of.Group, error)
58 GetGroupList() ([]*of.Group, error)
59 GetMeterInfo(cntx context.Context, id uint32) (map[string]*of.Meter, error)
60 GetAllMeterInfo() (map[string][]*of.Meter, error)
61 GetTaskList(device string) []tasks.Task
62}
63
Naveen Sampath04696f72022-06-13 15:19:14 +053064// VoltController structure
65type VoltController struct {
Naveen Sampath04696f72022-06-13 15:19:14 +053066 ctx context.Context
67 app intf.App
Naveen Sampath04696f72022-06-13 15:19:14 +053068 BlockedDeviceList *util.ConcurrentMap
69 deviceTaskQueue *util.ConcurrentMap
vinokuma926cb3e2023-03-29 11:41:06 +053070 vagent map[string]*vpagent.VPAgent
71 devices map[string]*Device
72 rebootInProgressDevices map[string]string
73 deviceLock sync.RWMutex
74 rebootLock sync.Mutex
Tinoj Josephaf37ce82022-12-28 11:59:43 +053075 deviceTableSyncDuration time.Duration
vinokuma926cb3e2023-03-29 11:41:06 +053076 RebootFlow bool
Naveen Sampath04696f72022-06-13 15:19:14 +053077}
78
79var vcontroller *VoltController
80
81// NewController is the constructor for VoltController
82func NewController(ctx context.Context, app intf.App) intf.IVPClientAgent {
83 var controller VoltController
84
85 controller.rebootInProgressDevices = make(map[string]string)
86 controller.devices = make(map[string]*Device)
87 controller.deviceLock = sync.RWMutex{}
88 controller.ctx = ctx
89 controller.app = app
90 controller.BlockedDeviceList = util.NewConcurrentMap()
91 controller.deviceTaskQueue = util.NewConcurrentMap()
92 db = database.GetDatabase()
93 vcontroller = &controller
94 return &controller
95}
96
vinokuma926cb3e2023-03-29 11:41:06 +053097// SetDeviceTableSyncDuration - sets interval between device table sync up activity
98// duration - in minutes
Tinoj Josephaf37ce82022-12-28 11:59:43 +053099func (v *VoltController) SetDeviceTableSyncDuration(duration int) {
100 v.deviceTableSyncDuration = time.Duration(duration) * time.Second
101}
102
vinokuma926cb3e2023-03-29 11:41:06 +0530103// GetDeviceTableSyncDuration - returns configured device table sync duration
Tinoj Josephaf37ce82022-12-28 11:59:43 +0530104func (v *VoltController) GetDeviceTableSyncDuration() time.Duration {
105 return v.deviceTableSyncDuration
106}
107
Naveen Sampath04696f72022-06-13 15:19:14 +0530108// AddDevice to add device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530109func (v *VoltController) AddDevice(cntx context.Context, config *intf.VPClientCfg) intf.IVPClient {
Tinoj Joseph429b9d92022-11-16 18:51:05 +0530110 d := NewDevice(cntx, config.DeviceID, config.SerialNum, config.VolthaClient, config.SouthBoundID, config.MfrDesc, config.HwDesc, config.SwDesc)
Naveen Sampath04696f72022-06-13 15:19:14 +0530111 v.devices[config.DeviceID] = d
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530112 v.app.AddDevice(cntx, d.ID, d.SerialNum, config.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530113
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530114 d.RestoreMetersFromDb(cntx)
115 d.RestoreGroupsFromDb(cntx)
116 d.RestoreFlowsFromDb(cntx)
117 d.RestorePortsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530118 d.ConnectInd(context.TODO(), intf.DeviceDisc)
119 d.packetOutChannel = config.PacketOutChannel
120
Akash Soni6168f312023-05-18 20:57:33 +0530121 logger.Debugw(ctx, "Added device", log.Fields{"Device": config.DeviceID, "SerialNo": d.SerialNum, "State": d.State})
Naveen Sampath04696f72022-06-13 15:19:14 +0530122
123 return d
124}
125
126// DelDevice to delete device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530127func (v *VoltController) DelDevice(cntx context.Context, id string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530128 d, ok := v.devices[id]
129 if ok {
130 delete(v.devices, id)
131 d.Delete()
132 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530133 v.app.DelDevice(cntx, id)
Naveen Sampath04696f72022-06-13 15:19:14 +0530134 d.cancel() // To stop the device tables sync routine
Akash Soni6168f312023-05-18 20:57:33 +0530135 logger.Debugw(ctx, "Deleted device", log.Fields{"Device": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530136}
137
vinokuma926cb3e2023-03-29 11:41:06 +0530138// AddControllerTask - add task to controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530139func (v *VoltController) AddControllerTask(device string, task tasks.Task) {
140 var taskQueueIntf interface{}
141 var taskQueue *tasks.Tasks
142 var found bool
143 if taskQueueIntf, found = v.deviceTaskQueue.Get(device); !found {
144 taskQueue = tasks.NewTasks(context.TODO())
145 v.deviceTaskQueue.Set(device, taskQueue)
146 } else {
147 taskQueue = taskQueueIntf.(*tasks.Tasks)
148 }
149 taskQueue.AddTask(task)
150 logger.Warnw(ctx, "Task Added to Controller Task List", log.Fields{"Len": taskQueue.NumPendingTasks(), "Total": taskQueue.TotalTasks()})
151}
152
vinokuma926cb3e2023-03-29 11:41:06 +0530153// AddNewDevice - called when new device is discovered. This will be
154// processed as part of controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530155func (v *VoltController) AddNewDevice(config *intf.VPClientCfg) {
156 adt := NewAddDeviceTask(config)
157 v.AddControllerTask(config.DeviceID, adt)
158}
159
160// GetDevice to get device info
161func (v *VoltController) GetDevice(id string) (*Device, error) {
162 d, ok := v.devices[id]
163 if ok {
164 return d, nil
165 }
166 return nil, errorCodes.ErrDeviceNotFound
167}
168
169// IsRebootInProgressForDevice to check if reboot is in progress for the device
170func (v *VoltController) IsRebootInProgressForDevice(device string) bool {
171 v.rebootLock.Lock()
172 defer v.rebootLock.Unlock()
173 _, ok := v.rebootInProgressDevices[device]
174 return ok
175}
176
177// SetRebootInProgressForDevice to set reboot in progress for the device
178func (v *VoltController) SetRebootInProgressForDevice(device string) bool {
179 v.rebootLock.Lock()
180 defer v.rebootLock.Unlock()
181 _, ok := v.rebootInProgressDevices[device]
182 if ok {
183 return true
184 }
185 v.rebootInProgressDevices[device] = device
186 logger.Warnw(ctx, "Setted Reboot-In-Progress flag", log.Fields{"Device": device})
187
188 d, err := v.GetDevice(device)
189 if err == nil {
190 d.ResetCache()
191 } else {
192 logger.Errorw(ctx, "Failed to get device", log.Fields{"Device": device, "Error": err})
193 }
194
195 return true
196}
197
198// ReSetRebootInProgressForDevice to reset reboot in progress for the device
199func (v *VoltController) ReSetRebootInProgressForDevice(device string) bool {
200 v.rebootLock.Lock()
201 defer v.rebootLock.Unlock()
202 _, ok := v.rebootInProgressDevices[device]
203 if !ok {
204 return true
205 }
206 delete(v.rebootInProgressDevices, device)
207 logger.Warnw(ctx, "Resetted Reboot-In-Progress flag", log.Fields{"Device": device})
208 return true
209}
210
211// DeviceRebootInd is device reboot indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530212func (v *VoltController) DeviceRebootInd(cntx context.Context, dID string, srNo string, sbID string) {
213 v.app.DeviceRebootInd(cntx, dID, srNo, sbID)
214 _ = db.DelAllRoutesForDevice(cntx, dID)
215 _ = db.DelAllGroup(cntx, dID)
216 _ = db.DelAllMeter(cntx, dID)
217 _ = db.DelAllPONCounters(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530218}
219
220// DeviceDisableInd is device deactivation indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530221func (v *VoltController) DeviceDisableInd(cntx context.Context, dID string) {
222 v.app.DeviceDisableInd(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530223}
224
vinokuma926cb3e2023-03-29 11:41:06 +0530225// TriggerPendingProfileDeleteReq - trigger pending profile delete requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530226func (v *VoltController) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
227 v.app.TriggerPendingProfileDeleteReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530228}
229
vinokuma926cb3e2023-03-29 11:41:06 +0530230// TriggerPendingMigrateServicesReq - trigger pending services migration requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530231func (v *VoltController) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
232 v.app.TriggerPendingMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530233}
234
235// SetAuditFlags to set the audit flags
236func (v *VoltController) SetAuditFlags(device *Device) {
237 v.app.SetRebootFlag(true)
238 device.auditInProgress = true
239}
240
241// ResetAuditFlags to reset the audit flags
242func (v *VoltController) ResetAuditFlags(device *Device) {
243 v.app.SetRebootFlag(false)
244 device.auditInProgress = false
245}
246
vinokuma926cb3e2023-03-29 11:41:06 +0530247// ProcessFlowModResultIndication - send flow mod result notification
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530248func (v *VoltController) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
249 v.app.ProcessFlowModResultIndication(cntx, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +0530250}
251
252// AddVPAgent to add the vpagent
253func (v *VoltController) AddVPAgent(vep string, vpa *vpagent.VPAgent) {
254 v.vagent[vep] = vpa
255}
256
257// VPAgent to get vpagent info
258func (v *VoltController) VPAgent(vep string) (*vpagent.VPAgent, error) {
259 vpa, ok := v.vagent[vep]
260 if ok {
261 return vpa, nil
262 }
263 return nil, errors.New("VPA Not Registered")
264}
265
266// PacketOutReq for packet out request
267func (v *VoltController) PacketOutReq(device string, inport string, outport string, pkt []byte, isCustomPkt bool) error {
268 logger.Debugw(ctx, "Packet Out Req", log.Fields{"Device": device, "OutPort": outport})
269 d, err := v.GetDevice(device)
270 if err != nil {
271 return err
272 }
273 logger.Debugw(ctx, "Packet Out Pkt", log.Fields{"Pkt": hex.EncodeToString(pkt)})
274 return d.PacketOutReq(inport, outport, pkt, isCustomPkt)
275}
276
277// AddFlows to add flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530278func (v *VoltController) AddFlows(cntx context.Context, port string, device string, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530279 d, err := v.GetDevice(device)
280 if err != nil {
281 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
282 return err
283 }
284 devPort := d.GetPortByName(port)
285 if devPort == nil {
286 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
287 return errorCodes.ErrPortNotFound
288 }
289 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530290 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530291 logger.Errorw(ctx, "Context is missing. AddFlow Operation Not added to Task", log.Fields{"Device": device})
292 return errorCodes.ErrInvalidParamInRequest
293 }
294
295 var isMigrationRequired bool
296 if flow.MigrateCookie {
297 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
298 // atlease one subflow with old cookie found in the device.
299 for _, subFlow := range flow.SubFlows {
300 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
301 break
302 }
303 }
304 }
305
306 if isMigrationRequired {
307 // In this case, the flow is updated in local cache and db here.
308 // Actual flow deletion and addition at voltha will happen during flow tables audit.
309 for _, subFlow := range flow.SubFlows {
310 logger.Debugw(ctx, "Cookie Migration Required", log.Fields{"OldCookie": subFlow.OldCookie, "NewCookie": subFlow.Cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530311 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530312 logger.Errorw(ctx, "Delete flow with old cookie failed", log.Fields{"Error": err, "OldCookie": subFlow.OldCookie})
313 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530314 if err := d.AddFlow(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530315 logger.Errorw(ctx, "Flow Add Failed", log.Fields{"Error": err, "Cookie": subFlow.Cookie})
316 }
317 }
318 } else {
319 flow.Command = of.CommandAdd
320 d.UpdateFlows(flow, devPort)
321 for cookie := range flow.SubFlows {
322 logger.Debugw(ctx, "Flow Add added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
323 }
324 }
325 return nil
326}
327
328// DelFlows to delete flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530329// delFlowsOnlyInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
330func (v *VoltController) DelFlows(cntx context.Context, port string, device string, flow *of.VoltFlow, delFlowsOnlyInDevice bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530331 d, err := v.GetDevice(device)
332 if err != nil {
333 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
334 return err
335 }
336 devPort := d.GetPortByName(port)
337 if devPort == nil {
338 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
339 return errorCodes.ErrPortNotFound
340 }
341 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530342 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530343 logger.Errorw(ctx, "Context is missing. DelFlow Operation Not added to Task", log.Fields{"Device": device})
344 return errorCodes.ErrInvalidParamInRequest
345 }
346
347 var isMigrationRequired bool
348 if flow.MigrateCookie {
349 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
350 // atlease one subflow with old cookie found in the device.
351 for _, subFlow := range flow.SubFlows {
352 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
353 break
354 }
355 }
356 }
357
358 if isMigrationRequired {
359 // In this case, the flow is deleted from local cache and db here.
360 // Actual flow deletion at voltha will happen during flow tables audit.
361 for _, subFlow := range flow.SubFlows {
362 logger.Debugw(ctx, "Old Cookie delete Required", log.Fields{"OldCookie": subFlow.OldCookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530363 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530364 logger.Errorw(ctx, "DelFlowWithOldCookie failed", log.Fields{"OldCookie": subFlow.OldCookie, "Error": err})
365 }
366 }
367 } else {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530368 // Delete flows only in DB/device when Port Delete has come. Do not send flows to core during Port Delete
369 if delFlowsOnlyInDevice {
370 for cookie, subFlow := range flow.SubFlows {
371 err := d.DelFlow(ctx, subFlow)
372 logger.Infow(ctx, "Flow Deleted from device/DB", log.Fields{"Cookie": cookie, "Device": device, "Port": port, "Error": err})
373 }
374 } else {
375 flow.Command = of.CommandDel
376 d.UpdateFlows(flow, devPort)
377 for cookie := range flow.SubFlows {
378 logger.Debugw(ctx, "Flow Del added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
379 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530380 }
381 }
382 return nil
383}
384
385// GroupUpdate for group update
386func (v *VoltController) GroupUpdate(port string, device string, group *of.Group) error {
387 d, err := v.GetDevice(device)
388 if err != nil {
389 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
390 return err
391 }
392
393 devPort := d.GetPortByName(port)
394 if devPort == nil {
395 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
396 return errorCodes.ErrPortNotFound
397 }
398
399 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530400 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530401 logger.Errorw(ctx, "Context is missing. GroupMod Operation Not added to task", log.Fields{"Device": device})
402 return errorCodes.ErrInvalidParamInRequest
403 }
404
405 d.UpdateGroup(group, devPort)
406 return nil
407}
408
409// ModMeter to get mod meter info
410func (v *VoltController) ModMeter(port string, device string, command of.MeterCommand, meter *of.Meter) error {
411 d, err := v.GetDevice(device)
412 if err != nil {
413 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
414 return err
415 }
416
417 devPort := d.GetPortByName(port)
418 if devPort == nil {
419 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
420 return errorCodes.ErrPortNotFound
421 }
422
423 d.ModMeter(command, meter, devPort)
424 return nil
425}
426
427// PortAddInd for port add indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530428func (v *VoltController) PortAddInd(cntx context.Context, device string, id uint32, name string) {
429 v.app.PortAddInd(cntx, device, id, name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530430}
431
432// PortDelInd for port delete indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530433func (v *VoltController) PortDelInd(cntx context.Context, device string, port string) {
434 v.app.PortDelInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530435}
436
437// PortUpdateInd for port update indication
438func (v *VoltController) PortUpdateInd(device string, name string, id uint32) {
439 v.app.PortUpdateInd(device, name, id)
440}
441
442// PortUpInd for port up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530443func (v *VoltController) PortUpInd(cntx context.Context, device string, port string) {
444 v.app.PortUpInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530445}
446
447// PortDownInd for port down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530448func (v *VoltController) PortDownInd(cntx context.Context, device string, port string) {
449 v.app.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530450}
451
452// DeviceUpInd for device up indication
453func (v *VoltController) DeviceUpInd(device string) {
454 v.app.DeviceUpInd(device)
455}
456
457// DeviceDownInd for device down indication
458func (v *VoltController) DeviceDownInd(device string) {
459 v.app.DeviceDownInd(device)
460}
461
462// PacketInInd for packet in indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530463func (v *VoltController) PacketInInd(cntx context.Context, device string, port string, data []byte) {
464 v.app.PacketInInd(cntx, device, port, data)
Naveen Sampath04696f72022-06-13 15:19:14 +0530465}
466
467// GetPortState to get port status
468func (v *VoltController) GetPortState(device string, name string) (PortState, error) {
469 d, err := v.GetDevice(device)
470 if err != nil {
471 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
472 return PortStateDown, err
473 }
474 return d.GetPortState(name)
475}
476
477// UpdateMvlanProfiles for update mvlan profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530478func (v *VoltController) UpdateMvlanProfiles(cntx context.Context, device string) {
479 v.app.UpdateMvlanProfilesForDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530480}
481
482// GetController to get controller
483func GetController() *VoltController {
484 return vcontroller
485}
486
487/*
488// PostIndication to post indication
489func (v *VoltController) PostIndication(device string, task interface{}) error {
490 var srvTask AddServiceIndTask
491 var portTask AddPortIndTask
492 var taskCommon tasks.Task
493 var isSvcTask bool
494
495 switch data := task.(type) {
496 case *AddServiceIndTask:
497 srvTask = *data
498 taskCommon = data
499 isSvcTask = true
500 case *AddPortIndTask:
501 portTask = *data
502 taskCommon = data
503 }
504
505 d, err := v.GetDevice(device)
506 if err != nil {
507 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
508 //It means device itself it not present so just post the indication directly
509 if isSvcTask {
510 msgbus.PostAccessConfigInd(srvTask.result, d.SerialNum, srvTask.indicationType, srvTask.serviceName, 0, srvTask.reason, srvTask.trigger, srvTask.portState)
511 } else {
512 msgbus.ProcessPortInd(portTask.indicationType, d.SerialNum, portTask.portName, portTask.accessConfig, portTask.serviceList)
513 }
514 return err
515 }
516 if taskCommon != nil {
517 d.AddTask(taskCommon)
518 }
519 return nil
520}
521*/
522
523// GetTaskList to get the task list
524func (v *VoltController) GetTaskList(device string) []tasks.Task {
525 d, err := v.GetDevice(device)
526 if err != nil || d.ctx == nil {
527 logger.Errorw(ctx, "Device Not Connected/Found", log.Fields{"Device": device, "Dev Obj": d})
528 return []tasks.Task{}
529 }
530 return d.GetTaskList()
Naveen Sampath04696f72022-06-13 15:19:14 +0530531}
532
Akash Soni6f369452023-09-19 11:18:28 +0530533// AddBlockedDevices to add Devices to blocked Devices list
Naveen Sampath04696f72022-06-13 15:19:14 +0530534func (v *VoltController) AddBlockedDevices(deviceSerialNumber string) {
535 v.BlockedDeviceList.Set(deviceSerialNumber, deviceSerialNumber)
536}
537
538// DelBlockedDevices to remove device from blocked device list
539func (v *VoltController) DelBlockedDevices(deviceSerialNumber string) {
540 v.BlockedDeviceList.Remove(deviceSerialNumber)
541}
542
543// IsBlockedDevice to check if device is blocked
544func (v *VoltController) IsBlockedDevice(deviceSerialNumber string) bool {
545 _, ifPresent := v.BlockedDeviceList.Get(deviceSerialNumber)
546 return ifPresent
547}
Tinoj Josephec742f62022-09-29 19:11:10 +0530548
549// GetFlows returns flow specific to device and flowID
550func (v *VoltController) GetFlow(deviceID string, cookie uint64) (*of.VoltSubFlow, error) {
551 d, err := v.GetDevice(deviceID)
552 if err != nil {
553 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
554 return nil, err
555 }
556 if flow, ok := d.GetFlow(cookie); ok {
557 return flow, nil
558 }
559 return nil, nil
560}
561
562// GetFlows returns list of flows for a particular device
563func (v *VoltController) GetFlows(deviceID string) ([]*of.VoltSubFlow, error) {
564 d, err := v.GetDevice(deviceID)
565 if err != nil {
566 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
Akash Sonia8246972023-01-03 10:37:08 +0530567 return nil, nil
Tinoj Josephec742f62022-09-29 19:11:10 +0530568 }
569 return d.GetAllFlows(), nil
570}
571
572// GetAllFlows returns list of all flows
573func (v *VoltController) GetAllFlows() ([]*of.VoltSubFlow, error) {
574 var flows []*of.VoltSubFlow
575 for _, d := range v.devices {
576 flows = append(flows, d.GetAllFlows()...)
577 }
578 return flows, nil
579}
580
581// GetAllPendingFlows returns list of all flows
582func (v *VoltController) GetAllPendingFlows() ([]*of.VoltSubFlow, error) {
583 var flows []*of.VoltSubFlow
584 for _, d := range v.devices {
585 flows = append(flows, d.GetAllPendingFlows()...)
586 }
587 return flows, nil
588}
Akash Sonib3abf522022-12-19 13:20:02 +0530589func (v *VoltController) GetAllMeterInfo() (map[string][]*of.Meter, error) {
590 logger.Info(ctx, "Entering into GetAllMeterInfo method")
591 meters := map[string][]*of.Meter{}
592 for _, device := range v.devices {
Akash Soni6168f312023-05-18 20:57:33 +0530593 logger.Debugw(ctx, "Inside GetAllMeterInfo method", log.Fields{"deviceId": device.ID, "southbound": device.SouthBoundID, "serial no": device.SerialNum})
Akash Sonib3abf522022-12-19 13:20:02 +0530594 for _, meter := range device.meters {
595 meters[device.ID] = append(meters[device.ID], meter)
596 }
Akash Soni6168f312023-05-18 20:57:33 +0530597 logger.Debugw(ctx, "Inside GetAllMeterInfo method", log.Fields{"meters": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530598 }
599 return meters, nil
600}
601
602func (v *VoltController) GetMeterInfo(cntx context.Context, id uint32) (map[string]*of.Meter, error) {
603 logger.Info(ctx, "Entering into GetMeterInfo method")
604 meters := map[string]*of.Meter{}
605 for _, device := range v.devices {
Akash Soni6168f312023-05-18 20:57:33 +0530606 logger.Debugw(ctx, "Inside GetMeterInfo method", log.Fields{"deviceId": device.ID})
Akash Sonib3abf522022-12-19 13:20:02 +0530607 meter, err := device.GetMeter(id)
608 if err != nil {
609 logger.Errorw(ctx, "Failed to fetch the meter", log.Fields{"Reason": err.Error()})
610 return nil, err
611 }
612 meters[device.ID] = meter
Akash Soni6168f312023-05-18 20:57:33 +0530613 logger.Debugw(ctx, "meters", log.Fields{"Meter": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530614 }
615 return meters, nil
616}
617
618func (v *VoltController) GetGroupList() ([]*of.Group, error) {
619 logger.Info(ctx, "Entering into GetGroupList method")
620 groups := []*of.Group{}
621 for _, device := range v.devices {
622 device.groups.Range(func(key, value interface{}) bool {
623 groupID := key.(uint32)
Akash Soni6168f312023-05-18 20:57:33 +0530624 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": groupID})
Akash Sonib3abf522022-12-19 13:20:02 +0530625 //Obtain all groups associated with the device
626 grps, ok := device.groups.Load(groupID)
627 if !ok {
628 return true
629 }
630 grp := grps.(*of.Group)
631 groups = append(groups, grp)
632 return true
633 })
634 }
635 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
636 return groups, nil
637}
638
639func (v *VoltController) GetGroups(cntx context.Context, id uint32) (*of.Group, error) {
Akash Sonib3abf522022-12-19 13:20:02 +0530640 logger.Info(ctx, "Entering into GetGroupList method")
641 var groups *of.Group
642 for _, device := range v.devices {
Akash Soni6168f312023-05-18 20:57:33 +0530643 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": id})
Akash Sonib3abf522022-12-19 13:20:02 +0530644 grps, ok := device.groups.Load(id)
645 if !ok {
Akash Sonid36d23b2023-08-18 12:51:40 +0530646 return nil, errors.New("group not found")
Akash Sonib3abf522022-12-19 13:20:02 +0530647 }
648 groups = grps.(*of.Group)
649 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
650 }
651 return groups, nil
652}