blob: 7d974f85f47e83c2508cd86df1cfb702e10addc3 [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
Akash Soni230e6212023-10-16 10:46:07 +053071 Devices map[string]*Device
vinokuma926cb3e2023-03-29 11:41:06 +053072 rebootInProgressDevices map[string]string
73 deviceLock sync.RWMutex
74 rebootLock sync.Mutex
Sridhar Ravindra3ec14232024-01-01 19:11:48 +053075 deviceTableSyncDuration time.Duration // Time interval between each cycle of audit task
76 maxFlowRetryDuration time.Duration // Maximum duration for which flows will be retried upon failures
77 maxFlowRetryAttempts uint32 // maxFlowRetryAttempt = maxFlowRetryDuration / deviceTableSyncDuration
vinokuma926cb3e2023-03-29 11:41:06 +053078 RebootFlow bool
Naveen Sampath04696f72022-06-13 15:19:14 +053079}
80
81var vcontroller *VoltController
82
83// NewController is the constructor for VoltController
84func NewController(ctx context.Context, app intf.App) intf.IVPClientAgent {
85 var controller VoltController
86
87 controller.rebootInProgressDevices = make(map[string]string)
Akash Soni230e6212023-10-16 10:46:07 +053088 controller.Devices = make(map[string]*Device)
Naveen Sampath04696f72022-06-13 15:19:14 +053089 controller.deviceLock = sync.RWMutex{}
90 controller.ctx = ctx
91 controller.app = app
92 controller.BlockedDeviceList = util.NewConcurrentMap()
93 controller.deviceTaskQueue = util.NewConcurrentMap()
94 db = database.GetDatabase()
95 vcontroller = &controller
96 return &controller
97}
98
vinokuma926cb3e2023-03-29 11:41:06 +053099// SetDeviceTableSyncDuration - sets interval between device table sync up activity
100// duration - in minutes
Tinoj Josephaf37ce82022-12-28 11:59:43 +0530101func (v *VoltController) SetDeviceTableSyncDuration(duration int) {
102 v.deviceTableSyncDuration = time.Duration(duration) * time.Second
103}
104
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530105// SetMaxFlowRetryDuration - sets max flow retry interval
106func (v *VoltController) SetMaxFlowRetryDuration(duration int) {
107 v.maxFlowRetryDuration = time.Duration(duration) * time.Second
108}
109
110// SetMaxFlowRetryAttempts - sets max flow retry attempts
111func (v *VoltController) SetMaxFlowRetryAttempts() {
112 v.maxFlowRetryAttempts = uint32((v.maxFlowRetryDuration / v.deviceTableSyncDuration))
113}
114
vinokuma926cb3e2023-03-29 11:41:06 +0530115// GetDeviceTableSyncDuration - returns configured device table sync duration
Tinoj Josephaf37ce82022-12-28 11:59:43 +0530116func (v *VoltController) GetDeviceTableSyncDuration() time.Duration {
117 return v.deviceTableSyncDuration
118}
119
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530120// GetMaxFlowRetryAttempt - returns max flow retry attempst
121func (v *VoltController) GetMaxFlowRetryAttempt() uint32 {
122 return v.maxFlowRetryAttempts
123}
124
Naveen Sampath04696f72022-06-13 15:19:14 +0530125// AddDevice to add device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530126func (v *VoltController) AddDevice(cntx context.Context, config *intf.VPClientCfg) intf.IVPClient {
Tinoj Joseph429b9d92022-11-16 18:51:05 +0530127 d := NewDevice(cntx, config.DeviceID, config.SerialNum, config.VolthaClient, config.SouthBoundID, config.MfrDesc, config.HwDesc, config.SwDesc)
Akash Soni230e6212023-10-16 10:46:07 +0530128 v.Devices[config.DeviceID] = d
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530129 v.app.AddDevice(cntx, d.ID, d.SerialNum, config.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530130
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530131 d.RestoreMetersFromDb(cntx)
132 d.RestoreGroupsFromDb(cntx)
133 d.RestoreFlowsFromDb(cntx)
134 d.RestorePortsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530135 d.ConnectInd(context.TODO(), intf.DeviceDisc)
136 d.packetOutChannel = config.PacketOutChannel
137
Akash Soni6168f312023-05-18 20:57:33 +0530138 logger.Debugw(ctx, "Added device", log.Fields{"Device": config.DeviceID, "SerialNo": d.SerialNum, "State": d.State})
Naveen Sampath04696f72022-06-13 15:19:14 +0530139
140 return d
141}
142
143// DelDevice to delete device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530144func (v *VoltController) DelDevice(cntx context.Context, id string) {
Akash Soni230e6212023-10-16 10:46:07 +0530145 d, ok := v.Devices[id]
Naveen Sampath04696f72022-06-13 15:19:14 +0530146 if ok {
Akash Soni230e6212023-10-16 10:46:07 +0530147 delete(v.Devices, id)
Naveen Sampath04696f72022-06-13 15:19:14 +0530148 d.Delete()
149 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530150 v.app.DelDevice(cntx, id)
Naveen Sampath04696f72022-06-13 15:19:14 +0530151 d.cancel() // To stop the device tables sync routine
Akash Soni6168f312023-05-18 20:57:33 +0530152 logger.Debugw(ctx, "Deleted device", log.Fields{"Device": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530153}
154
vinokuma926cb3e2023-03-29 11:41:06 +0530155// AddControllerTask - add task to controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530156func (v *VoltController) AddControllerTask(device string, task tasks.Task) {
157 var taskQueueIntf interface{}
158 var taskQueue *tasks.Tasks
159 var found bool
160 if taskQueueIntf, found = v.deviceTaskQueue.Get(device); !found {
161 taskQueue = tasks.NewTasks(context.TODO())
162 v.deviceTaskQueue.Set(device, taskQueue)
163 } else {
164 taskQueue = taskQueueIntf.(*tasks.Tasks)
165 }
166 taskQueue.AddTask(task)
167 logger.Warnw(ctx, "Task Added to Controller Task List", log.Fields{"Len": taskQueue.NumPendingTasks(), "Total": taskQueue.TotalTasks()})
168}
169
vinokuma926cb3e2023-03-29 11:41:06 +0530170// AddNewDevice - called when new device is discovered. This will be
171// processed as part of controller queue
Naveen Sampath04696f72022-06-13 15:19:14 +0530172func (v *VoltController) AddNewDevice(config *intf.VPClientCfg) {
173 adt := NewAddDeviceTask(config)
174 v.AddControllerTask(config.DeviceID, adt)
175}
176
177// GetDevice to get device info
178func (v *VoltController) GetDevice(id string) (*Device, error) {
Akash Soni230e6212023-10-16 10:46:07 +0530179 d, ok := v.Devices[id]
Naveen Sampath04696f72022-06-13 15:19:14 +0530180 if ok {
181 return d, nil
182 }
183 return nil, errorCodes.ErrDeviceNotFound
184}
185
186// IsRebootInProgressForDevice to check if reboot is in progress for the device
187func (v *VoltController) IsRebootInProgressForDevice(device string) bool {
188 v.rebootLock.Lock()
189 defer v.rebootLock.Unlock()
190 _, ok := v.rebootInProgressDevices[device]
191 return ok
192}
193
194// SetRebootInProgressForDevice to set reboot in progress for the device
195func (v *VoltController) SetRebootInProgressForDevice(device string) bool {
196 v.rebootLock.Lock()
197 defer v.rebootLock.Unlock()
198 _, ok := v.rebootInProgressDevices[device]
199 if ok {
200 return true
201 }
202 v.rebootInProgressDevices[device] = device
203 logger.Warnw(ctx, "Setted Reboot-In-Progress flag", log.Fields{"Device": device})
204
205 d, err := v.GetDevice(device)
206 if err == nil {
207 d.ResetCache()
208 } else {
209 logger.Errorw(ctx, "Failed to get device", log.Fields{"Device": device, "Error": err})
210 }
211
212 return true
213}
214
215// ReSetRebootInProgressForDevice to reset reboot in progress for the device
216func (v *VoltController) ReSetRebootInProgressForDevice(device string) bool {
217 v.rebootLock.Lock()
218 defer v.rebootLock.Unlock()
219 _, ok := v.rebootInProgressDevices[device]
220 if !ok {
221 return true
222 }
223 delete(v.rebootInProgressDevices, device)
224 logger.Warnw(ctx, "Resetted Reboot-In-Progress flag", log.Fields{"Device": device})
225 return true
226}
227
228// DeviceRebootInd is device reboot indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530229func (v *VoltController) DeviceRebootInd(cntx context.Context, dID string, srNo string, sbID string) {
230 v.app.DeviceRebootInd(cntx, dID, srNo, sbID)
231 _ = db.DelAllRoutesForDevice(cntx, dID)
232 _ = db.DelAllGroup(cntx, dID)
233 _ = db.DelAllMeter(cntx, dID)
234 _ = db.DelAllPONCounters(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530235}
236
237// DeviceDisableInd is device deactivation indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530238func (v *VoltController) DeviceDisableInd(cntx context.Context, dID string) {
239 v.app.DeviceDisableInd(cntx, dID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530240}
241
vinokuma926cb3e2023-03-29 11:41:06 +0530242// TriggerPendingProfileDeleteReq - trigger pending profile delete requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530243func (v *VoltController) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
244 v.app.TriggerPendingProfileDeleteReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530245}
246
vinokuma926cb3e2023-03-29 11:41:06 +0530247// TriggerPendingMigrateServicesReq - trigger pending services migration requests
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530248func (v *VoltController) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
249 v.app.TriggerPendingMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530250}
251
252// SetAuditFlags to set the audit flags
253func (v *VoltController) SetAuditFlags(device *Device) {
254 v.app.SetRebootFlag(true)
255 device.auditInProgress = true
256}
257
258// ResetAuditFlags to reset the audit flags
259func (v *VoltController) ResetAuditFlags(device *Device) {
260 v.app.SetRebootFlag(false)
261 device.auditInProgress = false
262}
263
vinokuma926cb3e2023-03-29 11:41:06 +0530264// ProcessFlowModResultIndication - send flow mod result notification
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530265func (v *VoltController) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
266 v.app.ProcessFlowModResultIndication(cntx, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +0530267}
268
Akash Sonief452f12024-12-12 18:20:28 +0530269func (v *VoltController) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
270 v.app.CheckAndDeactivateService(ctx, flow, devSerialNum, devID)
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530271}
272
Naveen Sampath04696f72022-06-13 15:19:14 +0530273// AddVPAgent to add the vpagent
274func (v *VoltController) AddVPAgent(vep string, vpa *vpagent.VPAgent) {
275 v.vagent[vep] = vpa
276}
277
278// VPAgent to get vpagent info
279func (v *VoltController) VPAgent(vep string) (*vpagent.VPAgent, error) {
280 vpa, ok := v.vagent[vep]
281 if ok {
282 return vpa, nil
283 }
284 return nil, errors.New("VPA Not Registered")
285}
286
287// PacketOutReq for packet out request
288func (v *VoltController) PacketOutReq(device string, inport string, outport string, pkt []byte, isCustomPkt bool) error {
289 logger.Debugw(ctx, "Packet Out Req", log.Fields{"Device": device, "OutPort": outport})
290 d, err := v.GetDevice(device)
291 if err != nil {
292 return err
293 }
294 logger.Debugw(ctx, "Packet Out Pkt", log.Fields{"Pkt": hex.EncodeToString(pkt)})
295 return d.PacketOutReq(inport, outport, pkt, isCustomPkt)
296}
297
298// AddFlows to add flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530299func (v *VoltController) AddFlows(cntx context.Context, port string, device string, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530300 d, err := v.GetDevice(device)
301 if err != nil {
302 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
303 return err
304 }
305 devPort := d.GetPortByName(port)
306 if devPort == nil {
307 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
308 return errorCodes.ErrPortNotFound
309 }
310 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530311 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530312 logger.Errorw(ctx, "Context is missing. AddFlow Operation Not added to Task", log.Fields{"Device": device})
313 return errorCodes.ErrInvalidParamInRequest
314 }
315
316 var isMigrationRequired bool
317 if flow.MigrateCookie {
318 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
319 // atlease one subflow with old cookie found in the device.
320 for _, subFlow := range flow.SubFlows {
321 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
322 break
323 }
324 }
325 }
326
327 if isMigrationRequired {
328 // In this case, the flow is updated in local cache and db here.
329 // Actual flow deletion and addition at voltha will happen during flow tables audit.
330 for _, subFlow := range flow.SubFlows {
331 logger.Debugw(ctx, "Cookie Migration Required", log.Fields{"OldCookie": subFlow.OldCookie, "NewCookie": subFlow.Cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530332 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530333 logger.Errorw(ctx, "Delete flow with old cookie failed", log.Fields{"Error": err, "OldCookie": subFlow.OldCookie})
334 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530335 if err := d.AddFlow(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530336 logger.Errorw(ctx, "Flow Add Failed", log.Fields{"Error": err, "Cookie": subFlow.Cookie})
337 }
338 }
339 } else {
340 flow.Command = of.CommandAdd
341 d.UpdateFlows(flow, devPort)
342 for cookie := range flow.SubFlows {
343 logger.Debugw(ctx, "Flow Add added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
344 }
345 }
346 return nil
347}
348
349// DelFlows to delete flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530350// delFlowsOnlyInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
351func (v *VoltController) DelFlows(cntx context.Context, port string, device string, flow *of.VoltFlow, delFlowsOnlyInDevice bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530352 d, err := v.GetDevice(device)
353 if err != nil {
354 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
355 return err
356 }
357 devPort := d.GetPortByName(port)
358 if devPort == nil {
359 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
360 return errorCodes.ErrPortNotFound
361 }
362 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530363 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530364 logger.Errorw(ctx, "Context is missing. DelFlow Operation Not added to Task", log.Fields{"Device": device})
365 return errorCodes.ErrInvalidParamInRequest
366 }
367
368 var isMigrationRequired bool
369 if flow.MigrateCookie {
370 // flow migration to new cookie must be done only during the audit. Migration for all subflows must be done if
371 // atlease one subflow with old cookie found in the device.
372 for _, subFlow := range flow.SubFlows {
373 if isMigrationRequired = d.IsFlowPresentWithOldCookie(subFlow); isMigrationRequired {
374 break
375 }
376 }
377 }
378
379 if isMigrationRequired {
380 // In this case, the flow is deleted from local cache and db here.
381 // Actual flow deletion at voltha will happen during flow tables audit.
382 for _, subFlow := range flow.SubFlows {
383 logger.Debugw(ctx, "Old Cookie delete Required", log.Fields{"OldCookie": subFlow.OldCookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530384 if err := d.DelFlowWithOldCookie(cntx, subFlow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530385 logger.Errorw(ctx, "DelFlowWithOldCookie failed", log.Fields{"OldCookie": subFlow.OldCookie, "Error": err})
386 }
387 }
388 } else {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530389 // Delete flows only in DB/device when Port Delete has come. Do not send flows to core during Port Delete
390 if delFlowsOnlyInDevice {
391 for cookie, subFlow := range flow.SubFlows {
392 err := d.DelFlow(ctx, subFlow)
393 logger.Infow(ctx, "Flow Deleted from device/DB", log.Fields{"Cookie": cookie, "Device": device, "Port": port, "Error": err})
394 }
395 } else {
396 flow.Command = of.CommandDel
397 d.UpdateFlows(flow, devPort)
398 for cookie := range flow.SubFlows {
399 logger.Debugw(ctx, "Flow Del added to queue", log.Fields{"Cookie": cookie, "Device": device, "Port": port})
400 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530401 }
402 }
403 return nil
404}
405
406// GroupUpdate for group update
407func (v *VoltController) GroupUpdate(port string, device string, group *of.Group) error {
408 d, err := v.GetDevice(device)
409 if err != nil {
410 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
411 return err
412 }
413
414 devPort := d.GetPortByName(port)
415 if devPort == nil {
416 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
417 return errorCodes.ErrPortNotFound
418 }
419
420 if d.ctx == nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530421 // FIXME: Application should know the context before it could submit task. Handle at application level
Naveen Sampath04696f72022-06-13 15:19:14 +0530422 logger.Errorw(ctx, "Context is missing. GroupMod Operation Not added to task", log.Fields{"Device": device})
423 return errorCodes.ErrInvalidParamInRequest
424 }
425
426 d.UpdateGroup(group, devPort)
427 return nil
428}
429
430// ModMeter to get mod meter info
431func (v *VoltController) ModMeter(port string, device string, command of.MeterCommand, meter *of.Meter) error {
432 d, err := v.GetDevice(device)
433 if err != nil {
434 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
435 return err
436 }
437
438 devPort := d.GetPortByName(port)
439 if devPort == nil {
440 logger.Errorw(ctx, "Port Not Found", log.Fields{"Device": device})
441 return errorCodes.ErrPortNotFound
442 }
443
444 d.ModMeter(command, meter, devPort)
445 return nil
446}
447
448// PortAddInd for port add indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530449func (v *VoltController) PortAddInd(cntx context.Context, device string, id uint32, name string) {
450 v.app.PortAddInd(cntx, device, id, name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530451}
452
453// PortDelInd for port delete indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530454func (v *VoltController) PortDelInd(cntx context.Context, device string, port string) {
455 v.app.PortDelInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530456}
457
458// PortUpdateInd for port update indication
459func (v *VoltController) PortUpdateInd(device string, name string, id uint32) {
460 v.app.PortUpdateInd(device, name, id)
461}
462
463// PortUpInd for port up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530464func (v *VoltController) PortUpInd(cntx context.Context, device string, port string) {
465 v.app.PortUpInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530466}
467
468// PortDownInd for port down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530469func (v *VoltController) PortDownInd(cntx context.Context, device string, port string) {
470 v.app.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530471}
472
473// DeviceUpInd for device up indication
474func (v *VoltController) DeviceUpInd(device string) {
475 v.app.DeviceUpInd(device)
476}
477
478// DeviceDownInd for device down indication
479func (v *VoltController) DeviceDownInd(device string) {
480 v.app.DeviceDownInd(device)
481}
482
483// PacketInInd for packet in indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530484func (v *VoltController) PacketInInd(cntx context.Context, device string, port string, data []byte) {
485 v.app.PacketInInd(cntx, device, port, data)
Naveen Sampath04696f72022-06-13 15:19:14 +0530486}
487
488// GetPortState to get port status
489func (v *VoltController) GetPortState(device string, name string) (PortState, error) {
490 d, err := v.GetDevice(device)
491 if err != nil {
492 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
493 return PortStateDown, err
494 }
495 return d.GetPortState(name)
496}
497
498// UpdateMvlanProfiles for update mvlan profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530499func (v *VoltController) UpdateMvlanProfiles(cntx context.Context, device string) {
500 v.app.UpdateMvlanProfilesForDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530501}
502
503// GetController to get controller
504func GetController() *VoltController {
505 return vcontroller
506}
507
508/*
509// PostIndication to post indication
510func (v *VoltController) PostIndication(device string, task interface{}) error {
511 var srvTask AddServiceIndTask
512 var portTask AddPortIndTask
513 var taskCommon tasks.Task
514 var isSvcTask bool
515
516 switch data := task.(type) {
517 case *AddServiceIndTask:
518 srvTask = *data
519 taskCommon = data
520 isSvcTask = true
521 case *AddPortIndTask:
522 portTask = *data
523 taskCommon = data
524 }
525
526 d, err := v.GetDevice(device)
527 if err != nil {
528 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": device})
529 //It means device itself it not present so just post the indication directly
530 if isSvcTask {
531 msgbus.PostAccessConfigInd(srvTask.result, d.SerialNum, srvTask.indicationType, srvTask.serviceName, 0, srvTask.reason, srvTask.trigger, srvTask.portState)
532 } else {
533 msgbus.ProcessPortInd(portTask.indicationType, d.SerialNum, portTask.portName, portTask.accessConfig, portTask.serviceList)
534 }
535 return err
536 }
537 if taskCommon != nil {
538 d.AddTask(taskCommon)
539 }
540 return nil
541}
542*/
543
544// GetTaskList to get the task list
545func (v *VoltController) GetTaskList(device string) []tasks.Task {
546 d, err := v.GetDevice(device)
547 if err != nil || d.ctx == nil {
548 logger.Errorw(ctx, "Device Not Connected/Found", log.Fields{"Device": device, "Dev Obj": d})
549 return []tasks.Task{}
550 }
551 return d.GetTaskList()
Naveen Sampath04696f72022-06-13 15:19:14 +0530552}
553
Akash Soni6f369452023-09-19 11:18:28 +0530554// AddBlockedDevices to add Devices to blocked Devices list
Naveen Sampath04696f72022-06-13 15:19:14 +0530555func (v *VoltController) AddBlockedDevices(deviceSerialNumber string) {
556 v.BlockedDeviceList.Set(deviceSerialNumber, deviceSerialNumber)
557}
558
559// DelBlockedDevices to remove device from blocked device list
560func (v *VoltController) DelBlockedDevices(deviceSerialNumber string) {
561 v.BlockedDeviceList.Remove(deviceSerialNumber)
562}
563
564// IsBlockedDevice to check if device is blocked
565func (v *VoltController) IsBlockedDevice(deviceSerialNumber string) bool {
566 _, ifPresent := v.BlockedDeviceList.Get(deviceSerialNumber)
567 return ifPresent
568}
Tinoj Josephec742f62022-09-29 19:11:10 +0530569
570// GetFlows returns flow specific to device and flowID
571func (v *VoltController) GetFlow(deviceID string, cookie uint64) (*of.VoltSubFlow, error) {
572 d, err := v.GetDevice(deviceID)
573 if err != nil {
574 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
575 return nil, err
576 }
577 if flow, ok := d.GetFlow(cookie); ok {
578 return flow, nil
579 }
580 return nil, nil
581}
582
583// GetFlows returns list of flows for a particular device
584func (v *VoltController) GetFlows(deviceID string) ([]*of.VoltSubFlow, error) {
585 d, err := v.GetDevice(deviceID)
586 if err != nil {
587 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID, "Error": err})
Akash Sonia8246972023-01-03 10:37:08 +0530588 return nil, nil
Tinoj Josephec742f62022-09-29 19:11:10 +0530589 }
590 return d.GetAllFlows(), nil
591}
592
593// GetAllFlows returns list of all flows
594func (v *VoltController) GetAllFlows() ([]*of.VoltSubFlow, error) {
595 var flows []*of.VoltSubFlow
Akash Soni230e6212023-10-16 10:46:07 +0530596 for _, d := range v.Devices {
Tinoj Josephec742f62022-09-29 19:11:10 +0530597 flows = append(flows, d.GetAllFlows()...)
598 }
599 return flows, nil
600}
601
602// GetAllPendingFlows returns list of all flows
603func (v *VoltController) GetAllPendingFlows() ([]*of.VoltSubFlow, error) {
604 var flows []*of.VoltSubFlow
Akash Soni230e6212023-10-16 10:46:07 +0530605 for _, d := range v.Devices {
Tinoj Josephec742f62022-09-29 19:11:10 +0530606 flows = append(flows, d.GetAllPendingFlows()...)
607 }
608 return flows, nil
609}
Akash Sonib3abf522022-12-19 13:20:02 +0530610func (v *VoltController) GetAllMeterInfo() (map[string][]*of.Meter, error) {
611 logger.Info(ctx, "Entering into GetAllMeterInfo method")
612 meters := map[string][]*of.Meter{}
Akash Soni230e6212023-10-16 10:46:07 +0530613 for _, device := range v.Devices {
Akash Soni6168f312023-05-18 20:57:33 +0530614 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 +0530615 for _, meter := range device.meters {
616 meters[device.ID] = append(meters[device.ID], meter)
617 }
Akash Soni6168f312023-05-18 20:57:33 +0530618 logger.Debugw(ctx, "Inside GetAllMeterInfo method", log.Fields{"meters": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530619 }
620 return meters, nil
621}
622
623func (v *VoltController) GetMeterInfo(cntx context.Context, id uint32) (map[string]*of.Meter, error) {
624 logger.Info(ctx, "Entering into GetMeterInfo method")
625 meters := map[string]*of.Meter{}
Akash Soni230e6212023-10-16 10:46:07 +0530626 for _, device := range v.Devices {
Akash Soni6168f312023-05-18 20:57:33 +0530627 logger.Debugw(ctx, "Inside GetMeterInfo method", log.Fields{"deviceId": device.ID})
Akash Sonib3abf522022-12-19 13:20:02 +0530628 meter, err := device.GetMeter(id)
629 if err != nil {
630 logger.Errorw(ctx, "Failed to fetch the meter", log.Fields{"Reason": err.Error()})
631 return nil, err
632 }
633 meters[device.ID] = meter
Akash Soni6168f312023-05-18 20:57:33 +0530634 logger.Debugw(ctx, "meters", log.Fields{"Meter": meters})
Akash Sonib3abf522022-12-19 13:20:02 +0530635 }
636 return meters, nil
637}
638
639func (v *VoltController) GetGroupList() ([]*of.Group, error) {
640 logger.Info(ctx, "Entering into GetGroupList method")
641 groups := []*of.Group{}
Akash Soni230e6212023-10-16 10:46:07 +0530642 for _, device := range v.Devices {
Akash Sonib3abf522022-12-19 13:20:02 +0530643 device.groups.Range(func(key, value interface{}) bool {
644 groupID := key.(uint32)
Akash Soni6168f312023-05-18 20:57:33 +0530645 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": groupID})
Akash Sonib3abf522022-12-19 13:20:02 +0530646 //Obtain all groups associated with the device
647 grps, ok := device.groups.Load(groupID)
648 if !ok {
649 return true
650 }
651 grp := grps.(*of.Group)
652 groups = append(groups, grp)
653 return true
654 })
655 }
656 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
657 return groups, nil
658}
659
660func (v *VoltController) GetGroups(cntx context.Context, id uint32) (*of.Group, error) {
Akash Sonib3abf522022-12-19 13:20:02 +0530661 logger.Info(ctx, "Entering into GetGroupList method")
662 var groups *of.Group
Akash Soni230e6212023-10-16 10:46:07 +0530663 for _, device := range v.Devices {
Akash Soni6168f312023-05-18 20:57:33 +0530664 logger.Debugw(ctx, "Inside GetGroupList method", log.Fields{"groupID": id})
Akash Sonib3abf522022-12-19 13:20:02 +0530665 grps, ok := device.groups.Load(id)
666 if !ok {
Akash Sonid36d23b2023-08-18 12:51:40 +0530667 return nil, errors.New("group not found")
Akash Sonib3abf522022-12-19 13:20:02 +0530668 }
669 groups = grps.(*of.Group)
670 logger.Debugw(ctx, "Groups", log.Fields{"groups": groups})
671 }
672 return groups, nil
673}