blob: 4f390fd8e98eec90c024572b7ab32a17158324b3 [file] [log] [blame]
Joey Armstrongaca03cf2024-04-23 09:29:52 -04001/* -----------------------------------------------------------------------
2 * Copyright 2022-2024 Open Networking Foundation Contributors
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 * -----------------------------------------------------------------------
16 * SPDX-FileCopyrightText: 2022-2024 Open Networking Foundation Contributors
17 * SPDX-License-Identifier: Apache-2.0
18 * -----------------------------------------------------------------------
Naveen Sampath04696f72022-06-13 15:19:14 +053019 */
20
21package application
22
23import (
24 "context"
25 "encoding/hex"
26 "encoding/json"
27 "errors"
28 "fmt"
29 "net"
30 "strconv"
31 "strings"
32 "sync"
33 "time"
34
35 "github.com/google/gopacket"
36 "github.com/google/gopacket/layers"
37
Akash Sonia8246972023-01-03 10:37:08 +053038 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053039 "voltha-go-controller/internal/pkg/controller"
40 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053041 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053042 "voltha-go-controller/internal/pkg/intf"
43 "voltha-go-controller/internal/pkg/of"
44 "voltha-go-controller/internal/pkg/tasks"
Akash Soni6f369452023-09-19 11:18:28 +053045 common "voltha-go-controller/internal/pkg/types"
Naveen Sampath04696f72022-06-13 15:19:14 +053046 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053047 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053048)
49
50var logger log.CLogger
51var ctx = context.TODO()
52
53func init() {
54 // Setup this package so that it's log level can be modified at run time
55 var err error
Tinoj Joseph1d108322022-07-13 10:07:39 +053056 logger, err = log.AddPackageWithDefaultParam()
Naveen Sampath04696f72022-06-13 15:19:14 +053057 if err != nil {
58 panic(err)
59 }
60}
61
62const (
63 // TODO - Need to identify a right place for this
64
65 // PriorityNone constant.
66 PriorityNone uint8 = 8
67 // AnyVlan constant.
68 AnyVlan uint16 = 0xFFFF
69)
70
71// List of Mac Learning Type
72const (
Tinoj Joseph1d108322022-07-13 10:07:39 +053073 MacLearningNone MacLearningType = iota
74 Learn
75 ReLearn
Naveen Sampath04696f72022-06-13 15:19:14 +053076)
77
78// MacLearningType represents Mac Learning Type
79type MacLearningType int
80
81var (
82 tickCount uint16
83 vgcRebooted bool
84 isUpgradeComplete bool
85)
86
87var db database.DBIntf
88
89// PacketHandlers : packet handler for different protocols
90var PacketHandlers map[string]CallBack
91
92// CallBack : registered call back function for different protocol packets
Tinoj Joseph07cc5372022-07-18 22:53:51 +053093type CallBack func(cntx context.Context, device string, port string, pkt gopacket.Packet)
Naveen Sampath04696f72022-06-13 15:19:14 +053094
95const (
96 // ARP packet
97 ARP string = "ARP"
98 // DHCPv4 packet
99 DHCPv4 string = "DHCPv4"
100 // DHCPv6 packet
101 DHCPv6 string = "DHCPv6"
102 // IGMP packet
103 IGMP string = "IGMP"
104 // PPPOE packet
105 PPPOE string = "PPPOE"
106 // US packet side
107 US string = "US"
108 // DS packet side
109 DS string = "DS"
110 // NNI port name
111 NNI string = "nni"
112)
113
114// RegisterPacketHandler : API to register callback function for every protocol
115func RegisterPacketHandler(protocol string, callback CallBack) {
116 if PacketHandlers == nil {
117 PacketHandlers = make(map[string]CallBack)
118 }
119 PacketHandlers[protocol] = callback
120}
121
122// ---------------------------------------------------------------------
123// VOLT Ports
124// ---------------------------------------------------------------------
125// VOLT Ports are ports associated with VOLT devices. Each port is classified into
126// Access/NNI. Each port is identified by Name (Identity known to the NB) and
127// Id (Identity used on the SB). Both identities are presented when a port is
128// discovered in the SB.
129
130// VoltPortType type for Port Type
131type VoltPortType uint8
132
133const (
134 // VoltPortTypeAccess constant.
135 VoltPortTypeAccess VoltPortType = 0
136 // VoltPortTypeNni constant.
137 VoltPortTypeNni VoltPortType = 1
138)
139
140// PortState type for Port State.
141type PortState uint8
142
143const (
144 // PortStateDown constant.
145 PortStateDown PortState = 0
146 // PortStateUp constant.
147 PortStateUp PortState = 1
148)
149
150// VoltPort structure that is used to store the ports. The name is the
151// the main identity used by the application. The SB and NB both present name
152// as the identity. The SB is abstracted by VPAgent and the VPAgent transacts
153// using name as identity
154type VoltPort struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530155 Name string
156 Device string
157 PonPort uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530158 ActiveChannels uint32
159 ID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530160 Type VoltPortType
161 State PortState
Naveen Sampath04696f72022-06-13 15:19:14 +0530162 ChannelPerSubAlarmRaised bool
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530163 NniDhcpTrapFlowAdded bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530164}
165
166// NewVoltPort : Constructor for the port.
167func NewVoltPort(device string, name string, id uint32) *VoltPort {
168 var vp VoltPort
169 vp.Device = device
170 vp.Name = name
171 vp.ID = id
172 if util.IsNniPort(id) {
173 vp.Type = VoltPortTypeNni
174 } else {
175 vp.PonPort = GetPonPortIDFromUNIPort(id)
176 }
177 vp.State = PortStateDown
178 vp.ChannelPerSubAlarmRaised = false
179 return &vp
180}
181
182// SetPortID : The ID is used when constructing flows as the flows require ID.
183func (vp *VoltPort) SetPortID(id uint32) {
184 vp.ID = id
185 if util.IsNniPort(id) {
186 vp.Type = VoltPortTypeNni
187 }
188}
189
190// ---------------------------------------------------------------------
191// VOLT Device
192// ---------------------------------------------------------------------
193//
194// VoltDevice is an OLT which contains ports of type access and NNI. Each OLT
195// can only have one NNI port in the current release. The NNI port always uses
196// identity 65536 and all the access ports use identities less than 65535. The
197// identification of NNI is done by comparing the port identity with 65535
198
199// VoltDevice fields :
200// Name: This is the name presented by the device/VOLTHA. This doesn't
vinokuma926cb3e2023-03-29 11:41:06 +0530201// have any relation to the physical device
Naveen Sampath04696f72022-06-13 15:19:14 +0530202// SerialNum: This is the serial number of the device and can be used to
vinokuma926cb3e2023-03-29 11:41:06 +0530203// correlate the devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530204// NniPort: The identity of the NNI port
205// Ports: List of all ports added to the device
206type VoltDevice struct {
Akash Sonief452f12024-12-12 18:20:28 +0530207 VoltDeviceIntr VoltDevInterface
Naveen Sampath04696f72022-06-13 15:19:14 +0530208 FlowAddEventMap *util.ConcurrentMap //map[string]*FlowEvent
209 FlowDelEventMap *util.ConcurrentMap //map[string]*FlowEvent
210 MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
vinokuma926cb3e2023-03-29 11:41:06 +0530211 VpvsBySvlan *util.ConcurrentMap // map[svlan]map[vnet_port]*VoltPortVnet
212 ConfiguredVlanForDeviceFlows *util.ConcurrentMap //map[string]map[string]bool
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530213 IgmpDsFlowAppliedForMvlan map[uint16]bool
214 Ports sync.Map
215 VlanPortStatus sync.Map
216 ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
217 PonPortList sync.Map // [PonPortID]map[string]string
218 State controller.DeviceState
219 SouthBoundID string
220 Name string
221 SerialNum string
222 NniPort []string
223 ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
224 NniDhcpTrapVid of.VlanType
225 GlobalDhcpFlowAdded bool
226 icmpv6GroupAdded bool
Akash Soni6f369452023-09-19 11:18:28 +0530227}
228
229type VoltDevInterface interface {
230 GetPortNameFromPortID(portID uint32) string
Naveen Sampath04696f72022-06-13 15:19:14 +0530231}
232
233// NewVoltDevice : Constructor for the device
234func NewVoltDevice(name string, slno, southBoundID string) *VoltDevice {
235 var d VoltDevice
236 d.Name = name
237 d.SouthBoundID = southBoundID
238 d.State = controller.DeviceStateDOWN
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530239 d.NniPort = make([]string, 0)
Naveen Sampath04696f72022-06-13 15:19:14 +0530240 d.SouthBoundID = southBoundID
241 d.SerialNum = slno
242 d.icmpv6GroupAdded = false
243 d.IgmpDsFlowAppliedForMvlan = make(map[uint16]bool)
244 d.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
245 d.MigratingServices = util.NewConcurrentMap()
246 d.VpvsBySvlan = util.NewConcurrentMap()
247 d.FlowAddEventMap = util.NewConcurrentMap()
248 d.FlowDelEventMap = util.NewConcurrentMap()
249 d.GlobalDhcpFlowAdded = false
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530250 if config, ok := GetApplication().DevicesConfig.Load(slno); ok {
251 //Update nni dhcp vid
Akash Soni53da2852023-03-15 00:31:31 +0530252 deviceConfig := config.(*DeviceConfig)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530253 d.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
254 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530255 return &d
256}
257
vinokuma926cb3e2023-03-29 11:41:06 +0530258// GetAssociatedVpvsForDevice - return the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530259func (va *VoltApplication) GetAssociatedVpvsForDevice(device string, svlan of.VlanType) *util.ConcurrentMap {
260 if d := va.GetDevice(device); d != nil {
261 return d.GetAssociatedVpvs(svlan)
262 }
263 return nil
264}
265
vinokuma926cb3e2023-03-29 11:41:06 +0530266// AssociateVpvsToDevice - updates the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530267func (va *VoltApplication) AssociateVpvsToDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530268 logger.Debugw(ctx, "AssociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530269 if d := va.GetDevice(device); d != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530270 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
271 vpvMap.Set(vpv, true)
272 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530273 logger.Debugw(ctx, "VPVMap: SET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530274 return
275 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530276 logger.Warnw(ctx, "Set VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530277}
278
vinokuma926cb3e2023-03-29 11:41:06 +0530279// DisassociateVpvsFromDevice - disassociated VPVs from given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530280func (va *VoltApplication) DisassociateVpvsFromDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530281 logger.Debugw(ctx, "DisassociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530282 if d := va.GetDevice(device); d != nil {
283 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
284 vpvMap.Remove(vpv)
285 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530286 logger.Debugw(ctx, "VPVMap: Remove", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530287 return
288 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530289 logger.Warnw(ctx, "Remove VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530290}
291
vinokuma926cb3e2023-03-29 11:41:06 +0530292// GetAssociatedVpvs - returns the associated VPVs for the given Svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530293func (d *VoltDevice) GetAssociatedVpvs(svlan of.VlanType) *util.ConcurrentMap {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530294 logger.Debugw(ctx, "Received Get Associated Vpvs", log.Fields{"svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530295 var vpvMap *util.ConcurrentMap
296 var mapIntf interface{}
297 var ok bool
298
299 if mapIntf, ok = d.VpvsBySvlan.Get(svlan); ok {
300 vpvMap = mapIntf.(*util.ConcurrentMap)
301 } else {
302 vpvMap = util.NewConcurrentMap()
303 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530304 logger.Debugw(ctx, "VPVMap: GET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530305 return vpvMap
306}
307
308// AddPort add port to the device.
309func (d *VoltDevice) AddPort(port string, id uint32) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530310 logger.Debugw(ctx, "Add Port", log.Fields{"Port": port, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530311 addPonPortFromUniPort := func(vPort *VoltPort) {
312 if vPort.Type == VoltPortTypeAccess {
313 ponPortID := GetPonPortIDFromUNIPort(vPort.ID)
314
315 if ponPortUniList, ok := d.PonPortList.Load(ponPortID); !ok {
316 uniList := make(map[string]uint32)
317 uniList[port] = vPort.ID
318 d.PonPortList.Store(ponPortID, uniList)
319 } else {
320 ponPortUniList.(map[string]uint32)[port] = vPort.ID
321 d.PonPortList.Store(ponPortID, ponPortUniList)
322 }
323 }
324 }
325 va := GetApplication()
326 if pIntf, ok := d.Ports.Load(port); ok {
327 voltPort := pIntf.(*VoltPort)
328 addPonPortFromUniPort(voltPort)
329 va.AggActiveChannelsCountPerSub(d.Name, port, voltPort)
330 d.Ports.Store(port, voltPort)
331 return voltPort
332 }
333 p := NewVoltPort(d.Name, port, id)
334 va.AggActiveChannelsCountPerSub(d.Name, port, p)
335 d.Ports.Store(port, p)
336 if util.IsNniPort(id) {
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530337 d.NniPort = append(d.NniPort, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530338 }
339 addPonPortFromUniPort(p)
340 return p
341}
342
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530343func (d *VoltDevice) IsPortNni(port string) bool {
344 for _, nniPort := range d.NniPort {
345 if nniPort == port {
346 return true
347 }
348 }
349 return false
350}
351
Naveen Sampath04696f72022-06-13 15:19:14 +0530352// GetPort to get port information from the device.
353func (d *VoltDevice) GetPort(port string) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530354 logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530355 if pIntf, ok := d.Ports.Load(port); ok {
356 return pIntf.(*VoltPort)
357 }
358 return nil
359}
360
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530361// GetPortNameFromPortID to get port information from the device.
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530362func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530363 logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530364 portName := ""
365 d.Ports.Range(func(key, value interface{}) bool {
366 vp := value.(*VoltPort)
367 if vp.ID == portID {
368 portName = vp.Name
369 }
370 return true
371 })
372 return portName
373}
374
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530375// GetPortIDFromPortName to get port information from the device.
376func (d *VoltDevice) GetPortIDFromPortName(portName string) uint32 {
377 logger.Debugw(ctx, "Get Port ID from the device", log.Fields{"PortName": portName})
378 var portID uint32
379 d.Ports.Range(func(key, value interface{}) bool {
380 vp := value.(*VoltPort)
381 if vp.Name == portName {
382 portID = vp.ID
383 }
384 return true
385 })
386 return portID
387}
388
Naveen Sampath04696f72022-06-13 15:19:14 +0530389// DelPort to delete port from the device
390func (d *VoltDevice) DelPort(port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530391 logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530392 if _, ok := d.Ports.Load(port); ok {
393 d.Ports.Delete(port)
394 } else {
395 logger.Warnw(ctx, "Port doesn't exist", log.Fields{"Device": d.Name, "Port": port})
396 }
397}
398
399// pushFlowsForUnis to send port-up-indication for uni ports.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530400func (d *VoltDevice) pushFlowsForUnis(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530401 logger.Info(ctx, "NNI Discovered, Sending Port UP Ind for UNIs")
402 d.Ports.Range(func(key, value interface{}) bool {
403 port := key.(string)
404 vp := value.(*VoltPort)
405
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530406 logger.Debugw(ctx, "NNI Discovered. Sending Port UP Ind for UNI", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530407 //Ignore if UNI port is not UP
408 if vp.State != PortStateUp {
409 return true
410 }
411
412 //Obtain all VPVs associated with the port
413 vnets, ok := GetApplication().VnetsByPort.Load(port)
414 if !ok {
415 return true
416 }
417
418 for _, vpv := range vnets.([]*VoltPortVnet) {
419 vpv.VpvLock.Lock()
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530420 vpv.PortUpInd(cntx, d, port, "")
Naveen Sampath04696f72022-06-13 15:19:14 +0530421 vpv.VpvLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +0530422 }
423 return true
424 })
425}
426
427// ----------------------------------------------------------
428// VOLT Application - hosts all other objects
429// ----------------------------------------------------------
430//
431// The VOLT application is a singleton implementation where
432// there is just one instance in the system and is the gateway
433// to all other components within the controller
434// The declaration of the singleton object
435var vapplication *VoltApplication
436
Akash Soni6f369452023-09-19 11:18:28 +0530437type VoltAppInterface interface {
438 AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
439 AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530440 AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16, nniPorts []string) error
Akash Soni6f369452023-09-19 11:18:28 +0530441 GetFlowProvisionStatus(portNo string) FlowProvisionStatus
442 DelServiceWithPrefix(cntx context.Context, prefix string) error
443 GetDevice(device string) *VoltDevice
444 GetTaskList(device string) map[int]*TaskInfo
445 AddMeterProf(cntx context.Context, cfg VoltMeter)
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530446 AddMvlanProfile(cntx context.Context, name string, mvlan of.VlanType, ponVlan of.VlanType, groups map[string][]string, isChannelBasedGroup bool, OLTSerialNum []string, activeChannelsPerPon uint32, proxy map[string]common.MulticastGroupProxy) error
Akash Soni6f369452023-09-19 11:18:28 +0530447 DelMvlanProfile(cntx context.Context, name string) error
448 GetMvlanProfileByTag(vlan of.VlanType) *MvlanProfile
449 AddMcastConfig(cntx context.Context, MvlanProfileID string, IgmpProfileID string, IgmpProxyIP string, OltSerialNum string) error
450 DelMeterProf(cntx context.Context, name string) error
451 GetMeterByName(name string) (*VoltMeter, bool)
452 UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig)
453 GetDeviceConfig(serNum string) *DeviceConfig
454 GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error)
455 GetAllMacLearnerInfo() ([]MacLearnerInfo, error)
456 GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error)
457 ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
458 DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
459 GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error)
460 UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService)
461 GetIgnoredPorts() (map[string][]string, error)
462}
463
Naveen Sampath04696f72022-06-13 15:19:14 +0530464// VoltApplication fields :
465// ServiceByName - Stores the services by the name as key
vinokuma926cb3e2023-03-29 11:41:06 +0530466// A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530467// VnetsByPort - Stores the VNETs by the ports configured
vinokuma926cb3e2023-03-29 11:41:06 +0530468// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530469// VnetsByTag - Stores the VNETs by the VLANS configured
vinokuma926cb3e2023-03-29 11:41:06 +0530470// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530471// VnetsByName - Stores the VNETs by the name configured
vinokuma926cb3e2023-03-29 11:41:06 +0530472// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530473// DevicesDisc - Stores the devices discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530474// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530475// PortsDisc - Stores the ports discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530476// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530477type VoltApplication struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530478 MeterMgr
vinokuma926cb3e2023-03-29 11:41:06 +0530479 DataMigrationInfo DataMigration
480 VnetsBySvlan *util.ConcurrentMap
481 IgmpGroupIds []*IgmpGroup
482 VoltPortVnetsToDelete map[*VoltPortVnet]bool
Akash Sonia8246972023-01-03 10:37:08 +0530483 IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
vinokuma926cb3e2023-03-29 11:41:06 +0530484 macPortMap map[string]string
Akash Sonia8246972023-01-03 10:37:08 +0530485 VnetsToDelete map[string]bool
Akash Sonief452f12024-12-12 18:20:28 +0530486 ServicesToDelete sync.Map
487 ServicesToDeactivate sync.Map
Akash Sonia8246972023-01-03 10:37:08 +0530488 PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
489 vendorID string
vinokuma926cb3e2023-03-29 11:41:06 +0530490 ServiceByName sync.Map // [serName]*VoltService
491 VnetsByPort sync.Map // [portName][]*VoltPortVnet
492 VnetsByTag sync.Map // [svlan-cvlan-uvlan]*VoltVnet
493 VnetsByName sync.Map // [vnetName]*VoltVnet
494 DevicesDisc sync.Map
495 PortsDisc sync.Map
496 IgmpGroups sync.Map // [grpKey]*IgmpGroup
497 MvlanProfilesByTag sync.Map
498 MvlanProfilesByName sync.Map
499 Icmpv6Receivers sync.Map
500 DeviceCounters sync.Map //[logicalDeviceId]*DeviceCounters
501 ServiceCounters sync.Map //[serviceName]*ServiceCounters
502 NbDevice sync.Map // [OLTSouthBoundID]*NbDevice
503 OltIgmpInfoBySerial sync.Map
504 McastConfigMap sync.Map //[OltSerialNo_MvlanProfileID]*McastConfig
Akash Sonia8246972023-01-03 10:37:08 +0530505 DevicesConfig sync.Map //[serialNumber]*DeviceConfig
vinokuma926cb3e2023-03-29 11:41:06 +0530506 IgmpProfilesByName sync.Map
507 IgmpTasks tasks.Tasks
508 IndicationsTasks tasks.Tasks
509 MulticastAlarmTasks tasks.Tasks
510 IgmpKPIsTasks tasks.Tasks
511 pppoeTasks tasks.Tasks
512 OltFlowServiceConfig OltFlowService
513 PendingPoolLock sync.RWMutex
514 // MacAddress-Port MAP to avoid swap of mac across ports.
515 macPortLock sync.RWMutex
516 portLock sync.Mutex
Akash Sonia8246972023-01-03 10:37:08 +0530517}
Naveen Sampath04696f72022-06-13 15:19:14 +0530518
Akash Sonia8246972023-01-03 10:37:08 +0530519type DeviceConfig struct {
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530520 SerialNumber string `json:"id"`
521 HardwareIdentifier string `json:"hardwareIdentifier"`
522 IPAddress string `json:"ipAddress"`
523 UplinkPort string `json:"uplinkPort"`
524 NasID string `json:"nasId"`
525 NniPorts []string `json:"nniPorts"`
526 NniDhcpTrapVid uint16 `json:"nniDhcpTrapVid"`
Naveen Sampath04696f72022-06-13 15:19:14 +0530527}
528
529// PonPortCfg contains NB port config and activeIGMPChannels count
530type PonPortCfg struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530531 PortAlarmProfileID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530532 PortID uint32
533 MaxActiveChannels uint32
534 ActiveIGMPChannels uint32
535 EnableMulticastKPI bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530536}
537
538// NbDevice OLT Device info
539type NbDevice struct {
540 SouthBoundID string
541 PonPorts sync.Map // [PortID]*PonPortCfg
542}
543
544// RestoreNbDeviceFromDb restores the NB Device in case of VGC pod restart.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530545func (va *VoltApplication) RestoreNbDeviceFromDb(cntx context.Context, deviceID string) *NbDevice {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530546 logger.Debugw(ctx, "Received Restore Nb Device From Db", log.Fields{"deviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530547 nbDevice := NewNbDevice()
548 nbDevice.SouthBoundID = deviceID
549
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530550 nbPorts, _ := db.GetAllNbPorts(cntx, deviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530551
552 for key, p := range nbPorts {
553 b, ok := p.Value.([]byte)
554 if !ok {
555 logger.Warn(ctx, "The value type is not []byte")
556 continue
557 }
558 var port PonPortCfg
559 err := json.Unmarshal(b, &port)
560 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530561 logger.Warnw(ctx, "Unmarshal of PonPortCfg failed", log.Fields{"deviceID": deviceID, "port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530562 continue
563 }
564 logger.Debugw(ctx, "Port recovered", log.Fields{"port": port})
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530565 ponPortID, err := strconv.ParseUint(key, 10, 32)
566 if err != nil {
567 logger.Errorw(ctx, "Error converting string to uint32:", log.Fields{"deviceID": deviceID, "error": err})
568 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530569 nbDevice.PonPorts.Store(uint32(ponPortID), &port)
570 }
571 va.NbDevice.Store(deviceID, nbDevice)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530572 logger.Debugw(ctx, "Recovered NbDevice From Db", log.Fields{"deviceID": deviceID, "nbDevice": nbDevice})
Naveen Sampath04696f72022-06-13 15:19:14 +0530573 return nbDevice
574}
575
576// NewNbDevice Constructor for NbDevice
577func NewNbDevice() *NbDevice {
578 var nbDevice NbDevice
579 return &nbDevice
580}
581
582// WriteToDb writes nb device port config to kv store
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530583func (nbd *NbDevice) WriteToDb(cntx context.Context, portID uint32, ponPort *PonPortCfg) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530584 b, err := json.Marshal(ponPort)
585 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530586 logger.Errorw(ctx, "PonPortConfig-marshal-failed", log.Fields{"err": err, "ponPort": ponPort})
Naveen Sampath04696f72022-06-13 15:19:14 +0530587 return
588 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530589 db.PutNbDevicePort(cntx, nbd.SouthBoundID, portID, string(b))
Naveen Sampath04696f72022-06-13 15:19:14 +0530590}
591
592// AddPortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530593func (nbd *NbDevice) AddPortToNbDevice(cntx context.Context, portID, allowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +0530594 enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530595 logger.Debugw(ctx, "AddPortToNbDevice", log.Fields{"PortID": portID, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530596 ponPort := &PonPortCfg{
597 PortID: portID,
598 MaxActiveChannels: allowedChannels,
599 EnableMulticastKPI: enableMulticastKPI,
600 PortAlarmProfileID: portAlarmProfileID,
601 }
602 nbd.PonPorts.Store(portID, ponPort)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530603 nbd.WriteToDb(cntx, portID, ponPort)
Naveen Sampath04696f72022-06-13 15:19:14 +0530604 return ponPort
605}
606
Akash Sonia8246972023-01-03 10:37:08 +0530607// RestoreDeviceConfigFromDb to restore vnet from port
608func (va *VoltApplication) RestoreDeviceConfigFromDb(cntx context.Context) {
609 // VNETS must be learnt first
610 dConfig, _ := db.GetDeviceConfig(cntx)
611 for _, device := range dConfig {
612 b, ok := device.Value.([]byte)
613 if !ok {
614 logger.Warn(ctx, "The value type is not []byte")
615 continue
616 }
617 devConfig := DeviceConfig{}
618 err := json.Unmarshal(b, &devConfig)
619 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530620 logger.Warnw(ctx, "Unmarshal of device configuration failed", log.Fields{"Device Config": devConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530621 continue
622 }
623 logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530624 if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid, devConfig.NniPorts); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530625 logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
626 }
Akash Sonia8246972023-01-03 10:37:08 +0530627 }
628}
629
630// WriteDeviceConfigToDb writes sb device config to kv store
631func (dc *DeviceConfig) WriteDeviceConfigToDb(cntx context.Context, serialNum string, deviceConfig *DeviceConfig) error {
632 b, err := json.Marshal(deviceConfig)
633 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530634 return fmt.Errorf("deviceConfig-marshal-failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530635 }
636 dberr := db.PutDeviceConfig(cntx, serialNum, string(b))
637 if dberr != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530638 return fmt.Errorf("update device config failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530639 }
640 return nil
641}
642
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530643func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16, nniPorts []string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530644 logger.Debugw(ctx, "Received Add device config", log.Fields{"SerialNumber": serialNum, "HardwareIdentifier": hardwareIdentifier, "NasID": nasID, "IPAddress": ipAddress, "UplinkPort": uplinkPort, "NniDhcpTrapID": nniDhcpTrapID})
Akash Sonia8246972023-01-03 10:37:08 +0530645 var dc *DeviceConfig
646
Akash Soni87a19072023-02-28 00:46:59 +0530647 deviceConfig := &DeviceConfig{
648 SerialNumber: serialNum,
649 HardwareIdentifier: hardwareIdentifier,
650 NasID: nasID,
651 UplinkPort: uplinkPort,
652 IPAddress: ipAddress,
vinokuma926cb3e2023-03-29 11:41:06 +0530653 NniDhcpTrapVid: nniDhcpTrapID,
Sridhar Ravindrab76eb162025-07-02 01:25:10 +0530654 NniPorts: nniPorts,
Akash Sonia8246972023-01-03 10:37:08 +0530655 }
Akash Soni87a19072023-02-28 00:46:59 +0530656 va.DevicesConfig.Store(serialNum, deviceConfig)
657 err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
658 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530659 return fmt.Errorf("DB update for device config failed - %w ", err)
Akash Soni87a19072023-02-28 00:46:59 +0530660 }
661
662 // If device is already discovered update the VoltDevice structure
663 device, id := va.GetDeviceBySerialNo(serialNum)
664 if device != nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530665 device.NniDhcpTrapVid = of.VlanType(nniDhcpTrapID)
Akash Soni87a19072023-02-28 00:46:59 +0530666 va.DevicesDisc.Store(id, device)
667 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530668 logger.Debugw(ctx, "Added device config", log.Fields{"Device Config": deviceConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530669 return nil
670}
671
672// GetDeviceConfig to get a device config.
673func (va *VoltApplication) GetDeviceConfig(serNum string) *DeviceConfig {
674 if d, ok := va.DevicesConfig.Load(serNum); ok {
675 return d.(*DeviceConfig)
676 }
677 return nil
678}
679
Naveen Sampath04696f72022-06-13 15:19:14 +0530680// UpdatePortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530681func (nbd *NbDevice) UpdatePortToNbDevice(cntx context.Context, portID, allowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530682 logger.Debugw(ctx, "Received Update Port To NbDevice", log.Fields{"portID": portID, "AllowedChannels": allowedChannels, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530683 p, exists := nbd.PonPorts.Load(portID)
684 if !exists {
685 logger.Errorw(ctx, "PON port not exists in nb-device", log.Fields{"portID": portID})
686 return nil
687 }
688 port := p.(*PonPortCfg)
689 if allowedChannels != 0 {
690 port.MaxActiveChannels = allowedChannels
691 port.EnableMulticastKPI = enableMulticastKPI
692 port.PortAlarmProfileID = portAlarmProfileID
693 }
694
695 nbd.PonPorts.Store(portID, port)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530696 nbd.WriteToDb(cntx, portID, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530697 return port
698}
699
700// DeletePortFromNbDevice Deletes pon port from NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530701func (nbd *NbDevice) DeletePortFromNbDevice(cntx context.Context, portID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530702 logger.Debugw(ctx, "Received Delete Port from NbDevice", log.Fields{"portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530703 if _, ok := nbd.PonPorts.Load(portID); ok {
704 nbd.PonPorts.Delete(portID)
705 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530706 db.DelNbDevicePort(cntx, nbd.SouthBoundID, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530707}
708
709// GetApplication : Interface to access the singleton object
710func GetApplication() *VoltApplication {
711 if vapplication == nil {
712 vapplication = newVoltApplication()
713 }
714 return vapplication
715}
716
717// newVoltApplication : Constructor for the singleton object. Hence this is not
718// an exported function
719func newVoltApplication() *VoltApplication {
720 var va VoltApplication
721 va.IgmpTasks.Initialize(context.TODO())
722 va.MulticastAlarmTasks.Initialize(context.TODO())
723 va.IgmpKPIsTasks.Initialize(context.TODO())
724 va.pppoeTasks.Initialize(context.TODO())
725 va.storeIgmpProfileMap(DefaultIgmpProfID, newDefaultIgmpProfile())
726 va.MeterMgr.Init()
727 va.AddIgmpGroups(5000)
728 va.macPortMap = make(map[string]string)
729 va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
730 va.VnetsBySvlan = util.NewConcurrentMap()
731 va.VnetsToDelete = make(map[string]bool)
Naveen Sampath04696f72022-06-13 15:19:14 +0530732 va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530733 go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
734 go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
Naveen Sampath04696f72022-06-13 15:19:14 +0530735 InitEventFuncMapper()
736 db = database.GetDatabase()
Akash Soni6f369452023-09-19 11:18:28 +0530737
Naveen Sampath04696f72022-06-13 15:19:14 +0530738 return &va
739}
740
vinokuma926cb3e2023-03-29 11:41:06 +0530741// GetFlowEventRegister - returs the register based on flow mod type
Naveen Sampath04696f72022-06-13 15:19:14 +0530742func (d *VoltDevice) GetFlowEventRegister(flowModType of.Command) (*util.ConcurrentMap, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530743 switch flowModType {
744 case of.CommandDel:
745 return d.FlowDelEventMap, nil
746 case of.CommandAdd:
747 return d.FlowAddEventMap, nil
748 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530749 logger.Warnw(ctx, "Unknown Flow Mod received", log.Fields{"flowModtype": flowModType})
Naveen Sampath04696f72022-06-13 15:19:14 +0530750 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530751 return util.NewConcurrentMap(), errors.New("unknown flow mod")
Naveen Sampath04696f72022-06-13 15:19:14 +0530752}
753
754// RegisterFlowAddEvent to register a flow event.
755func (d *VoltDevice) RegisterFlowAddEvent(cookie string, event *FlowEvent) {
756 logger.Debugw(ctx, "Registered Flow Add Event", log.Fields{"Cookie": cookie, "Event": event})
757 d.FlowAddEventMap.MapLock.Lock()
758 defer d.FlowAddEventMap.MapLock.Unlock()
759 d.FlowAddEventMap.Set(cookie, event)
760}
761
762// RegisterFlowDelEvent to register a flow event.
763func (d *VoltDevice) RegisterFlowDelEvent(cookie string, event *FlowEvent) {
764 logger.Debugw(ctx, "Registered Flow Del Event", log.Fields{"Cookie": cookie, "Event": event})
765 d.FlowDelEventMap.MapLock.Lock()
766 defer d.FlowDelEventMap.MapLock.Unlock()
767 d.FlowDelEventMap.Set(cookie, event)
768}
769
770// UnRegisterFlowEvent to unregister a flow event.
771func (d *VoltDevice) UnRegisterFlowEvent(cookie string, flowModType of.Command) {
772 logger.Debugw(ctx, "UnRegistered Flow Add Event", log.Fields{"Cookie": cookie, "Type": flowModType})
773 flowEventMap, err := d.GetFlowEventRegister(flowModType)
774 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530775 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowModType, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530776 return
777 }
778 flowEventMap.MapLock.Lock()
779 defer flowEventMap.MapLock.Unlock()
780 flowEventMap.Remove(cookie)
781}
782
783// AddIgmpGroups to add Igmp groups.
784func (va *VoltApplication) AddIgmpGroups(numOfGroups uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530785 logger.Debugw(ctx, "AddIgmpGroups", log.Fields{"NumOfGroups": numOfGroups})
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530786 var i uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530787 //TODO: Temp change to resolve group id issue in pOLT
788 //for i := 1; uint32(i) <= numOfGroups; i++ {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530789 for i = 2; i <= (numOfGroups + 1); i++ {
Naveen Sampath04696f72022-06-13 15:19:14 +0530790 ig := IgmpGroup{}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530791 ig.GroupID = i
Naveen Sampath04696f72022-06-13 15:19:14 +0530792 va.IgmpGroupIds = append(va.IgmpGroupIds, &ig)
793 }
794}
795
796// GetAvailIgmpGroupID to get id of available igmp group.
797func (va *VoltApplication) GetAvailIgmpGroupID() *IgmpGroup {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530798 logger.Info(ctx, "GetAvailIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530799 var ig *IgmpGroup
800 if len(va.IgmpGroupIds) > 0 {
801 ig, va.IgmpGroupIds = va.IgmpGroupIds[0], va.IgmpGroupIds[1:]
802 return ig
803 }
804 return nil
805}
806
807// GetIgmpGroupID to get id of igmp group.
808func (va *VoltApplication) GetIgmpGroupID(gid uint32) (*IgmpGroup, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530809 logger.Info(ctx, "GetIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530810 for id, ig := range va.IgmpGroupIds {
811 if ig.GroupID == gid {
812 va.IgmpGroupIds = append(va.IgmpGroupIds[0:id], va.IgmpGroupIds[id+1:]...)
813 return ig, nil
814 }
815 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530816 return nil, errors.New("group id missing")
Naveen Sampath04696f72022-06-13 15:19:14 +0530817}
818
819// PutIgmpGroupID to add id of igmp group.
820func (va *VoltApplication) PutIgmpGroupID(ig *IgmpGroup) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530821 logger.Debugw(ctx, "GetIgmpGroupID", log.Fields{"GroupID": ig.GroupID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530822 va.IgmpGroupIds = append([]*IgmpGroup{ig}, va.IgmpGroupIds[0:]...)
823}
824
vinokuma926cb3e2023-03-29 11:41:06 +0530825// RestoreUpgradeStatus - gets upgrade/migration status from DB and updates local flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826func (va *VoltApplication) RestoreUpgradeStatus(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530827 logger.Info(ctx, "Received Restore Upgrade Status")
Naveen Sampath04696f72022-06-13 15:19:14 +0530828 Migrate := new(DataMigration)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530829 if err := GetMigrationInfo(cntx, Migrate); err == nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530830 if Migrate.Status == MigrationInProgress {
831 isUpgradeComplete = false
832 return
833 }
834 }
835 isUpgradeComplete = true
836
837 logger.Infow(ctx, "Upgrade Status Restored", log.Fields{"Upgrade Completed": isUpgradeComplete})
838}
839
840// ReadAllFromDb : If we are restarted, learn from the database the current execution
841// stage
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530842func (va *VoltApplication) ReadAllFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530843 logger.Info(ctx, "Reading the meters from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530844 va.RestoreMetersFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530845 logger.Info(ctx, "Reading the VNETs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530846 va.RestoreVnetsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530847 logger.Info(ctx, "Reading the VPVs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530848 va.RestoreVpvsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530849 logger.Info(ctx, "Reading the Services from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530850 va.RestoreSvcsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530851 logger.Info(ctx, "Reading the MVLANs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530852 va.RestoreMvlansFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530853 logger.Info(ctx, "Reading the IGMP profiles from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530854 va.RestoreIGMPProfilesFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530855 logger.Info(ctx, "Reading the Mcast configs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530856 va.RestoreMcastConfigsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530857 logger.Info(ctx, "Reading the IGMP groups for DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530858 va.RestoreIgmpGroupsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530859 logger.Info(ctx, "Reading Upgrade status from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530860 va.RestoreUpgradeStatus(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530861 logger.Info(ctx, "Reading OltFlowService from DB")
862 va.RestoreOltFlowService(cntx)
Akash Sonia8246972023-01-03 10:37:08 +0530863 logger.Info(ctx, "Reading device config from DB")
864 va.RestoreDeviceConfigFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530865 logger.Info(ctx, "Reconciled from DB")
866}
867
vinokuma926cb3e2023-03-29 11:41:06 +0530868// InitStaticConfig to initialize static config.
Naveen Sampath04696f72022-06-13 15:19:14 +0530869func (va *VoltApplication) InitStaticConfig() {
870 va.InitIgmpSrcMac()
871}
872
873// SetVendorID to set vendor id
874func (va *VoltApplication) SetVendorID(vendorID string) {
875 va.vendorID = vendorID
876}
877
878// GetVendorID to get vendor id
879func (va *VoltApplication) GetVendorID() string {
880 return va.vendorID
881}
882
883// SetRebootFlag to set reboot flag
884func (va *VoltApplication) SetRebootFlag(flag bool) {
885 vgcRebooted = flag
886}
887
888// GetUpgradeFlag to get reboot status
889func (va *VoltApplication) GetUpgradeFlag() bool {
890 return isUpgradeComplete
891}
892
893// SetUpgradeFlag to set reboot status
894func (va *VoltApplication) SetUpgradeFlag(flag bool) {
895 isUpgradeComplete = flag
896}
897
898// ------------------------------------------------------------
899// Device related functions
900
901// AddDevice : Add a device and typically the device stores the NNI port on the device
902// The NNI port is used when the packets are emitted towards the network.
903// The outport is selected as the NNI port of the device. Today, we support
904// a single NNI port per OLT. This is true whether the network uses any
905// protection mechanism (LAG, ERPS, etc.). The aggregate of the such protection
906// is represented by a single NNI port
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530907func (va *VoltApplication) AddDevice(cntx context.Context, device string, slno, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530908 logger.Debugw(ctx, "Received Device Ind: Add", log.Fields{"Device": device, "SrNo": slno, "southBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530909 if _, ok := va.DevicesDisc.Load(device); ok {
910 logger.Warnw(ctx, "Device Exists", log.Fields{"Device": device})
911 }
912 d := NewVoltDevice(device, slno, southBoundID)
913
914 addPort := func(key, value interface{}) bool {
915 portID := key.(uint32)
916 port := value.(*PonPortCfg)
917 va.AggActiveChannelsCountForPonPort(device, portID, port)
918 d.ActiveChannelsPerPon.Store(portID, port)
919 return true
920 }
921 if nbDevice, exists := va.NbDevice.Load(southBoundID); exists {
922 // Pon Ports added before OLT activate.
923 nbDevice.(*NbDevice).PonPorts.Range(addPort)
924 } else {
925 // Check if NbPort exists in DB. VGC restart case.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530926 nbd := va.RestoreNbDeviceFromDb(cntx, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530927 nbd.PonPorts.Range(addPort)
928 }
929 va.DevicesDisc.Store(device, d)
930}
931
932// GetDevice to get a device.
933func (va *VoltApplication) GetDevice(device string) *VoltDevice {
934 if d, ok := va.DevicesDisc.Load(device); ok {
935 return d.(*VoltDevice)
936 }
937 return nil
938}
939
940// DelDevice to delete a device.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530941func (va *VoltApplication) DelDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530942 logger.Debugw(ctx, "Received Device Ind: Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530943 if vdIntf, ok := va.DevicesDisc.Load(device); ok {
944 vd := vdIntf.(*VoltDevice)
945 va.DevicesDisc.Delete(device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530946 _ = db.DelAllRoutesForDevice(cntx, device)
947 va.HandleFlowClearFlag(cntx, device, vd.SerialNum, vd.SouthBoundID)
948 _ = db.DelAllGroup(cntx, device)
949 _ = db.DelAllMeter(cntx, device)
950 _ = db.DelAllPorts(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530951 logger.Debugw(ctx, "Device deleted", log.Fields{"Device": device})
952 } else {
953 logger.Warnw(ctx, "Device Doesn't Exist", log.Fields{"Device": device})
954 }
955}
956
Akash Sonief452f12024-12-12 18:20:28 +0530957// CheckServiceExists to check if service exists for the given uniport and tech profile ID.
958func (va *VoltApplication) CheckServiceExists(port string, techProfID uint16) bool {
959 var serviceExists bool
960 va.ServiceByName.Range(func(key, existingServiceIntf interface{}) bool {
961 existingService := existingServiceIntf.(*VoltService)
962 if existingService.Port == port && existingService.TechProfileID == techProfID {
963 logger.Warnw(ctx, "Service already exists for same Port and TP. Ignoring add service request", log.Fields{"ExistingService": existingService.Name})
964 serviceExists = true
965 return false
966 }
967 return true
968 })
969 return serviceExists
970}
971
Naveen Sampath04696f72022-06-13 15:19:14 +0530972// GetDeviceBySerialNo to get a device by serial number.
973// TODO - Transform this into a MAP instead
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530974func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530975 logger.Debugw(ctx, "Received Device Ind: Get", log.Fields{"Serial Num": slno})
Naveen Sampath04696f72022-06-13 15:19:14 +0530976 var device *VoltDevice
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530977 var deviceID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530978 getserial := func(key interface{}, value interface{}) bool {
979 device = value.(*VoltDevice)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530980 deviceID = key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +0530981 return device.SerialNum != slno
982 }
983 va.DevicesDisc.Range(getserial)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530984 return device, deviceID
Naveen Sampath04696f72022-06-13 15:19:14 +0530985}
986
987// PortAddInd : This is a PORT add indication coming from the VPAgent, which is essentially
988// a request coming from VOLTHA. The device and identity of the port is provided
989// in this request. Add them to the application for further use
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530990func (va *VoltApplication) PortAddInd(cntx context.Context, device string, id uint32, portName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530991 logger.Debugw(ctx, "Received Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530992 va.portLock.Lock()
993 if d := va.GetDevice(device); d != nil {
994 p := d.AddPort(portName, id)
995 va.PortsDisc.Store(portName, p)
996 va.portLock.Unlock()
997 nni, _ := va.GetNniPort(device)
998 if nni == portName {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530999 d.pushFlowsForUnis(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301000 }
1001 } else {
1002 va.portLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301003 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +05301004 }
1005}
1006
1007// PortDelInd : Only the NNI ports are recorded in the device for now. When port delete
1008// arrives, only the NNI ports need adjustments.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301009func (va *VoltApplication) PortDelInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301010 logger.Debugw(ctx, "Received Port Ind: Delete", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301011 if d := va.GetDevice(device); d != nil {
1012 p := d.GetPort(port)
1013 if p != nil && p.State == PortStateUp {
1014 logger.Infow(ctx, "Port state is UP. Trigerring Port Down Ind before deleting", log.Fields{"Port": p})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301015 va.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301016 }
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05301017 // if RemoveFlowsOnDisable is flase, then flows will be existing till port delete. Remove the flows now
1018 if !va.OltFlowServiceConfig.RemoveFlowsOnDisable {
Akash Sonia8246972023-01-03 10:37:08 +05301019 vpvs, ok := va.VnetsByPort.Load(port)
1020 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05301021 logger.Infow(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
1022 } else {
1023 for _, vpv := range vpvs.([]*VoltPortVnet) {
1024 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301025 // Set delFlowsInDevice to true to delete flows only in DB/device during Port Delete.
1026 vpv.PortDownInd(cntx, device, port, true, true)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05301027 vpv.VpvLock.Unlock()
1028 }
1029 }
1030 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301031 va.portLock.Lock()
1032 defer va.portLock.Unlock()
1033 d.DelPort(port)
1034 if _, ok := va.PortsDisc.Load(port); ok {
1035 va.PortsDisc.Delete(port)
1036 }
1037 } else {
1038 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Delete", log.Fields{"Device": device, "Port": port})
1039 }
1040}
1041
vinokuma926cb3e2023-03-29 11:41:06 +05301042// PortUpdateInd Updates port Id incase of ONU movement
Naveen Sampath04696f72022-06-13 15:19:14 +05301043func (va *VoltApplication) PortUpdateInd(device string, portName string, id uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301044 logger.Debugw(ctx, "Received Port Ind: Update", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301045 va.portLock.Lock()
1046 defer va.portLock.Unlock()
1047 if d := va.GetDevice(device); d != nil {
1048 vp := d.GetPort(portName)
1049 vp.ID = id
1050 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301051 logger.Warnw(ctx, "Device Not Found", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301052 }
1053}
1054
1055// AddNbPonPort Add pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301056func (va *VoltApplication) AddNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +05301057 enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301058 logger.Debugw(ctx, "Received NbPonPort Ind: Add", log.Fields{"oltSbID": oltSbID, "portID": portID, "maxAllowedChannels": maxAllowedChannels, "enableMulticastKPI": enableMulticastKPI, "portAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301059 var nbd *NbDevice
1060 nbDevice, ok := va.NbDevice.Load(oltSbID)
1061
1062 if !ok {
1063 nbd = NewNbDevice()
1064 nbd.SouthBoundID = oltSbID
1065 } else {
1066 nbd = nbDevice.(*NbDevice)
1067 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301068 port := nbd.AddPortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301069 logger.Debugw(ctx, "Added Port To NbDevice", log.Fields{"port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301070 // Add this port to voltDevice
1071 addPort := func(key, value interface{}) bool {
1072 voltDevice := value.(*VoltDevice)
1073 if oltSbID == voltDevice.SouthBoundID {
1074 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); !exists {
1075 voltDevice.ActiveChannelsPerPon.Store(portID, port)
1076 }
1077 return false
1078 }
1079 return true
1080 }
1081 va.DevicesDisc.Range(addPort)
1082 va.NbDevice.Store(oltSbID, nbd)
1083
1084 return nil
1085}
1086
1087// UpdateNbPonPort update pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301088func (va *VoltApplication) UpdateNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301089 logger.Debugw(ctx, "Received NbPonPort Ind: Update", log.Fields{"oltSbID": oltSbID, "portID": portID, "maxAllowedChannels": maxAllowedChannels, "enableMulticastKPI": enableMulticastKPI, "portAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301090 var nbd *NbDevice
1091 nbDevice, ok := va.NbDevice.Load(oltSbID)
1092
1093 if !ok {
1094 logger.Errorw(ctx, "Device-doesn't-exists", log.Fields{"deviceID": oltSbID})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301095 return fmt.Errorf("device-doesn't-exists - %s", oltSbID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301096 }
1097 nbd = nbDevice.(*NbDevice)
1098
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301099 port := nbd.UpdatePortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301100 if port == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301101 return fmt.Errorf("port-doesn't-exists-%d", portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301102 }
1103 va.NbDevice.Store(oltSbID, nbd)
1104
1105 // Add this port to voltDevice
1106 updPort := func(key, value interface{}) bool {
1107 voltDevice := value.(*VoltDevice)
1108 if oltSbID == voltDevice.SouthBoundID {
1109 voltDevice.ActiveChannelCountLock.Lock()
1110 if p, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1111 oldPort := p.(*PonPortCfg)
1112 if port.MaxActiveChannels != 0 {
1113 oldPort.MaxActiveChannels = port.MaxActiveChannels
1114 oldPort.EnableMulticastKPI = port.EnableMulticastKPI
1115 voltDevice.ActiveChannelsPerPon.Store(portID, oldPort)
1116 }
1117 }
1118 voltDevice.ActiveChannelCountLock.Unlock()
1119 return false
1120 }
1121 return true
1122 }
1123 va.DevicesDisc.Range(updPort)
1124
1125 return nil
1126}
1127
1128// DeleteNbPonPort Delete pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129func (va *VoltApplication) DeleteNbPonPort(cntx context.Context, oltSbID string, portID uint32) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301130 logger.Debugw(ctx, "Received NbPonPort Ind: Delete", log.Fields{"oltSbID": oltSbID, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301131 nbDevice, ok := va.NbDevice.Load(oltSbID)
1132 if ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301133 nbDevice.(*NbDevice).DeletePortFromNbDevice(cntx, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301134 va.NbDevice.Store(oltSbID, nbDevice.(*NbDevice))
1135 } else {
1136 logger.Warnw(ctx, "Delete pon received for unknown device", log.Fields{"oltSbID": oltSbID})
1137 return nil
1138 }
1139 // Delete this port from voltDevice
1140 delPort := func(key, value interface{}) bool {
1141 voltDevice := value.(*VoltDevice)
1142 if oltSbID == voltDevice.SouthBoundID {
1143 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1144 voltDevice.ActiveChannelsPerPon.Delete(portID)
1145 }
1146 return false
1147 }
1148 return true
1149 }
1150 va.DevicesDisc.Range(delPort)
1151 return nil
1152}
1153
1154// GetNniPort : Get the NNI port for a device. Called from different other applications
1155// as a port to match or destination for a packet out. The VOLT application
1156// is written with the assumption that there is a single NNI port. The OLT
1157// device is responsible for translating the combination of VLAN and the
1158// NNI port ID to identify possibly a single physical port or a logical
1159// port which is a result of protection methods applied.
1160func (va *VoltApplication) GetNniPort(device string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301161 logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301162 d, ok := va.DevicesDisc.Load(device)
1163 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301164 return "", errors.New("device doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301165 }
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301166 devConfig := va.GetDeviceConfig(d.(*VoltDevice).SerialNum)
1167 if devConfig == nil {
1168 return "", fmt.Errorf("device config not found for serial number %s", d.(*VoltDevice).SerialNum)
1169 }
1170 if len(d.(*VoltDevice).NniPort) > 0 {
1171 for _, nniPort := range d.(*VoltDevice).NniPort {
1172 nniPortID, err := GetApplication().GetPortID(nniPort)
1173 if err != nil {
1174 logger.Errorw(ctx, "Error getting port ID by port Name", log.Fields{"Error": err})
1175 continue
1176 }
1177 if devConfig.UplinkPort == strconv.Itoa(int(nniPortID)) {
1178 logger.Debugw(ctx, "NNI port configured from NB", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI Ports": d.(*VoltDevice).NniPort})
1179 return nniPort, nil // Match found
1180 }
1181 }
1182 }
1183 // If no matching NNI port is found, return an error
1184 return "", errors.New("nni port doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301185}
1186
1187// NniDownInd process for Nni down indication.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301188func (va *VoltApplication) NniDownInd(cntx context.Context, deviceID string, devSrNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301189 logger.Debugw(ctx, "NNI Down Ind", log.Fields{"DeviceID": deviceID, "Device SrNo": devSrNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301190
1191 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1192 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301193 mvProfile.removeIgmpMcastFlows(cntx, devSrNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301194 return true
1195 }
1196 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1197
1198 //Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301199 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301200}
1201
1202// DeviceUpInd changes device state to up.
1203func (va *VoltApplication) DeviceUpInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301204 logger.Infow(ctx, "Received Device Ind: UP", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301205 if d := va.GetDevice(device); d != nil {
1206 d.State = controller.DeviceStateUP
1207 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301208 logger.Warnw(ctx, "Ignoring Device indication: UP. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301209 }
1210}
1211
1212// DeviceDownInd changes device state to down.
1213func (va *VoltApplication) DeviceDownInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301214 logger.Infow(ctx, "Received Device Ind: DOWN", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301215 if d := va.GetDevice(device); d != nil {
1216 d.State = controller.DeviceStateDOWN
1217 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301218 logger.Warnw(ctx, "Ignoring Device indication: DOWN. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301219 }
1220}
1221
1222// DeviceRebootInd process for handling flow clear flag for device reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301223func (va *VoltApplication) DeviceRebootInd(cntx context.Context, device string, serialNum string, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301224 logger.Infow(ctx, "Received Device Ind: Reboot", log.Fields{"Device": device, "SerialNumber": serialNum, "SouthBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301225
1226 if d := va.GetDevice(device); d != nil {
1227 if d.State == controller.DeviceStateREBOOTED {
1228 logger.Warnw(ctx, "Ignoring Device Ind: Reboot, Device already in Reboot state", log.Fields{"Device": device, "SerialNumber": serialNum, "State": d.State})
1229 return
1230 }
1231 d.State = controller.DeviceStateREBOOTED
1232 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301233 va.HandleFlowClearFlag(cntx, device, serialNum, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301234}
1235
1236// DeviceDisableInd handles device deactivation process
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301237func (va *VoltApplication) DeviceDisableInd(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301238 logger.Infow(ctx, "Received Device Ind: Disable", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301239
1240 d := va.GetDevice(device)
1241 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301242 logger.Warnw(ctx, "Ignoring Device indication: DISABLED. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301243 return
1244 }
1245
1246 d.State = controller.DeviceStateDISABLED
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301247 va.HandleFlowClearFlag(cntx, device, d.SerialNum, d.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301248}
1249
1250// ProcessIgmpDSFlowForMvlan for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301251func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301252 logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
1253 portState := false
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301254 nniPort, err := va.GetNniPort(d.Name)
1255 if err != nil {
1256 logger.Errorw(ctx, "Error gettin NNI port", log.Fields{"Error": err})
1257 }
1258 p := d.GetPort(nniPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301259 if p != nil && p.State == PortStateUp {
1260 portState = true
1261 }
1262
1263 if addFlow {
1264 if portState {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301265 mvp.pushIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301266 }
1267 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301268 mvp.removeIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301269 }
1270}
1271
1272// ProcessIgmpDSFlowForDevice for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301273func (va *VoltApplication) ProcessIgmpDSFlowForDevice(cntx context.Context, d *VoltDevice, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301274 logger.Debugw(ctx, "Process IGMP DS Flows for device", log.Fields{"device": d.Name, "addFlow": addFlow})
1275
1276 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1277 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301278 va.ProcessIgmpDSFlowForMvlan(cntx, d, mvProfile, addFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301279 return true
1280 }
1281 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1282}
1283
1284// GetDeviceFromPort : This is suitable only for access ports as their naming convention
1285// makes them unique across all the OLTs. This must be called with
1286// port name that is an access port. Currently called from VNETs, attached
1287// only to access ports, and the services which are also attached only
1288// to access ports
1289func (va *VoltApplication) GetDeviceFromPort(port string) (*VoltDevice, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301290 logger.Debugw(ctx, "Received Get Device From Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301291 va.portLock.Lock()
1292 defer va.portLock.Unlock()
1293 var err error
1294 err = nil
1295 p, ok := va.PortsDisc.Load(port)
1296 if !ok {
1297 return nil, errorCodes.ErrPortNotFound
1298 }
1299 d := va.GetDevice(p.(*VoltPort).Device)
1300 if d == nil {
1301 err = errorCodes.ErrDeviceNotFound
1302 }
1303 return d, err
1304}
1305
1306// GetPortID : This too applies only to access ports. The ports can be indexed
1307// purely by their names without the device forming part of the key
1308func (va *VoltApplication) GetPortID(port string) (uint32, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301309 logger.Debugw(ctx, "Received Get Port ID", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301310 va.portLock.Lock()
1311 defer va.portLock.Unlock()
1312 p, ok := va.PortsDisc.Load(port)
1313 if !ok {
1314 return 0, errorCodes.ErrPortNotFound
1315 }
1316 return p.(*VoltPort).ID, nil
1317}
1318
1319// GetPortName : This too applies only to access ports. The ports can be indexed
1320// purely by their names without the device forming part of the key
1321func (va *VoltApplication) GetPortName(port uint32) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301322 logger.Debugw(ctx, "Received Get Port Name", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301323 va.portLock.Lock()
1324 defer va.portLock.Unlock()
1325 var portName string
1326 va.PortsDisc.Range(func(key interface{}, value interface{}) bool {
1327 portInfo := value.(*VoltPort)
1328 if portInfo.ID == port {
1329 portName = portInfo.Name
1330 return false
1331 }
1332 return true
1333 })
1334 return portName, nil
1335}
1336
1337// GetPonFromUniPort to get Pon info from UniPort
1338func (va *VoltApplication) GetPonFromUniPort(port string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301339 logger.Debugw(ctx, "Received Get Pon From UniPort", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301340 uniPortID, err := va.GetPortID(port)
1341 if err == nil {
1342 ponPortID := (uniPortID & 0x0FF00000) >> 20 //pon(8) + onu(8) + uni(12)
1343 return strconv.FormatUint(uint64(ponPortID), 10), nil
1344 }
1345 return "", err
1346}
1347
1348// GetPortState : This too applies only to access ports. The ports can be indexed
1349// purely by their names without the device forming part of the key
1350func (va *VoltApplication) GetPortState(port string) (PortState, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301351 logger.Debugw(ctx, "Received Get Port State", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301352 va.portLock.Lock()
1353 defer va.portLock.Unlock()
1354 p, ok := va.PortsDisc.Load(port)
1355 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301356 return 0, errors.New("port not configured")
Naveen Sampath04696f72022-06-13 15:19:14 +05301357 }
1358 return p.(*VoltPort).State, nil
1359}
1360
1361// GetIcmpv6Receivers to get Icmp v6 receivers
1362func (va *VoltApplication) GetIcmpv6Receivers(device string) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301363 logger.Debugw(ctx, "Get Icmpv6 Receivers", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301364 var receiverList []uint32
1365 receivers, _ := va.Icmpv6Receivers.Load(device)
1366 if receivers != nil {
1367 receiverList = receivers.([]uint32)
1368 }
1369 return receiverList
1370}
1371
1372// AddIcmpv6Receivers to add Icmp v6 receivers
1373func (va *VoltApplication) AddIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301374 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301375 var receiverList []uint32
1376 receivers, _ := va.Icmpv6Receivers.Load(device)
1377 if receivers != nil {
1378 receiverList = receivers.([]uint32)
1379 }
1380 receiverList = append(receiverList, portID)
1381 va.Icmpv6Receivers.Store(device, receiverList)
1382 logger.Debugw(ctx, "Receivers after addition", log.Fields{"Receivers": receiverList})
1383 return receiverList
1384}
1385
1386// DelIcmpv6Receivers to delete Icmp v6 receievers
1387func (va *VoltApplication) DelIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301388 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301389 var receiverList []uint32
1390 receivers, _ := va.Icmpv6Receivers.Load(device)
1391 if receivers != nil {
1392 receiverList = receivers.([]uint32)
1393 }
1394 for i, port := range receiverList {
1395 if port == portID {
1396 receiverList = append(receiverList[0:i], receiverList[i+1:]...)
1397 va.Icmpv6Receivers.Store(device, receiverList)
1398 break
1399 }
1400 }
1401 logger.Debugw(ctx, "Receivers After deletion", log.Fields{"Receivers": receiverList})
1402 return receiverList
1403}
1404
1405// ProcessDevFlowForDevice - Process DS ICMPv6 & ARP flow for provided device and vnet profile
1406// device - Device Obj
1407// vnet - vnet profile name
1408// enabled - vlan enabled/disabled - based on the status, the flow shall be added/removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301409func (va *VoltApplication) ProcessDevFlowForDevice(cntx context.Context, device *VoltDevice, vnet *VoltVnet, enabled bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301410 logger.Debugw(ctx, "Process Dev Flow For Device", log.Fields{"Device": device, "VnetName": vnet.Name, "Enabled": enabled})
Naveen Sampath04696f72022-06-13 15:19:14 +05301411 _, applied := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0))
1412 if enabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301413 va.PushDevFlowForVlan(cntx, vnet)
Naveen Sampath04696f72022-06-13 15:19:14 +05301414 } else if !enabled && applied {
1415 //va.DeleteDevFlowForVlan(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301416 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, device.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301417 }
1418}
1419
vinokuma926cb3e2023-03-29 11:41:06 +05301420// NniVlanIndToIgmp - Trigger receiver up indication to all ports with igmp enabled
1421// and has the provided mvlan
Naveen Sampath04696f72022-06-13 15:19:14 +05301422func (va *VoltApplication) NniVlanIndToIgmp(device *VoltDevice, mvp *MvlanProfile) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301423 logger.Infow(ctx, "Received Nni Vlan Ind To Igmp", log.Fields{"Vlan": mvp.Mvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301424
vinokuma926cb3e2023-03-29 11:41:06 +05301425 // Trigger nni indication for receiver only for first time
Naveen Sampath04696f72022-06-13 15:19:14 +05301426 if device.IgmpDsFlowAppliedForMvlan[uint16(mvp.Mvlan)] {
1427 return
1428 }
1429 device.Ports.Range(func(key, value interface{}) bool {
1430 port := key.(string)
1431
1432 if state, _ := va.GetPortState(port); state == PortStateUp {
1433 vpvs, _ := va.VnetsByPort.Load(port)
1434 if vpvs == nil {
1435 return true
1436 }
1437 for _, vpv := range vpvs.([]*VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05301438 // Send indication only for subscribers with the received mvlan profile
Naveen Sampath04696f72022-06-13 15:19:14 +05301439 if vpv.IgmpEnabled && vpv.MvlanProfileName == mvp.Name {
1440 vpv.services.Range(ReceiverUpInd)
1441 }
1442 }
1443 }
1444 return true
1445 })
1446}
1447
1448// PortUpInd :
1449// -----------------------------------------------------------------------
1450// Port status change handling
1451// ----------------------------------------------------------------------
1452// Port UP indication is passed to all services associated with the port
1453// so that the services can configure flows applicable when the port goes
1454// up from down state
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301455func (va *VoltApplication) PortUpInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301456 logger.Infow(ctx, "Received Southbound Port Ind: UP", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301457 d := va.GetDevice(device)
1458
1459 if d == nil {
1460 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: UP", log.Fields{"Device": device, "Port": port})
1461 return
1462 }
1463
vinokuma926cb3e2023-03-29 11:41:06 +05301464 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301465 va.portLock.Lock()
1466 // Do not defer the port mutex unlock here
1467 // Some of the following func calls needs the port lock, so defering the lock here
1468 // may lead to dead-lock
1469 p := d.GetPort(port)
1470
1471 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301472 logger.Warnw(ctx, "Ignoring Port Ind: UP, Port doesnt exist", log.Fields{"Device": device, "PortName": port, "PortId": p})
Naveen Sampath04696f72022-06-13 15:19:14 +05301473 va.portLock.Unlock()
1474 return
1475 }
1476 p.State = PortStateUp
1477 va.portLock.Unlock()
1478
Naveen Sampath04696f72022-06-13 15:19:14 +05301479 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301480 logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301481 if d.NniDhcpTrapVid == 1 {
1482 err := va.AddDefaultDhcpTrapFlow(cntx, d, p)
1483 if err != nil {
1484 logger.Errorw(ctx, "Failed adding DHCP trap flow", log.Fields{"Device": device, "PortName": port, "PortId": p.ID, "error": err})
1485 }
1486 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301487 }
1488 vpvs, ok := va.VnetsByPort.Load(port)
1489 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301490 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301491 //msgbus.ProcessPortInd(msgbus.PortUp, d.SerialNum, p.Name, false, getServiceList(port))
1492 return
1493 }
1494
vinokuma926cb3e2023-03-29 11:41:06 +05301495 // If NNI port is not UP, do not push Flows
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301496 if len(d.NniPort) == 0 {
Naveen Sampath04696f72022-06-13 15:19:14 +05301497 logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
1498 return
1499 }
1500
Naveen Sampath04696f72022-06-13 15:19:14 +05301501 for _, vpv := range vpvs.([]*VoltPortVnet) {
1502 vpv.VpvLock.Lock()
vinokuma926cb3e2023-03-29 11:41:06 +05301503 // If no service is activated drop the portUpInd
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301504 if ok, nniPort := vpv.IsServiceActivated(cntx); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301505 // Do not trigger indication for the vpv which is already removed from vpv list as
Tinoj Josephec742f62022-09-29 19:11:10 +05301506 // part of service delete (during the lock wait duration)
1507 // In that case, the services associated wil be zero
1508 if vpv.servicesCount.Load() != 0 {
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301509 vpv.PortUpInd(cntx, d, port, nniPort)
Tinoj Josephec742f62022-09-29 19:11:10 +05301510 }
1511 } else {
1512 // Service not activated, still attach device to service
1513 vpv.setDevice(d.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301514 }
1515 vpv.VpvLock.Unlock()
1516 }
1517 // At the end of processing inform the other entities that
1518 // are interested in the events
1519}
1520
1521/*
1522func getServiceList(port string) map[string]bool {
1523 serviceList := make(map[string]bool)
1524
1525 getServiceNames := func(key interface{}, value interface{}) bool {
1526 serviceList[key.(string)] = value.(*VoltService).DsHSIAFlowsApplied
1527 return true
1528 }
1529
1530 if vpvs, _ := GetApplication().VnetsByPort.Load(port); vpvs != nil {
1531 vpvList := vpvs.([]*VoltPortVnet)
1532 for _, vpv := range vpvList {
1533 vpv.services.Range(getServiceNames)
1534 }
1535 }
1536 return serviceList
1537
1538}*/
1539
vinokuma926cb3e2023-03-29 11:41:06 +05301540// ReceiverUpInd - Send receiver up indication for service with Igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301541func ReceiverUpInd(key, value interface{}) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301542 logger.Info(ctx, "Receiver Indication: UP")
Naveen Sampath04696f72022-06-13 15:19:14 +05301543 svc := value.(*VoltService)
1544 var vlan of.VlanType
1545
1546 if !svc.IPAssigned() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301547 logger.Warnw(ctx, "IP Not assigned, skipping general query", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +05301548 return false
1549 }
1550
vinokuma926cb3e2023-03-29 11:41:06 +05301551 // Send port up indication to igmp only for service with igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301552 if svc.IgmpEnabled {
1553 if svc.VlanControl == ONUCVlan || svc.VlanControl == ONUCVlanOLTSVlan {
1554 vlan = svc.CVlan
1555 } else {
1556 vlan = svc.UniVlan
1557 }
1558 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
1559 GetApplication().ReceiverUpInd(device.Name, svc.Port, svc.MvlanProfileName, vlan, svc.Pbits)
1560 }
1561 return false
1562 }
1563 return true
1564}
1565
1566// PortDownInd : Port down indication is passed on to the services so that the services
1567// can make changes at this transition.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301568func (va *VoltApplication) PortDownInd(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301569 logger.Infow(ctx, "Received SouthBound Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1570 d := va.GetDevice(device)
1571
1572 if d == nil {
1573 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1574 return
1575 }
vinokuma926cb3e2023-03-29 11:41:06 +05301576 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301577 va.portLock.Lock()
1578 // Do not defer the port mutex unlock here
1579 // Some of the following func calls needs the port lock, so defering the lock here
1580 // may lead to dead-lock
1581 p := d.GetPort(port)
1582 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301583 logger.Warnw(ctx, "Ignoring Port Ind: Down, Port doesnt exist", log.Fields{"Device": device, "PortName": port, "PortId": p})
Naveen Sampath04696f72022-06-13 15:19:14 +05301584 va.portLock.Unlock()
1585 return
1586 }
1587 p.State = PortStateDown
1588 va.portLock.Unlock()
1589
1590 if d.State == controller.DeviceStateREBOOTED {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301591 logger.Warnw(ctx, "Ignoring Port Ind: Down, Device has been Rebooted", log.Fields{"Device": device, "PortName": port, "PortId": p})
Naveen Sampath04696f72022-06-13 15:19:14 +05301592 return
1593 }
1594
1595 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301596 logger.Debugw(ctx, "Received NNI Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301597 va.DeleteDevFlowForDevice(cntx, d)
1598 va.NniDownInd(cntx, device, d.SerialNum)
1599 va.RemovePendingGroups(cntx, device, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301600 }
1601 vpvs, ok := va.VnetsByPort.Load(port)
1602 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301603 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301604 //msgbus.ProcessPortInd(msgbus.PortDown, d.SerialNum, p.Name, false, getServiceList(port))
1605 return
1606 }
Akash Sonia8246972023-01-03 10:37:08 +05301607
Naveen Sampath04696f72022-06-13 15:19:14 +05301608 for _, vpv := range vpvs.([]*VoltPortVnet) {
1609 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301610 vpv.PortDownInd(cntx, device, port, false, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301611 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301612 va.ReceiverDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301613 }
1614 vpv.VpvLock.Unlock()
1615 }
1616}
1617
1618// PacketInInd :
1619// -----------------------------------------------------------------------
1620// PacketIn Processing
1621// Packet In Indication processing. It arrives with the identities of
1622// the device and port on which the packet is received. At first, the
1623// packet is decoded and the right processor is called. Currently, we
1624// plan to support only DHCP and IGMP. In future, we can add more
1625// capabilities as needed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301626func (va *VoltApplication) PacketInInd(cntx context.Context, device string, port string, pkt []byte) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301627 logger.Infow(ctx, "Received a Packet-In Indication", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301628 // Decode the incoming packet
1629 packetSide := US
1630 if strings.Contains(port, NNI) {
1631 packetSide = DS
1632 }
1633
Naveen Sampath04696f72022-06-13 15:19:14 +05301634 gopkt := gopacket.NewPacket(pkt, layers.LayerTypeEthernet, gopacket.Default)
1635
1636 var dot1qFound = false
1637 for _, l := range gopkt.Layers() {
1638 if l.LayerType() == layers.LayerTypeDot1Q {
1639 dot1qFound = true
1640 break
1641 }
1642 }
1643
1644 if !dot1qFound {
1645 logger.Debugw(ctx, "Ignoring Received Packet-In Indication without Dot1Q Header",
1646 log.Fields{"Device": device, "Port": port})
1647 return
1648 }
1649
1650 logger.Debugw(ctx, "Received Southbound Packet In", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1651
1652 // Classify the packet into packet types that we support
1653 // The supported types are DHCP and IGMP. The DHCP packet is
1654 // identified by matching the L4 protocol to UDP. The IGMP packet
1655 // is identified by matching L3 protocol to IGMP
1656 arpl := gopkt.Layer(layers.LayerTypeARP)
1657 if arpl != nil {
1658 if callBack, ok := PacketHandlers[ARP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301659 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301660 } else {
1661 logger.Debugw(ctx, "ARP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1662 }
1663 return
1664 }
1665 ipv4l := gopkt.Layer(layers.LayerTypeIPv4)
1666 if ipv4l != nil {
1667 ip := ipv4l.(*layers.IPv4)
1668
1669 if ip.Protocol == layers.IPProtocolUDP {
1670 logger.Debugw(ctx, "Received Southbound UDP ipv4 packet in", log.Fields{"StreamSide": packetSide})
1671 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv4)
1672 if dhcpl != nil {
1673 if callBack, ok := PacketHandlers[DHCPv4]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301674 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301675 } else {
1676 logger.Debugw(ctx, "DHCPv4 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1677 }
1678 }
1679 } else if ip.Protocol == layers.IPProtocolIGMP {
1680 logger.Debugw(ctx, "Received Southbound IGMP packet in", log.Fields{"StreamSide": packetSide})
1681 if callBack, ok := PacketHandlers[IGMP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301682 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301683 } else {
1684 logger.Debugw(ctx, "IGMP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1685 }
1686 }
1687 return
1688 }
1689 ipv6l := gopkt.Layer(layers.LayerTypeIPv6)
1690 if ipv6l != nil {
1691 ip := ipv6l.(*layers.IPv6)
1692 if ip.NextHeader == layers.IPProtocolUDP {
1693 logger.Debug(ctx, "Received Southbound UDP ipv6 packet in")
1694 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv6)
1695 if dhcpl != nil {
1696 if callBack, ok := PacketHandlers[DHCPv6]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301697 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301698 } else {
1699 logger.Debugw(ctx, "DHCPv6 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1700 }
1701 }
1702 }
1703 return
1704 }
1705
1706 pppoel := gopkt.Layer(layers.LayerTypePPPoE)
1707 if pppoel != nil {
1708 logger.Debugw(ctx, "Received Southbound PPPoE packet in", log.Fields{"StreamSide": packetSide})
1709 if callBack, ok := PacketHandlers[PPPOE]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301710 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301711 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301712 logger.Warnw(ctx, "PPPoE handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
Naveen Sampath04696f72022-06-13 15:19:14 +05301713 }
1714 }
1715}
1716
1717// GetVlans : This utility gets the VLANs from the packet. The VLANs are
1718// used to identify the right service that must process the incoming
1719// packet
1720func GetVlans(pkt gopacket.Packet) []of.VlanType {
1721 var vlans []of.VlanType
1722 for _, l := range pkt.Layers() {
1723 if l.LayerType() == layers.LayerTypeDot1Q {
1724 q, ok := l.(*layers.Dot1Q)
1725 if ok {
1726 vlans = append(vlans, of.VlanType(q.VLANIdentifier))
1727 }
1728 }
1729 }
1730 return vlans
1731}
1732
1733// GetPriority to get priority
1734func GetPriority(pkt gopacket.Packet) uint8 {
1735 for _, l := range pkt.Layers() {
1736 if l.LayerType() == layers.LayerTypeDot1Q {
1737 q, ok := l.(*layers.Dot1Q)
1738 if ok {
1739 return q.Priority
1740 }
1741 }
1742 }
1743 return PriorityNone
1744}
1745
1746// HandleFlowClearFlag to handle flow clear flag during reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301747func (va *VoltApplication) HandleFlowClearFlag(cntx context.Context, deviceID string, serialNum, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301748 logger.Infow(ctx, "Clear All flags for Device", log.Fields{"Device": deviceID, "SerialNum": serialNum, "SBID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301749 dev, ok := va.DevicesDisc.Load(deviceID)
1750 if ok && dev != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301751 logger.Debugw(ctx, "Clear Flags for device", log.Fields{"voltDevice": dev.(*VoltDevice).Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301752 dev.(*VoltDevice).icmpv6GroupAdded = false
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301753 logger.Debugw(ctx, "Clearing DS Icmpv6 Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301754 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1755 dev.(*VoltDevice).ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301756 logger.Debugw(ctx, "Clearing DS IGMP Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301757 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1758 for k := range dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan {
1759 delete(dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan, k)
1760 }
vinokuma926cb3e2023-03-29 11:41:06 +05301761 // Delete group 1 - ICMPv6/ARP group
Naveen Sampath04696f72022-06-13 15:19:14 +05301762 if err := ProcessIcmpv6McGroup(deviceID, true); err != nil {
1763 logger.Errorw(ctx, "ProcessIcmpv6McGroup failed", log.Fields{"Device": deviceID, "Error": err})
1764 }
1765 } else {
1766 logger.Warnw(ctx, "VoltDevice not found for device ", log.Fields{"deviceID": deviceID})
1767 }
1768
1769 getVpvs := func(key interface{}, value interface{}) bool {
1770 vpvs := value.([]*VoltPortVnet)
1771 for _, vpv := range vpvs {
1772 if vpv.Device == deviceID {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301773 logger.Debugw(ctx, "Clear Flags for vpv",
Naveen Sampath04696f72022-06-13 15:19:14 +05301774 log.Fields{"device": vpv.Device, "port": vpv.Port,
1775 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301776 vpv.ClearAllServiceFlags(cntx)
1777 vpv.ClearAllVpvFlags(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301778
1779 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301780 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05301781 // Also clear service igmp stats
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301782 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301783 }
1784 }
1785 }
1786 return true
1787 }
1788 va.VnetsByPort.Range(getVpvs)
1789
vinokuma926cb3e2023-03-29 11:41:06 +05301790 // Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301791 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301792
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301793 logger.Infow(ctx, "All flags cleared for device", log.Fields{"Device": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301794
vinokuma926cb3e2023-03-29 11:41:06 +05301795 // Reset pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301796 va.RemovePendingGroups(cntx, deviceID, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301797
vinokuma926cb3e2023-03-29 11:41:06 +05301798 // Process all Migrate Service Request - force udpate all profiles since resources are already cleaned up
Naveen Sampath04696f72022-06-13 15:19:14 +05301799 if dev != nil {
1800 triggerForceUpdate := func(key, value interface{}) bool {
1801 msrList := value.(*util.ConcurrentMap)
1802 forceUpdateServices := func(key, value interface{}) bool {
1803 msr := value.(*MigrateServicesRequest)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301804 forceUpdateAllServices(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301805 return true
1806 }
1807 msrList.Range(forceUpdateServices)
1808 return true
1809 }
1810 dev.(*VoltDevice).MigratingServices.Range(triggerForceUpdate)
1811 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301812 va.FetchAndProcessAllMigrateServicesReq(cntx, deviceID, forceUpdateAllServices)
Naveen Sampath04696f72022-06-13 15:19:14 +05301813 }
1814}
1815
vinokuma926cb3e2023-03-29 11:41:06 +05301816// GetPonPortIDFromUNIPort to get pon port id from uni port
Naveen Sampath04696f72022-06-13 15:19:14 +05301817func GetPonPortIDFromUNIPort(uniPortID uint32) uint32 {
1818 ponPortID := (uniPortID & 0x0FF00000) >> 20
1819 return ponPortID
1820}
1821
vinokuma926cb3e2023-03-29 11:41:06 +05301822// ProcessFlowModResultIndication - Processes Flow mod operation indications from controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301823func (va *VoltApplication) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301824 logger.Debugw(ctx, "Received Flow Mod Result Indication.", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301825 d := va.GetDevice(flowStatus.Device)
1826 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301827 logger.Warnw(ctx, "Dropping Flow Mod Indication. Device not found", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301828 return
1829 }
1830
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301831 cookieExists := ExecuteFlowEvent(cntx, d, flowStatus.Cookie, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +05301832
1833 if flowStatus.Flow != nil {
1834 flowAdd := (flowStatus.FlowModType == of.CommandAdd)
1835 if !cookieExists && !isFlowStatusSuccess(flowStatus.Status, flowAdd) {
1836 pushFlowFailureNotif(flowStatus)
1837 }
1838 }
1839}
1840
Akash Sonief452f12024-12-12 18:20:28 +05301841// CheckAndDeactivateService - check if the attempts for flow delete has reached threshold or not
1842func (va *VoltApplication) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
1843 logger.Debugw(ctx, "Check and Deactivate service", log.Fields{"Cookie": flow.Cookie, "FlowCount": flow.FlowCount, "DeviceSerial": devSerialNum})
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +05301844 if flow.FlowCount >= uint32(controller.GetController().GetMaxFlowRetryAttempt()) {
Akash Sonief452f12024-12-12 18:20:28 +05301845 devConfig := va.GetDeviceConfig(devSerialNum)
1846 if devConfig != nil {
Sridhar Ravindrab76eb162025-07-02 01:25:10 +05301847 portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, devConfig.NniPorts, flow)
Akash Sonief452f12024-12-12 18:20:28 +05301848 portName, err := va.GetPortName(portNo)
1849 if err != nil {
1850 logger.Warnw(ctx, "Error getting port name", log.Fields{"Reason": err.Error(), "PortID": portNo})
1851 return
1852 } else if portName == "" {
1853 logger.Warnw(ctx, "Port does not exist", log.Fields{"PortID": portNo})
1854 return
1855 }
1856 svc := va.GetServiceNameFromCookie(flow.Cookie, portName, uint8(of.PbitMatchNone), devID, flow.Match.TableMetadata)
1857 if svc != nil {
1858 va.DeactivateServiceForPort(ctx, svc, devID, portName)
1859 }
1860 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301861 }
Akash Sonief452f12024-12-12 18:20:28 +05301862}
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301863
Akash Sonief452f12024-12-12 18:20:28 +05301864// DeactivateServiceForPort - deactivate service for given UNI and remove flows from DB, after max flow install threshold has reached
1865func (va *VoltApplication) DeactivateServiceForPort(cntx context.Context, vs *VoltService, devID string, portName string) {
1866 logger.Debugw(ctx, "Flow install threshold reached. Deactivating service", log.Fields{"Service": vs.Name, "Port": portName})
1867
1868 if devID == vs.Device && portName == vs.Port && vs.IsActivated {
1869 vs.SetSvcDeactivationFlags(SvcDeacRsn_Controller)
1870 va.ServiceByName.Store(vs.Name, vs)
1871 vs.WriteToDb(cntx)
1872 device, err := va.GetDeviceFromPort(portName)
1873 if err != nil {
1874 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
1875 // So no error is returned
1876 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portName})
1877 }
1878 p := device.GetPort(vs.Port)
1879 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
1880 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
1881 // Port down call internally deletes all the flows
1882 vpv.PortDownInd(cntx, device.Name, portName, true, true)
1883 if vpv.IgmpEnabled {
1884 va.ReceiverDownInd(cntx, device.Name, portName)
1885 }
1886 } else {
1887 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": device.Name, "port": portName, "SvcName": vs.Name})
1888 }
1889 logger.Infow(ctx, "Service deactivated after flow install threshold", log.Fields{"Device": device.Name, "Service": vs.Name, "Port": portName})
1890 }
1891 vs.DeactivateInProgress = false
1892 va.ServiceByName.Store(vs.Name, vs)
1893 vs.WriteToDb(cntx)
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301894 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301895}
1896
Naveen Sampath04696f72022-06-13 15:19:14 +05301897func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1898 subFlow := flowStatus.Flow
1899 cookie := subFlow.Cookie
1900 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301901 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301902}
1903
vinokuma926cb3e2023-03-29 11:41:06 +05301904// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301905func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301906 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301907 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1908 mvp := value.(*MvlanProfile)
1909 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301910 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301911 }
1912 return true
1913 }
1914 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1915}
1916
1917// TaskInfo structure that is used to store the task Info.
1918type TaskInfo struct {
1919 ID string
1920 Name string
1921 Timestamp string
1922}
1923
1924// GetTaskList to get task list information.
1925func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301926 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301927 taskList := cntlr.GetController().GetTaskList(device)
1928 taskMap := make(map[int]*TaskInfo)
1929 for i, task := range taskList {
1930 taskID := strconv.Itoa(int(task.TaskID()))
1931 name := task.Name()
1932 timestamp := task.Timestamp()
1933 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1934 taskMap[i] = taskInfo
1935 }
1936 return taskMap
1937}
1938
1939// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1940func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301941 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301942 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301943
1944 if voltDevice != nil {
1945 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301946 logger.Warnw(ctx, "OLT Migration cannot be completed as there are dangling devices", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301947 } else {
1948 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301949 // Add Serial Number to Blocked Devices List.
1950 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1951 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1952
1953 updateSlNoForVnet := func(key, value interface{}) bool {
1954 vnet := value.(*VoltVnet)
1955 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1956 if deviceSlNo == oldOltSlNo {
1957 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1958 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1959 break
1960 }
1961 }
1962 return true
1963 }
1964
1965 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1966 mvProfile := value.(*MvlanProfile)
1967 for deviceSlNo := range mvProfile.DevicesList {
1968 if deviceSlNo == oldOltSlNo {
1969 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1970 delete(mvProfile.DevicesList, oldOltSlNo)
1971 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1972 break
1973 }
1974 }
1975 return true
1976 }
1977
1978 va.VnetsByName.Range(updateSlNoForVnet)
1979 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1980
1981 // Clear the serial number from Blocked Devices List
1982 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1983 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301984 }
1985}
1986
1987// GetVpvsForDsPkt to get vpv for downstream packets
1988func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1989 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301990 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301991 var matchVPVs []*VoltPortVnet
1992 findVpv := func(key, value interface{}) bool {
1993 vpvs := value.([]*VoltPortVnet)
1994 for _, vpv := range vpvs {
1995 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1996 var subMac net.HardwareAddr
1997 if NonZeroMacAddress(vpv.MacAddr) {
1998 subMac = vpv.MacAddr
1999 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
2000 subMac = vpv.LearntMacAddr
2001 } else {
2002 matchVPVs = append(matchVPVs, vpv)
2003 continue
2004 }
2005 if util.MacAddrsMatch(subMac, clientMAC) {
2006 matchVPVs = append([]*VoltPortVnet{}, vpv)
2007 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
2008 return false
2009 }
2010 }
2011 }
2012 return true
2013 }
2014 va.VnetsByPort.Range(findVpv)
2015
2016 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302017 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
2018 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05302019 }
2020 return matchVPVs, nil
2021}
2022
2023// GetMacInPortMap to get PORT value based on MAC key
2024func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302025 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05302026 if NonZeroMacAddress(macAddr) {
2027 va.macPortLock.Lock()
2028 defer va.macPortLock.Unlock()
2029 if port, ok := va.macPortMap[macAddr.String()]; ok {
2030 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2031 return port
2032 }
2033 }
2034 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
2035 return ""
2036}
2037
2038// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
2039func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302040 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05302041 if NonZeroMacAddress(macAddr) {
2042 va.macPortLock.Lock()
2043 va.macPortMap[macAddr.String()] = port
2044 va.macPortLock.Unlock()
2045 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2046 }
2047}
2048
2049// DeleteMacInPortMap to remove MAC key from MacPortMap
2050func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302051 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05302052 if NonZeroMacAddress(macAddr) {
2053 port := va.GetMacInPortMap(macAddr)
2054 va.macPortLock.Lock()
2055 delete(va.macPortMap, macAddr.String())
2056 va.macPortLock.Unlock()
2057 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2058 }
2059}
2060
vinokuma926cb3e2023-03-29 11:41:06 +05302061// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302062func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
2063 var grpMap map[*IgmpGroup]bool
2064 var ok bool
2065
2066 va.PendingPoolLock.Lock()
2067 defer va.PendingPoolLock.Unlock()
2068
2069 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
2070 // Do Not Reset any current profile info since group table entry tied to mvlan profile
2071 // The PonVlan is part of set field in group installed
2072 // Hence, Group created is always tied to the same mvlan profile until deleted
2073
2074 for device := range ig.Devices {
2075 key := getPendingPoolKey(ig.Mvlan, device)
2076
2077 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
2078 grpMap = make(map[*IgmpGroup]bool)
2079 }
2080 grpMap[ig] = true
2081
2082 //Add grpObj reference to all associated devices
2083 va.IgmpPendingPool[key] = grpMap
2084 }
2085}
2086
vinokuma926cb3e2023-03-29 11:41:06 +05302087// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302088func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
2089 GetApplication().PendingPoolLock.Lock()
2090 defer GetApplication().PendingPoolLock.Unlock()
2091
2092 logger.Infow(ctx, "Removing IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
2093
2094 key := getPendingPoolKey(ig.Mvlan, device)
2095 if _, ok := va.IgmpPendingPool[key]; ok {
2096 delete(va.IgmpPendingPool[key], ig)
2097 return true
2098 }
2099 return false
2100}
2101
vinokuma926cb3e2023-03-29 11:41:06 +05302102// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302103func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302104 GetApplication().PendingPoolLock.Lock()
2105 defer GetApplication().PendingPoolLock.Unlock()
2106
2107 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
2108
2109 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302110 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302111}
2112
vinokuma926cb3e2023-03-29 11:41:06 +05302113// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05302114// 1. Deletes the group from device
2115// 2. Delete the IgmpGroup obj and release the group ID to pool
2116// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302117func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302118 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05302119 if grpMap, ok := va.IgmpPendingPool[key]; ok {
2120 delete(va.IgmpPendingPool, key)
2121 for ig := range grpMap {
2122 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302123 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302124 }
2125 }
2126 }
2127}
2128
vinokuma926cb3e2023-03-29 11:41:06 +05302129// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302130func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302131 logger.Infow(ctx, "Removing IgmpGroup for all devices from Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
2132 for device := range ig.PendingGroupForDevice {
2133 va.RemoveGroupFromPendingPool(device, ig)
2134 }
2135}
2136
vinokuma926cb3e2023-03-29 11:41:06 +05302137// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302138func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302139 var ig *IgmpGroup
2140
2141 va.PendingPoolLock.Lock()
2142 defer va.PendingPoolLock.Unlock()
2143
2144 key := getPendingPoolKey(mvlan, device)
2145 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2146
vinokuma926cb3e2023-03-29 11:41:06 +05302147 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302148 grpMap, ok := va.IgmpPendingPool[key]
2149 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302150 logger.Warnw(ctx, "Matching IgmpGroup not found in Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05302151 return nil
2152 }
2153
vinokuma926cb3e2023-03-29 11:41:06 +05302154 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302155 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302156 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302157 for dev := range ig.Devices {
2158 key := getPendingPoolKey(mvlan, dev)
2159 delete(va.IgmpPendingPool[key], ig)
2160 }
2161
vinokuma926cb3e2023-03-29 11:41:06 +05302162 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302163 if ig.NumDevicesActive() == 0 {
2164 return ig
2165 }
2166
vinokuma926cb3e2023-03-29 11:41:06 +05302167 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302168 }
2169 return nil
2170}
2171
vinokuma926cb3e2023-03-29 11:41:06 +05302172// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302173// reference - mvlan/device ID
2174// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302175// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302176func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302177 va.PendingPoolLock.Lock()
2178 defer va.PendingPoolLock.Unlock()
2179
2180 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2181
vinokuma926cb3e2023-03-29 11:41:06 +05302182 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302183 paramPosition := 0
2184 if isRefDevice {
2185 paramPosition = 1
2186 }
2187
2188 // 1.Remove the Entry from pending pool
2189 // 2.Deletes the group from device
2190 // 3.Delete the IgmpGroup obj and release the group ID to pool
2191 for key := range va.IgmpPendingPool {
2192 keyParams := strings.Split(key, "_")
2193 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302194 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302195 }
2196 }
2197}
2198
2199func getPendingPoolKey(mvlan of.VlanType, device string) string {
2200 return mvlan.String() + "_" + device
2201}
2202
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302203func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302204 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302205 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2206 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302207 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302208 return true
2209 }
2210 va.IgmpGroups.Range(removeExpiredGroups)
2211}
2212
vinokuma926cb3e2023-03-29 11:41:06 +05302213// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302214func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302215 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302216 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302217 va.TriggerPendingServiceDeleteReq(cntx, device)
2218 va.TriggerPendingVpvDeleteReq(cntx, device)
2219 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302220 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302221}
2222
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302223// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2224func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302225 va.ServicesToDeactivate.Range(func(key, value interface{}) bool {
2226 serviceName := key.(string)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302227 if vs := va.GetService(serviceName); vs != nil {
2228 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302229 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302230 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2231 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302232 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
Akash Sonief452f12024-12-12 18:20:28 +05302233 return true
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302234 }
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302235 vpv.DelTrapFlows(cntx)
2236 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302237 // Set the flag to false and clear the SevicesToDeactivate map entry so that when core restarts, VGC will not
2238 // try to deactivate the service again
2239 vs.DeactivateInProgress = false
2240 va.ServicesToDeactivate.Delete(serviceName)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302241 vs.WriteToDb(cntx)
2242 vpv.ClearServiceCounters(cntx)
2243 }
2244 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302245 logger.Warnw(ctx, "Pending Service Not found during Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302246 }
Akash Sonief452f12024-12-12 18:20:28 +05302247 return true
2248 })
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302249}
2250
vinokuma926cb3e2023-03-29 11:41:06 +05302251// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302252func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302253 va.ServicesToDelete.Range(func(key, value interface{}) bool {
2254 serviceName := key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +05302255 if vs := va.GetService(serviceName); vs != nil {
2256 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302257 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302258 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302259 // Clear the SevicesToDelete map so that when core restarts, VGC will not try to deactivate the service again
2260 va.ServicesToDelete.Delete(serviceName)
Naveen Sampath04696f72022-06-13 15:19:14 +05302261 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302262 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302263 }
2264 }
2265 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302266 logger.Warnw(ctx, "Pending Service Not found during Delete", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302267 }
Akash Sonief452f12024-12-12 18:20:28 +05302268 return true
2269 })
Naveen Sampath04696f72022-06-13 15:19:14 +05302270}
2271
vinokuma926cb3e2023-03-29 11:41:06 +05302272// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302273func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302274 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302275 for vpv := range va.VoltPortVnetsToDelete {
2276 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302277 logger.Debugw(ctx, "Triggering Pending VPv flow delete", log.Fields{"Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302278 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302279 }
2280 }
2281}
2282
vinokuma926cb3e2023-03-29 11:41:06 +05302283// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302284func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302285 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302286 for vnetName := range va.VnetsToDelete {
2287 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2288 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302289 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302290 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302291 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302292 va.deleteVnetConfig(vnet)
2293 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302294 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302295 }
2296 }
2297 }
2298}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302299
2300type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302301 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302302 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302303 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2304 EnableEapol bool `json:"enableEapol"`
2305 EnableDhcpV6 bool `json:"enableDhcpV6"`
2306 EnableDhcpV4 bool `json:"enableDhcpV4"`
2307 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302308}
2309
2310func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2311 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2312 va.OltFlowServiceConfig = oltFlowService
2313 b, err := json.Marshal(va.OltFlowServiceConfig)
2314 if err != nil {
2315 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2316 return
2317 }
2318 _ = db.PutOltFlowService(cntx, string(b))
2319}
Akash Sonia8246972023-01-03 10:37:08 +05302320
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302321// RestoreOltFlowService to read from the DB and restore olt flow service config
2322func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2323 oltflowService, err := db.GetOltFlowService(cntx)
2324 if err != nil {
2325 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2326 return
2327 }
2328 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2329 if err != nil {
2330 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2331 return
2332 }
2333 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2334}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302335
Akash Soni87a19072023-02-28 00:46:59 +05302336func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302337 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302338 var dc *DeviceConfig
2339 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2340 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2341 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302342 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302343 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302344 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302345 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302346 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302347 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302348 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302349 va.DevicesDisc.Store(id, device)
2350 }
2351}