blob: 65b435eff3fb0eaae89b49337a7740a0f5911e33 [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
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053065//
66//nolint:govet
Naveen Sampath04696f72022-06-13 15:19:14 +053067type VoltController struct {
Naveen Sampath04696f72022-06-13 15:19:14 +053068 ctx context.Context
69 app intf.App
Naveen Sampath04696f72022-06-13 15:19:14 +053070 BlockedDeviceList *util.ConcurrentMap
71 deviceTaskQueue *util.ConcurrentMap
vinokuma926cb3e2023-03-29 11:41:06 +053072 vagent map[string]*vpagent.VPAgent
bseenivaa8cb94c2024-12-16 13:37:17 +053073 Devices sync.Map
vinokuma926cb3e2023-03-29 11:41:06 +053074 rebootInProgressDevices map[string]string
75 deviceLock sync.RWMutex
76 rebootLock sync.Mutex
Sridhar Ravindra3ec14232024-01-01 19:11:48 +053077 deviceTableSyncDuration time.Duration // Time interval between each cycle of audit task
78 maxFlowRetryDuration time.Duration // Maximum duration for which flows will be retried upon failures
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053079 maxFlowRetryAttempts int64 // maxFlowRetryAttempt = maxFlowRetryDuration / deviceTableSyncDuration
vinokuma926cb3e2023-03-29 11:41:06 +053080 RebootFlow bool
Naveen Sampath04696f72022-06-13 15:19:14 +053081}
82
83var vcontroller *VoltController
84
85// NewController is the constructor for VoltController
86func NewController(ctx context.Context, app intf.App) intf.IVPClientAgent {
87 var controller VoltController
88
89 controller.rebootInProgressDevices = make(map[string]string)
Naveen Sampath04696f72022-06-13 15:19:14 +053090 controller.deviceLock = sync.RWMutex{}
91 controller.ctx = ctx
92 controller.app = app
93 controller.BlockedDeviceList = util.NewConcurrentMap()
94 controller.deviceTaskQueue = util.NewConcurrentMap()
95 db = database.GetDatabase()
96 vcontroller = &controller
97 return &controller
98}
99
vinokuma926cb3e2023-03-29 11:41:06 +0530100// SetDeviceTableSyncDuration - sets interval between device table sync up activity
101// duration - in minutes
Tinoj Josephaf37ce82022-12-28 11:59:43 +0530102func (v *VoltController) SetDeviceTableSyncDuration(duration int) {
103 v.deviceTableSyncDuration = time.Duration(duration) * time.Second
104}
105
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530106// SetMaxFlowRetryDuration - sets max flow retry interval
107func (v *VoltController) SetMaxFlowRetryDuration(duration int) {
108 v.maxFlowRetryDuration = time.Duration(duration) * time.Second
109}
110
111// SetMaxFlowRetryAttempts - sets max flow retry attempts
112func (v *VoltController) SetMaxFlowRetryAttempts() {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530113 v.maxFlowRetryAttempts = int64((v.maxFlowRetryDuration / v.deviceTableSyncDuration))
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530114}
115
vinokuma926cb3e2023-03-29 11:41:06 +0530116// GetDeviceTableSyncDuration - returns configured device table sync duration
Tinoj Josephaf37ce82022-12-28 11:59:43 +0530117func (v *VoltController) GetDeviceTableSyncDuration() time.Duration {
118 return v.deviceTableSyncDuration
119}
120
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530121// GetMaxFlowRetryAttempt - returns max flow retry attempst
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530122func (v *VoltController) GetMaxFlowRetryAttempt() int64 {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530123 return v.maxFlowRetryAttempts
124}
125
Naveen Sampath04696f72022-06-13 15:19:14 +0530126// AddDevice to add device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530127func (v *VoltController) AddDevice(cntx context.Context, config *intf.VPClientCfg) intf.IVPClient {
Tinoj Joseph429b9d92022-11-16 18:51:05 +0530128 d := NewDevice(cntx, config.DeviceID, config.SerialNum, config.VolthaClient, config.SouthBoundID, config.MfrDesc, config.HwDesc, config.SwDesc)
bseenivaa8cb94c2024-12-16 13:37:17 +0530129 v.Devices.Store(config.DeviceID, d)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530130 v.app.AddDevice(cntx, d.ID, d.SerialNum, config.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530131
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530132 d.RestoreMetersFromDb(cntx)
133 d.RestoreGroupsFromDb(cntx)
134 d.RestoreFlowsFromDb(cntx)
135 d.RestorePortsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530136 d.ConnectInd(context.TODO(), intf.DeviceDisc)
137 d.packetOutChannel = config.PacketOutChannel
138
Akash Soni6168f312023-05-18 20:57:33 +0530139 logger.Debugw(ctx, "Added device", log.Fields{"Device": config.DeviceID, "SerialNo": d.SerialNum, "State": d.State})
Naveen Sampath04696f72022-06-13 15:19:14 +0530140
141 return d
142}
143
144// DelDevice to delete device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530145func (v *VoltController) DelDevice(cntx context.Context, id string) {
bseenivaa8cb94c2024-12-16 13:37:17 +0530146 var device *Device
147 d, ok := v.Devices.Load(id)
Naveen Sampath04696f72022-06-13 15:19:14 +0530148 if ok {
bseenivaa8cb94c2024-12-16 13:37:17 +0530149 v.Devices.Delete(id)
150 device, ok = d.(*Device)
151 if ok {
152 device.Delete()
153 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530154 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530155 v.app.DelDevice(cntx, id)
bseenivaa8cb94c2024-12-16 13:37:17 +0530156 device.cancel() // To stop the device tables sync routine
Akash Soni6168f312023-05-18 20:57:33 +0530157 logger.Debugw(ctx, "Deleted device", log.Fields{"Device": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530158}
159
vinokuma926cb3e2023-03-29 11:41:06 +0530160// AddControllerTask - add task to controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530161func (v *VoltController) AddControllerTask(device string, task tasks.Task) {
162 var taskQueueIntf interface{}
163 var taskQueue *tasks.Tasks
164 var found bool
165 if taskQueueIntf, found = v.deviceTaskQueue.Get(device); !found {
166 taskQueue = tasks.NewTasks(context.TODO())
167 v.deviceTaskQueue.Set(device, taskQueue)
168 } else {
169 taskQueue = taskQueueIntf.(*tasks.Tasks)
170 }
171 taskQueue.AddTask(task)
172 logger.Warnw(ctx, "Task Added to Controller Task List", log.Fields{"Len": taskQueue.NumPendingTasks(), "Total": taskQueue.TotalTasks()})
173}
174
vinokuma926cb3e2023-03-29 11:41:06 +0530175// AddNewDevice - called when new device is discovered. This will be
176// processed as part of controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530177func (v *VoltController) AddNewDevice(config *intf.VPClientCfg) {
178 adt := NewAddDeviceTask(config)
179 v.AddControllerTask(config.DeviceID, adt)
180}
181
182// GetDevice to get device info
183func (v *VoltController) GetDevice(id string) (*Device, error) {
bseenivaa8cb94c2024-12-16 13:37:17 +0530184 var device *Device
185 d, ok := v.Devices.Load(id)
186 if !ok {
187 return nil, errorCodes.ErrDeviceNotFound
188 }
189 device, ok = d.(*Device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530190 if ok {
bseenivaa8cb94c2024-12-16 13:37:17 +0530191 return device, nil
Naveen Sampath04696f72022-06-13 15:19:14 +0530192 }
193 return nil, errorCodes.ErrDeviceNotFound
194}
195
196// IsRebootInProgressForDevice to check if reboot is in progress for the device
197func (v *VoltController) IsRebootInProgressForDevice(device string) bool {
198 v.rebootLock.Lock()
199 defer v.rebootLock.Unlock()
200 _, ok := v.rebootInProgressDevices[device]
201 return ok
202}
203
204// SetRebootInProgressForDevice to set reboot in progress for the device
205func (v *VoltController) SetRebootInProgressForDevice(device string) bool {
206 v.rebootLock.Lock()
207 defer v.rebootLock.Unlock()
208 _, ok := v.rebootInProgressDevices[device]
209 if ok {
210 return true
211 }
212 v.rebootInProgressDevices[device] = device
213 logger.Warnw(ctx, "Setted Reboot-In-Progress flag", log.Fields{"Device": device})
214
215 d, err := v.GetDevice(device)
216 if err == nil {
217 d.ResetCache()
218 } else {
219 logger.Errorw(ctx, "Failed to get device", log.Fields{"Device": device, "Error": err})
220 }
221
222 return true
223}
224
225// ReSetRebootInProgressForDevice to reset reboot in progress for the device
226func (v *VoltController) ReSetRebootInProgressForDevice(device string) bool {
227 v.rebootLock.Lock()
228 defer v.rebootLock.Unlock()
229 _, ok := v.rebootInProgressDevices[device]
230 if !ok {
231 return true
232 }
233 delete(v.rebootInProgressDevices, device)
234 logger.Warnw(ctx, "Resetted Reboot-In-Progress flag", log.Fields{"Device": device})
235 return true
236}
237
238// DeviceRebootInd is device reboot indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530239func (v *VoltController) DeviceRebootInd(cntx context.Context, dID string, srNo string, sbID string) {
240 v.app.DeviceRebootInd(cntx, dID, srNo, sbID)
241 _ = db.DelAllRoutesForDevice(cntx, dID)
242 _ = db.DelAllGroup(cntx, dID)
243 _ = db.DelAllMeter(cntx, dID)
244 _ = db.DelAllPONCounters(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530245}
246
247// DeviceDisableInd is device deactivation indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530248func (v *VoltController) DeviceDisableInd(cntx context.Context, dID string) {
249 v.app.DeviceDisableInd(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530250}
251
vinokuma926cb3e2023-03-29 11:41:06 +0530252// TriggerPendingProfileDeleteReq - trigger pending profile delete requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530253func (v *VoltController) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
254 v.app.TriggerPendingProfileDeleteReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530255}
256
vinokuma926cb3e2023-03-29 11:41:06 +0530257// TriggerPendingMigrateServicesReq - trigger pending services migration requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530258func (v *VoltController) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
259 v.app.TriggerPendingMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530260}
261
262// SetAuditFlags to set the audit flags
263func (v *VoltController) SetAuditFlags(device *Device) {
264 v.app.SetRebootFlag(true)
265 device.auditInProgress = true
266}
267
268// ResetAuditFlags to reset the audit flags
269func (v *VoltController) ResetAuditFlags(device *Device) {
270 v.app.SetRebootFlag(false)
271 device.auditInProgress = false
272}
273
vinokuma926cb3e2023-03-29 11:41:06 +0530274// ProcessFlowModResultIndication - send flow mod result notification
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530275func (v *VoltController) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
276 v.app.ProcessFlowModResultIndication(cntx, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +0530277}
278
Akash Sonief452f12024-12-12 18:20:28 +0530279func (v *VoltController) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
280 v.app.CheckAndDeactivateService(ctx, flow, devSerialNum, devID)
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530281}
282
Naveen Sampath04696f72022-06-13 15:19:14 +0530283// AddVPAgent to add the vpagent
284func (v *VoltController) AddVPAgent(vep string, vpa *vpagent.VPAgent) {
285 v.vagent[vep] = vpa
286}
287
288// VPAgent to get vpagent info
289func (v *VoltController) VPAgent(vep string) (*vpagent.VPAgent, error) {
290 vpa, ok := v.vagent[vep]
291 if ok {
292 return vpa, nil
293 }
294 return nil, errors.New("VPA Not Registered")
295}
296
297// PacketOutReq for packet out request
298func (v *VoltController) PacketOutReq(device string, inport string, outport string, pkt []byte, isCustomPkt bool) error {
299 logger.Debugw(ctx, "Packet Out Req", log.Fields{"Device": device, "OutPort": outport})
300 d, err := v.GetDevice(device)
301 if err != nil {
302 return err
303 }
304 logger.Debugw(ctx, "Packet Out Pkt", log.Fields{"Pkt": hex.EncodeToString(pkt)})
305 return d.PacketOutReq(inport, outport, pkt, isCustomPkt)
306}
307
308// AddFlows to add flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530309func (v *VoltController) AddFlows(cntx context.Context, port string, device string, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530310 d, err := v.GetDevice(device)
311 if err != nil {
312 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
313 return err
314 }
315 devPort := d.GetPortByName(port)
316 if devPort == nil {
317 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
318 return errorCodes.ErrPortNotFound
319 }
320 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530321 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530322 logger.Errorw(ctx, "Context is missing. AddFlow Operation Not added to Task", log.Fields{"Device": device})
323 return errorCodes.ErrInvalidParamInRequest
324 }
325
326 var isMigrationRequired bool
327 if flow.MigrateCookie {
328 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
329 // atlease one subflow with old cookie found in the device.
330 for _, subFlow := range flow.SubFlows {
331 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
332 break
333 }
334 }
335 }
336
337 if isMigrationRequired {
338 // In this case, the flow is updated in local cache and db here.
339 // Actual flow deletion and addition at voltha will happen during flow tables audit.
340 for _, subFlow := range flow.SubFlows {
341 logger.Debugw(ctx, "Cookie Migration Required", log.Fields{"OldCookie": subFlow.OldCookie, "NewCookie": subFlow.Cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530342 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530343 logger.Errorw(ctx, "Delete flow with old cookie failed", log.Fields{"Error": err, "OldCookie": subFlow.OldCookie})
344 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530345 if err := d.AddFlow(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530346 logger.Errorw(ctx, "Flow Add Failed", log.Fields{"Error": err, "Cookie": subFlow.Cookie})
347 }
348 }
349 } else {
350 flow.Command = of.CommandAdd
351 d.UpdateFlows(flow, devPort)
352 for cookie := range flow.SubFlows {
353 logger.Debugw(ctx, "Flow Add added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
354 }
355 }
356 return nil
357}
358
359// DelFlows to delete flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530360// delFlowsOnlyInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
361func (v *VoltController) DelFlows(cntx context.Context, port string, device string, flow *of.VoltFlow, delFlowsOnlyInDevice bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530362 d, err := v.GetDevice(device)
363 if err != nil {
364 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
365 return err
366 }
367 devPort := d.GetPortByName(port)
368 if devPort == nil {
369 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
370 return errorCodes.ErrPortNotFound
371 }
372 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530373 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530374 logger.Errorw(ctx, "Context is missing. DelFlow Operation Not added to Task", log.Fields{"Device": device})
375 return errorCodes.ErrInvalidParamInRequest
376 }
377
378 var isMigrationRequired bool
379 if flow.MigrateCookie {
380 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
381 // atlease one subflow with old cookie found in the device.
382 for _, subFlow := range flow.SubFlows {
383 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
384 break
385 }
386 }
387 }
388
389 if isMigrationRequired {
390 // In this case, the flow is deleted from local cache and db here.
391 // Actual flow deletion at voltha will happen during flow tables audit.
392 for _, subFlow := range flow.SubFlows {
393 logger.Debugw(ctx, "Old Cookie delete Required", log.Fields{"OldCookie": subFlow.OldCookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530394 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530395 logger.Errorw(ctx, "DelFlowWithOldCookie failed", log.Fields{"OldCookie": subFlow.OldCookie, "Error": err})
396 }
397 }
398 } else {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530399 // Delete flows only in DB/device when Port Delete has come. Do not send flows to core during Port Delete
400 if delFlowsOnlyInDevice {
401 for cookie, subFlow := range flow.SubFlows {
402 err := d.DelFlow(ctx, subFlow)
403 logger.Infow(ctx, "Flow Deleted from device/DB", log.Fields{"Cookie": cookie, "Device": device, "Port": port, "Error": err})
404 }
405 } else {
406 flow.Command = of.CommandDel
407 d.UpdateFlows(flow, devPort)
408 for cookie := range flow.SubFlows {
409 logger.Debugw(ctx, "Flow Del added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
410 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530411 }
412 }
413 return nil
414}
415
416// GroupUpdate for group update
417func (v *VoltController) GroupUpdate(port string, device string, group *of.Group) error {
418 d, err := v.GetDevice(device)
419 if err != nil {
420 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
421 return err
422 }
423
424 devPort := d.GetPortByName(port)
425 if devPort == nil {
426 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
427 return errorCodes.ErrPortNotFound
428 }
429
430 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530431 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530432 logger.Errorw(ctx, "Context is missing. GroupMod Operation Not added to task", log.Fields{"Device": device})
433 return errorCodes.ErrInvalidParamInRequest
434 }
435
436 d.UpdateGroup(group, devPort)
437 return nil
438}
439
440// ModMeter to get mod meter info
441func (v *VoltController) ModMeter(port string, device string, command of.MeterCommand, meter *of.Meter) error {
442 d, err := v.GetDevice(device)
443 if err != nil {
444 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
445 return err
446 }
447
448 devPort := d.GetPortByName(port)
449 if devPort == nil {
450 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
451 return errorCodes.ErrPortNotFound
452 }
453
454 d.ModMeter(command, meter, devPort)
455 return nil
456}
457
458// PortAddInd for port add indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530459func (v *VoltController) PortAddInd(cntx context.Context, device string, id uint32, name string) {
460 v.app.PortAddInd(cntx, device, id, name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530461}
462
463// PortDelInd for port delete indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530464func (v *VoltController) PortDelInd(cntx context.Context, device string, port string) {
465 v.app.PortDelInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530466}
467
468// PortUpdateInd for port update indication
469func (v *VoltController) PortUpdateInd(device string, name string, id uint32) {
470 v.app.PortUpdateInd(device, name, id)
471}
472
473// PortUpInd for port up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530474func (v *VoltController) PortUpInd(cntx context.Context, device string, port string) {
475 v.app.PortUpInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530476}
477
478// PortDownInd for port down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530479func (v *VoltController) PortDownInd(cntx context.Context, device string, port string) {
480 v.app.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530481}
482
483// DeviceUpInd for device up indication
484func (v *VoltController) DeviceUpInd(device string) {
485 v.app.DeviceUpInd(device)
486}
487
488// DeviceDownInd for device down indication
489func (v *VoltController) DeviceDownInd(device string) {
490 v.app.DeviceDownInd(device)
491}
492
493// PacketInInd for packet in indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530494func (v *VoltController) PacketInInd(cntx context.Context, device string, port string, data []byte) {
495 v.app.PacketInInd(cntx, device, port, data)
Naveen Sampath04696f72022-06-13 15:19:14 +0530496}
497
498// GetPortState to get port status
499func (v *VoltController) GetPortState(device string, name string) (PortState, error) {
500 d, err := v.GetDevice(device)
501 if err != nil {
502 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
503 return PortStateDown, err
504 }
505 return d.GetPortState(name)
506}
507
508// UpdateMvlanProfiles for update mvlan profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530509func (v *VoltController) UpdateMvlanProfiles(cntx context.Context, device string) {
510 v.app.UpdateMvlanProfilesForDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530511}
512
513// GetController to get controller
514func GetController() *VoltController {
515 return vcontroller
516}
517
518/*
519// PostIndication to post indication
520func (v *VoltController) PostIndication(device string, task interface{}) error {
521 var srvTask AddServiceIndTask
522 var portTask AddPortIndTask
523 var taskCommon tasks.Task
524 var isSvcTask bool
525
526 switch data := task.(type) {
527 case *AddServiceIndTask:
528 srvTask = *data
529 taskCommon = data
530 isSvcTask = true
531 case *AddPortIndTask:
532 portTask = *data
533 taskCommon = data
534 }
535
536 d, err := v.GetDevice(device)
537 if err != nil {
538 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
539 //It means device itself it not present so just post the indication directly
540 if isSvcTask {
541 msgbus.PostAccessConfigInd(srvTask.result, d.SerialNum, srvTask.indicationType, srvTask.serviceName, 0, srvTask.reason, srvTask.trigger, srvTask.portState)
542 } else {
543 msgbus.ProcessPortInd(portTask.indicationType, d.SerialNum, portTask.portName, portTask.accessConfig, portTask.serviceList)
544 }
545 return err
546 }
547 if taskCommon != nil {
548 d.AddTask(taskCommon)
549 }
550 return nil
551}
552*/
553
554// GetTaskList to get the task list
555func (v *VoltController) GetTaskList(device string) []tasks.Task {
556 d, err := v.GetDevice(device)
557 if err != nil || d.ctx == nil {
558 logger.Errorw(ctx, "Device Not Connected/Found", log.Fields{"Device": device, "Dev Obj": d})
559 return []tasks.Task{}
560 }
561 return d.GetTaskList()
Naveen Sampath04696f72022-06-13 15:19:14 +0530562}
563
Akash Soni6f369452023-09-19 11:18:28 +0530564// AddBlockedDevices to add Devices to blocked Devices list
Naveen Sampath04696f72022-06-13 15:19:14 +0530565func (v *VoltController) AddBlockedDevices(deviceSerialNumber string) {
566 v.BlockedDeviceList.Set(deviceSerialNumber, deviceSerialNumber)
567}
568
569// DelBlockedDevices to remove device from blocked device list
570func (v *VoltController) DelBlockedDevices(deviceSerialNumber string) {
571 v.BlockedDeviceList.Remove(deviceSerialNumber)
572}
573
574// IsBlockedDevice to check if device is blocked
575func (v *VoltController) IsBlockedDevice(deviceSerialNumber string) bool {
576 _, ifPresent := v.BlockedDeviceList.Get(deviceSerialNumber)
577 return ifPresent
578}
Tinoj Josephec742f62022-09-29 19:11:10 +0530579
580// GetFlows returns flow specific to device and flowID
581func (v *VoltController) GetFlow(deviceID string, cookie uint64) (*of.VoltSubFlow, error) {
582 d, err := v.GetDevice(deviceID)
583 if err != nil {
584 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
585 return nil, err
586 }
587 if flow, ok := d.GetFlow(cookie); ok {
588 return flow, nil
589 }
590 return nil, nil
591}
592
593// GetFlows returns list of flows for a particular device
594func (v *VoltController) GetFlows(deviceID string) ([]*of.VoltSubFlow, error) {
595 d, err := v.GetDevice(deviceID)
596 if err != nil {
597 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
Akash Sonia8246972023-01-03 10:37:08 +0530598 return nil, nil
Tinoj Josephec742f62022-09-29 19:11:10 +0530599 }
600 return d.GetAllFlows(), nil
601}
602
603// GetAllFlows returns list of all flows
604func (v *VoltController) GetAllFlows() ([]*of.VoltSubFlow, error) {
605 var flows []*of.VoltSubFlow
bseenivaa8cb94c2024-12-16 13:37:17 +0530606 v.Devices.Range(func(_, value interface{}) bool {
607 d, ok := value.(*Device)
608 if ok {
609 flows = append(flows, d.GetAllFlows()...)
610 }
611 return true
612 })
Tinoj Josephec742f62022-09-29 19:11:10 +0530613 return flows, nil
614}
615
616// GetAllPendingFlows returns list of all flows
617func (v *VoltController) GetAllPendingFlows() ([]*of.VoltSubFlow, error) {
618 var flows []*of.VoltSubFlow
bseenivaa8cb94c2024-12-16 13:37:17 +0530619 v.Devices.Range(func(_, value interface{}) bool {
620 d, ok := value.(*Device)
621 if ok {
622 flows = append(flows, d.GetAllPendingFlows()...)
623 }
624 return true
625 })
Tinoj Josephec742f62022-09-29 19:11:10 +0530626 return flows, nil
627}
Akash Sonib3abf522022-12-19 13:20:02 +0530628func (v *VoltController) GetAllMeterInfo() (map[string][]*of.Meter, error) {
629 logger.Info(ctx, "Entering into GetAllMeterInfo method")
630 meters := map[string][]*of.Meter{}
bseenivaa8cb94c2024-12-16 13:37:17 +0530631 v.Devices.Range(func(_, value interface{}) bool {
632 device, ok := value.(*Device)
633 if ok {
634 logger.Debugw(ctx, "Inside GetAllMeterInfo method", log.Fields{"deviceId": device.ID, "southbound": device.SouthBoundID, "serial no": device.SerialNum})
635 for _, meter := range device.meters {
636 meters[device.ID] = append(meters[device.ID], meter)
637 }
638 logger.Debugw(ctx, "Inside GetAllMeterInfo method", log.Fields{"meters": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530639 }
bseenivaa8cb94c2024-12-16 13:37:17 +0530640 return true
641 })
Akash Sonib3abf522022-12-19 13:20:02 +0530642 return meters, nil
643}
644
645func (v *VoltController) GetMeterInfo(cntx context.Context, id uint32) (map[string]*of.Meter, error) {
646 logger.Info(ctx, "Entering into GetMeterInfo method")
647 meters := map[string]*of.Meter{}
bseenivaa8cb94c2024-12-16 13:37:17 +0530648 var errResult error
649 v.Devices.Range(func(_, value interface{}) bool {
650 device, ok := value.(*Device)
651 if ok {
652 logger.Debugw(ctx, "Inside GetMeterInfo method", log.Fields{"deviceId": device.ID})
653 meter, err := device.GetMeter(id)
654 if err != nil {
655 logger.Errorw(ctx, "Failed to fetch the meter", log.Fields{"Reason": err.Error()})
656 errResult = err
657 return false
658 }
659 meters[device.ID] = meter
660 logger.Debugw(ctx, "meters", log.Fields{"Meter": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530661 }
bseenivaa8cb94c2024-12-16 13:37:17 +0530662 return true
663 })
664 if errResult != nil {
665 return nil, errResult
Akash Sonib3abf522022-12-19 13:20:02 +0530666 }
667 return meters, nil
668}
669
670func (v *VoltController) GetGroupList() ([]*of.Group, error) {
671 logger.Info(ctx, "Entering into GetGroupList method")
672 groups := []*of.Group{}
bseenivaa8cb94c2024-12-16 13:37:17 +0530673 v.Devices.Range(func(_, value interface{}) bool {
674 device, ok := value.(*Device)
675 if ok {
676 device.groups.Range(func(key, value interface{}) bool {
677 groupID := key.(uint32)
678 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": groupID})
679 //Obtain all groups associated with the device
680 grps, ok := device.groups.Load(groupID)
681 if !ok {
682 return true
683 }
684 grp := grps.(*of.Group)
685 groups = append(groups, grp)
Akash Sonib3abf522022-12-19 13:20:02 +0530686 return true
bseenivaa8cb94c2024-12-16 13:37:17 +0530687 })
688 }
689 return true
690 })
Akash Sonib3abf522022-12-19 13:20:02 +0530691 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
692 return groups, nil
693}
694
695func (v *VoltController) GetGroups(cntx context.Context, id uint32) (*of.Group, error) {
Akash Sonib3abf522022-12-19 13:20:02 +0530696 logger.Info(ctx, "Entering into GetGroupList method")
697 var groups *of.Group
bseenivaa8cb94c2024-12-16 13:37:17 +0530698 var err error
699 v.Devices.Range(func(_, value interface{}) bool {
700 device, ok := value.(*Device)
701 if ok {
702 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": id})
703 grps, ok := device.groups.Load(id)
704 if !ok {
705 err = errors.New("group not found")
706 return false
707 }
708 groups = grps.(*of.Group)
709 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
Akash Sonib3abf522022-12-19 13:20:02 +0530710 }
bseenivaa8cb94c2024-12-16 13:37:17 +0530711 return true
712 })
713 if err != nil {
714 return nil, err
Akash Sonib3abf522022-12-19 13:20:02 +0530715 }
716 return groups, nil
717}