blob: f0fa05e0ab508a2f9acacd971dcb69e8557bc762 [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
163}
164
165// NewVoltPort : Constructor for the port.
166func NewVoltPort(device string, name string, id uint32) *VoltPort {
167 var vp VoltPort
168 vp.Device = device
169 vp.Name = name
170 vp.ID = id
171 if util.IsNniPort(id) {
172 vp.Type = VoltPortTypeNni
173 } else {
174 vp.PonPort = GetPonPortIDFromUNIPort(id)
175 }
176 vp.State = PortStateDown
177 vp.ChannelPerSubAlarmRaised = false
178 return &vp
179}
180
181// SetPortID : The ID is used when constructing flows as the flows require ID.
182func (vp *VoltPort) SetPortID(id uint32) {
183 vp.ID = id
184 if util.IsNniPort(id) {
185 vp.Type = VoltPortTypeNni
186 }
187}
188
189// ---------------------------------------------------------------------
190// VOLT Device
191// ---------------------------------------------------------------------
192//
193// VoltDevice is an OLT which contains ports of type access and NNI. Each OLT
194// can only have one NNI port in the current release. The NNI port always uses
195// identity 65536 and all the access ports use identities less than 65535. The
196// identification of NNI is done by comparing the port identity with 65535
197
198// VoltDevice fields :
199// Name: This is the name presented by the device/VOLTHA. This doesn't
vinokuma926cb3e2023-03-29 11:41:06 +0530200// have any relation to the physical device
Naveen Sampath04696f72022-06-13 15:19:14 +0530201// SerialNum: This is the serial number of the device and can be used to
vinokuma926cb3e2023-03-29 11:41:06 +0530202// correlate the devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530203// NniPort: The identity of the NNI port
204// Ports: List of all ports added to the device
205type VoltDevice struct {
Akash Sonief452f12024-12-12 18:20:28 +0530206 VoltDeviceIntr VoltDevInterface
Naveen Sampath04696f72022-06-13 15:19:14 +0530207 FlowAddEventMap *util.ConcurrentMap //map[string]*FlowEvent
208 FlowDelEventMap *util.ConcurrentMap //map[string]*FlowEvent
209 MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
vinokuma926cb3e2023-03-29 11:41:06 +0530210 VpvsBySvlan *util.ConcurrentMap // map[svlan]map[vnet_port]*VoltPortVnet
211 ConfiguredVlanForDeviceFlows *util.ConcurrentMap //map[string]map[string]bool
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530212
213 IgmpDsFlowAppliedForMvlan map[uint16]bool
214
215 Ports sync.Map
216 VlanPortStatus sync.Map
217 ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
218 PonPortList sync.Map // [PonPortID]map[string]string
219
220 State controller.DeviceState
221 SouthBoundID string
222 NniPort string
223 Name string
224 SerialNum string
225
226 ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
227
228 NniDhcpTrapVid of.VlanType
229
230 GlobalDhcpFlowAdded bool
231 icmpv6GroupAdded bool
Akash Soni6f369452023-09-19 11:18:28 +0530232}
233
234type VoltDevInterface interface {
235 GetPortNameFromPortID(portID uint32) string
Naveen Sampath04696f72022-06-13 15:19:14 +0530236}
237
238// NewVoltDevice : Constructor for the device
239func NewVoltDevice(name string, slno, southBoundID string) *VoltDevice {
240 var d VoltDevice
241 d.Name = name
242 d.SouthBoundID = southBoundID
243 d.State = controller.DeviceStateDOWN
244 d.NniPort = ""
245 d.SouthBoundID = southBoundID
246 d.SerialNum = slno
247 d.icmpv6GroupAdded = false
248 d.IgmpDsFlowAppliedForMvlan = make(map[uint16]bool)
249 d.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
250 d.MigratingServices = util.NewConcurrentMap()
251 d.VpvsBySvlan = util.NewConcurrentMap()
252 d.FlowAddEventMap = util.NewConcurrentMap()
253 d.FlowDelEventMap = util.NewConcurrentMap()
254 d.GlobalDhcpFlowAdded = false
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530255 if config, ok := GetApplication().DevicesConfig.Load(slno); ok {
256 //Update nni dhcp vid
Akash Soni53da2852023-03-15 00:31:31 +0530257 deviceConfig := config.(*DeviceConfig)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530258 d.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
259 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530260 return &d
261}
262
vinokuma926cb3e2023-03-29 11:41:06 +0530263// GetAssociatedVpvsForDevice - return the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530264func (va *VoltApplication) GetAssociatedVpvsForDevice(device string, svlan of.VlanType) *util.ConcurrentMap {
265 if d := va.GetDevice(device); d != nil {
266 return d.GetAssociatedVpvs(svlan)
267 }
268 return nil
269}
270
vinokuma926cb3e2023-03-29 11:41:06 +0530271// AssociateVpvsToDevice - updates the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530272func (va *VoltApplication) AssociateVpvsToDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530273 logger.Debugw(ctx, "AssociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530274 if d := va.GetDevice(device); d != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530275 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
276 vpvMap.Set(vpv, true)
277 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530278 logger.Debugw(ctx, "VPVMap: SET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530279 return
280 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530281 logger.Warnw(ctx, "Set VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530282}
283
vinokuma926cb3e2023-03-29 11:41:06 +0530284// DisassociateVpvsFromDevice - disassociated VPVs from given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530285func (va *VoltApplication) DisassociateVpvsFromDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530286 logger.Debugw(ctx, "DisassociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530287 if d := va.GetDevice(device); d != nil {
288 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
289 vpvMap.Remove(vpv)
290 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530291 logger.Debugw(ctx, "VPVMap: Remove", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530292 return
293 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530294 logger.Warnw(ctx, "Remove VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530295}
296
vinokuma926cb3e2023-03-29 11:41:06 +0530297// GetAssociatedVpvs - returns the associated VPVs for the given Svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530298func (d *VoltDevice) GetAssociatedVpvs(svlan of.VlanType) *util.ConcurrentMap {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530299 logger.Debugw(ctx, "Received Get Associated Vpvs", log.Fields{"svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530300 var vpvMap *util.ConcurrentMap
301 var mapIntf interface{}
302 var ok bool
303
304 if mapIntf, ok = d.VpvsBySvlan.Get(svlan); ok {
305 vpvMap = mapIntf.(*util.ConcurrentMap)
306 } else {
307 vpvMap = util.NewConcurrentMap()
308 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530309 logger.Debugw(ctx, "VPVMap: GET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530310 return vpvMap
311}
312
313// AddPort add port to the device.
314func (d *VoltDevice) AddPort(port string, id uint32) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530315 logger.Debugw(ctx, "Add Port", log.Fields{"Port": port, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530316 addPonPortFromUniPort := func(vPort *VoltPort) {
317 if vPort.Type == VoltPortTypeAccess {
318 ponPortID := GetPonPortIDFromUNIPort(vPort.ID)
319
320 if ponPortUniList, ok := d.PonPortList.Load(ponPortID); !ok {
321 uniList := make(map[string]uint32)
322 uniList[port] = vPort.ID
323 d.PonPortList.Store(ponPortID, uniList)
324 } else {
325 ponPortUniList.(map[string]uint32)[port] = vPort.ID
326 d.PonPortList.Store(ponPortID, ponPortUniList)
327 }
328 }
329 }
330 va := GetApplication()
331 if pIntf, ok := d.Ports.Load(port); ok {
332 voltPort := pIntf.(*VoltPort)
333 addPonPortFromUniPort(voltPort)
334 va.AggActiveChannelsCountPerSub(d.Name, port, voltPort)
335 d.Ports.Store(port, voltPort)
336 return voltPort
337 }
338 p := NewVoltPort(d.Name, port, id)
339 va.AggActiveChannelsCountPerSub(d.Name, port, p)
340 d.Ports.Store(port, p)
341 if util.IsNniPort(id) {
342 d.NniPort = port
343 }
344 addPonPortFromUniPort(p)
345 return p
346}
347
348// GetPort to get port information from the device.
349func (d *VoltDevice) GetPort(port string) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530350 logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530351 if pIntf, ok := d.Ports.Load(port); ok {
352 return pIntf.(*VoltPort)
353 }
354 return nil
355}
356
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530357// GetPortByPortID to get port information from the device.
358func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530359 logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530360 portName := ""
361 d.Ports.Range(func(key, value interface{}) bool {
362 vp := value.(*VoltPort)
363 if vp.ID == portID {
364 portName = vp.Name
365 }
366 return true
367 })
368 return portName
369}
370
Naveen Sampath04696f72022-06-13 15:19:14 +0530371// DelPort to delete port from the device
372func (d *VoltDevice) DelPort(port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530373 logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530374 if _, ok := d.Ports.Load(port); ok {
375 d.Ports.Delete(port)
376 } else {
377 logger.Warnw(ctx, "Port doesn't exist", log.Fields{"Device": d.Name, "Port": port})
378 }
379}
380
381// pushFlowsForUnis to send port-up-indication for uni ports.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530382func (d *VoltDevice) pushFlowsForUnis(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530383 logger.Info(ctx, "NNI Discovered, Sending Port UP Ind for UNIs")
384 d.Ports.Range(func(key, value interface{}) bool {
385 port := key.(string)
386 vp := value.(*VoltPort)
387
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530388 logger.Debugw(ctx, "NNI Discovered. Sending Port UP Ind for UNI", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530389 //Ignore if UNI port is not UP
390 if vp.State != PortStateUp {
391 return true
392 }
393
394 //Obtain all VPVs associated with the port
395 vnets, ok := GetApplication().VnetsByPort.Load(port)
396 if !ok {
397 return true
398 }
399
400 for _, vpv := range vnets.([]*VoltPortVnet) {
401 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530402 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530403 vpv.VpvLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +0530404 }
405 return true
406 })
407}
408
409// ----------------------------------------------------------
410// VOLT Application - hosts all other objects
411// ----------------------------------------------------------
412//
413// The VOLT application is a singleton implementation where
414// there is just one instance in the system and is the gateway
415// to all other components within the controller
416// The declaration of the singleton object
417var vapplication *VoltApplication
418
Akash Soni6f369452023-09-19 11:18:28 +0530419type VoltAppInterface interface {
420 AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
421 AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530422 AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16) error
Akash Soni6f369452023-09-19 11:18:28 +0530423 GetFlowProvisionStatus(portNo string) FlowProvisionStatus
424 DelServiceWithPrefix(cntx context.Context, prefix string) error
425 GetDevice(device string) *VoltDevice
426 GetTaskList(device string) map[int]*TaskInfo
427 AddMeterProf(cntx context.Context, cfg VoltMeter)
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530428 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 +0530429 DelMvlanProfile(cntx context.Context, name string) error
430 GetMvlanProfileByTag(vlan of.VlanType) *MvlanProfile
431 AddMcastConfig(cntx context.Context, MvlanProfileID string, IgmpProfileID string, IgmpProxyIP string, OltSerialNum string) error
432 DelMeterProf(cntx context.Context, name string) error
433 GetMeterByName(name string) (*VoltMeter, bool)
434 UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig)
435 GetDeviceConfig(serNum string) *DeviceConfig
436 GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error)
437 GetAllMacLearnerInfo() ([]MacLearnerInfo, error)
438 GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error)
439 ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
440 DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
441 GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error)
442 UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService)
443 GetIgnoredPorts() (map[string][]string, error)
444}
445
Naveen Sampath04696f72022-06-13 15:19:14 +0530446// VoltApplication fields :
447// ServiceByName - Stores the services by the name as key
vinokuma926cb3e2023-03-29 11:41:06 +0530448// A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530449// VnetsByPort - Stores the VNETs by the ports configured
vinokuma926cb3e2023-03-29 11:41:06 +0530450// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530451// VnetsByTag - Stores the VNETs by the VLANS configured
vinokuma926cb3e2023-03-29 11:41:06 +0530452// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530453// VnetsByName - Stores the VNETs by the name configured
vinokuma926cb3e2023-03-29 11:41:06 +0530454// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530455// DevicesDisc - Stores the devices discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530456// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530457// PortsDisc - Stores the ports discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530458// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530459type VoltApplication struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530460 MeterMgr
vinokuma926cb3e2023-03-29 11:41:06 +0530461 DataMigrationInfo DataMigration
462 VnetsBySvlan *util.ConcurrentMap
463 IgmpGroupIds []*IgmpGroup
464 VoltPortVnetsToDelete map[*VoltPortVnet]bool
Akash Sonia8246972023-01-03 10:37:08 +0530465 IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
vinokuma926cb3e2023-03-29 11:41:06 +0530466 macPortMap map[string]string
Akash Sonia8246972023-01-03 10:37:08 +0530467 VnetsToDelete map[string]bool
Akash Sonief452f12024-12-12 18:20:28 +0530468 ServicesToDelete sync.Map
469 ServicesToDeactivate sync.Map
Akash Sonia8246972023-01-03 10:37:08 +0530470 PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
471 vendorID string
vinokuma926cb3e2023-03-29 11:41:06 +0530472 ServiceByName sync.Map // [serName]*VoltService
473 VnetsByPort sync.Map // [portName][]*VoltPortVnet
474 VnetsByTag sync.Map // [svlan-cvlan-uvlan]*VoltVnet
475 VnetsByName sync.Map // [vnetName]*VoltVnet
476 DevicesDisc sync.Map
477 PortsDisc sync.Map
478 IgmpGroups sync.Map // [grpKey]*IgmpGroup
479 MvlanProfilesByTag sync.Map
480 MvlanProfilesByName sync.Map
481 Icmpv6Receivers sync.Map
482 DeviceCounters sync.Map //[logicalDeviceId]*DeviceCounters
483 ServiceCounters sync.Map //[serviceName]*ServiceCounters
484 NbDevice sync.Map // [OLTSouthBoundID]*NbDevice
485 OltIgmpInfoBySerial sync.Map
486 McastConfigMap sync.Map //[OltSerialNo_MvlanProfileID]*McastConfig
Akash Sonia8246972023-01-03 10:37:08 +0530487 DevicesConfig sync.Map //[serialNumber]*DeviceConfig
vinokuma926cb3e2023-03-29 11:41:06 +0530488 IgmpProfilesByName sync.Map
489 IgmpTasks tasks.Tasks
490 IndicationsTasks tasks.Tasks
491 MulticastAlarmTasks tasks.Tasks
492 IgmpKPIsTasks tasks.Tasks
493 pppoeTasks tasks.Tasks
494 OltFlowServiceConfig OltFlowService
495 PendingPoolLock sync.RWMutex
496 // MacAddress-Port MAP to avoid swap of mac across ports.
497 macPortLock sync.RWMutex
498 portLock sync.Mutex
Akash Sonia8246972023-01-03 10:37:08 +0530499}
Naveen Sampath04696f72022-06-13 15:19:14 +0530500
Akash Sonia8246972023-01-03 10:37:08 +0530501type DeviceConfig struct {
502 SerialNumber string `json:"id"`
503 HardwareIdentifier string `json:"hardwareIdentifier"`
Akash Soni87a19072023-02-28 00:46:59 +0530504 IPAddress string `json:"ipAddress"`
Akash Soni53da2852023-03-15 00:31:31 +0530505 UplinkPort string `json:"uplinkPort"`
Akash Sonia8246972023-01-03 10:37:08 +0530506 NasID string `json:"nasId"`
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530507 NniDhcpTrapVid uint16 `json:"nniDhcpTrapVid"`
Naveen Sampath04696f72022-06-13 15:19:14 +0530508}
509
510// PonPortCfg contains NB port config and activeIGMPChannels count
511type PonPortCfg struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530512 PortAlarmProfileID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530513 PortID uint32
514 MaxActiveChannels uint32
515 ActiveIGMPChannels uint32
516 EnableMulticastKPI bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530517}
518
519// NbDevice OLT Device info
520type NbDevice struct {
521 SouthBoundID string
522 PonPorts sync.Map // [PortID]*PonPortCfg
523}
524
525// RestoreNbDeviceFromDb restores the NB Device in case of VGC pod restart.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530526func (va *VoltApplication) RestoreNbDeviceFromDb(cntx context.Context, deviceID string) *NbDevice {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530527 logger.Debugw(ctx, "Received Restore Nb Device From Db", log.Fields{"deviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530528 nbDevice := NewNbDevice()
529 nbDevice.SouthBoundID = deviceID
530
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530531 nbPorts, _ := db.GetAllNbPorts(cntx, deviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530532
533 for key, p := range nbPorts {
534 b, ok := p.Value.([]byte)
535 if !ok {
536 logger.Warn(ctx, "The value type is not []byte")
537 continue
538 }
539 var port PonPortCfg
540 err := json.Unmarshal(b, &port)
541 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530542 logger.Warnw(ctx, "Unmarshal of PonPortCfg failed", log.Fields{"deviceID": deviceID, "port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530543 continue
544 }
545 logger.Debugw(ctx, "Port recovered", log.Fields{"port": port})
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530546 ponPortID, err := strconv.ParseUint(key, 10, 32)
547 if err != nil {
548 logger.Errorw(ctx, "Error converting string to uint32:", log.Fields{"deviceID": deviceID, "error": err})
549 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530550 nbDevice.PonPorts.Store(uint32(ponPortID), &port)
551 }
552 va.NbDevice.Store(deviceID, nbDevice)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530553 logger.Debugw(ctx, "Recovered NbDevice From Db", log.Fields{"deviceID": deviceID, "nbDevice": nbDevice})
Naveen Sampath04696f72022-06-13 15:19:14 +0530554 return nbDevice
555}
556
557// NewNbDevice Constructor for NbDevice
558func NewNbDevice() *NbDevice {
559 var nbDevice NbDevice
560 return &nbDevice
561}
562
563// WriteToDb writes nb device port config to kv store
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530564func (nbd *NbDevice) WriteToDb(cntx context.Context, portID uint32, ponPort *PonPortCfg) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530565 b, err := json.Marshal(ponPort)
566 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530567 logger.Errorw(ctx, "PonPortConfig-marshal-failed", log.Fields{"err": err, "ponPort": ponPort})
Naveen Sampath04696f72022-06-13 15:19:14 +0530568 return
569 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530570 db.PutNbDevicePort(cntx, nbd.SouthBoundID, portID, string(b))
Naveen Sampath04696f72022-06-13 15:19:14 +0530571}
572
573// AddPortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530574func (nbd *NbDevice) AddPortToNbDevice(cntx context.Context, portID, allowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +0530575 enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530576 logger.Debugw(ctx, "AddPortToNbDevice", log.Fields{"PortID": portID, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530577 ponPort := &PonPortCfg{
578 PortID: portID,
579 MaxActiveChannels: allowedChannels,
580 EnableMulticastKPI: enableMulticastKPI,
581 PortAlarmProfileID: portAlarmProfileID,
582 }
583 nbd.PonPorts.Store(portID, ponPort)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530584 nbd.WriteToDb(cntx, portID, ponPort)
Naveen Sampath04696f72022-06-13 15:19:14 +0530585 return ponPort
586}
587
Akash Sonia8246972023-01-03 10:37:08 +0530588// RestoreDeviceConfigFromDb to restore vnet from port
589func (va *VoltApplication) RestoreDeviceConfigFromDb(cntx context.Context) {
590 // VNETS must be learnt first
591 dConfig, _ := db.GetDeviceConfig(cntx)
592 for _, device := range dConfig {
593 b, ok := device.Value.([]byte)
594 if !ok {
595 logger.Warn(ctx, "The value type is not []byte")
596 continue
597 }
598 devConfig := DeviceConfig{}
599 err := json.Unmarshal(b, &devConfig)
600 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530601 logger.Warnw(ctx, "Unmarshal of device configuration failed", log.Fields{"Device Config": devConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530602 continue
603 }
604 logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
605 if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid); err != nil {
606 logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
607 }
Akash Sonia8246972023-01-03 10:37:08 +0530608 }
609}
610
611// WriteDeviceConfigToDb writes sb device config to kv store
612func (dc *DeviceConfig) WriteDeviceConfigToDb(cntx context.Context, serialNum string, deviceConfig *DeviceConfig) error {
613 b, err := json.Marshal(deviceConfig)
614 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530615 return fmt.Errorf("deviceConfig-marshal-failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530616 }
617 dberr := db.PutDeviceConfig(cntx, serialNum, string(b))
618 if dberr != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530619 return fmt.Errorf("update device config failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530620 }
621 return nil
622}
623
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530624func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID uint16) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530625 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 +0530626 var dc *DeviceConfig
627
Akash Soni87a19072023-02-28 00:46:59 +0530628 deviceConfig := &DeviceConfig{
629 SerialNumber: serialNum,
630 HardwareIdentifier: hardwareIdentifier,
631 NasID: nasID,
632 UplinkPort: uplinkPort,
633 IPAddress: ipAddress,
vinokuma926cb3e2023-03-29 11:41:06 +0530634 NniDhcpTrapVid: nniDhcpTrapID,
Akash Sonia8246972023-01-03 10:37:08 +0530635 }
Akash Soni87a19072023-02-28 00:46:59 +0530636 va.DevicesConfig.Store(serialNum, deviceConfig)
637 err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
638 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530639 return fmt.Errorf("DB update for device config failed - %w ", err)
Akash Soni87a19072023-02-28 00:46:59 +0530640 }
641
642 // If device is already discovered update the VoltDevice structure
643 device, id := va.GetDeviceBySerialNo(serialNum)
644 if device != nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530645 device.NniDhcpTrapVid = of.VlanType(nniDhcpTrapID)
Akash Soni87a19072023-02-28 00:46:59 +0530646 va.DevicesDisc.Store(id, device)
647 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530648 logger.Debugw(ctx, "Added device config", log.Fields{"Device Config": deviceConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530649 return nil
650}
651
652// GetDeviceConfig to get a device config.
653func (va *VoltApplication) GetDeviceConfig(serNum string) *DeviceConfig {
654 if d, ok := va.DevicesConfig.Load(serNum); ok {
655 return d.(*DeviceConfig)
656 }
657 return nil
658}
659
Naveen Sampath04696f72022-06-13 15:19:14 +0530660// UpdatePortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530661func (nbd *NbDevice) UpdatePortToNbDevice(cntx context.Context, portID, allowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530662 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 +0530663 p, exists := nbd.PonPorts.Load(portID)
664 if !exists {
665 logger.Errorw(ctx, "PON port not exists in nb-device", log.Fields{"portID": portID})
666 return nil
667 }
668 port := p.(*PonPortCfg)
669 if allowedChannels != 0 {
670 port.MaxActiveChannels = allowedChannels
671 port.EnableMulticastKPI = enableMulticastKPI
672 port.PortAlarmProfileID = portAlarmProfileID
673 }
674
675 nbd.PonPorts.Store(portID, port)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530676 nbd.WriteToDb(cntx, portID, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530677 return port
678}
679
680// DeletePortFromNbDevice Deletes pon port from NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530681func (nbd *NbDevice) DeletePortFromNbDevice(cntx context.Context, portID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530682 logger.Debugw(ctx, "Received Delete Port from NbDevice", log.Fields{"portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530683 if _, ok := nbd.PonPorts.Load(portID); ok {
684 nbd.PonPorts.Delete(portID)
685 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530686 db.DelNbDevicePort(cntx, nbd.SouthBoundID, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530687}
688
689// GetApplication : Interface to access the singleton object
690func GetApplication() *VoltApplication {
691 if vapplication == nil {
692 vapplication = newVoltApplication()
693 }
694 return vapplication
695}
696
697// newVoltApplication : Constructor for the singleton object. Hence this is not
698// an exported function
699func newVoltApplication() *VoltApplication {
700 var va VoltApplication
701 va.IgmpTasks.Initialize(context.TODO())
702 va.MulticastAlarmTasks.Initialize(context.TODO())
703 va.IgmpKPIsTasks.Initialize(context.TODO())
704 va.pppoeTasks.Initialize(context.TODO())
705 va.storeIgmpProfileMap(DefaultIgmpProfID, newDefaultIgmpProfile())
706 va.MeterMgr.Init()
707 va.AddIgmpGroups(5000)
708 va.macPortMap = make(map[string]string)
709 va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
710 va.VnetsBySvlan = util.NewConcurrentMap()
711 va.VnetsToDelete = make(map[string]bool)
Naveen Sampath04696f72022-06-13 15:19:14 +0530712 va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530713 go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
714 go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
Naveen Sampath04696f72022-06-13 15:19:14 +0530715 InitEventFuncMapper()
716 db = database.GetDatabase()
Akash Soni6f369452023-09-19 11:18:28 +0530717
Naveen Sampath04696f72022-06-13 15:19:14 +0530718 return &va
719}
720
vinokuma926cb3e2023-03-29 11:41:06 +0530721// GetFlowEventRegister - returs the register based on flow mod type
Naveen Sampath04696f72022-06-13 15:19:14 +0530722func (d *VoltDevice) GetFlowEventRegister(flowModType of.Command) (*util.ConcurrentMap, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530723 switch flowModType {
724 case of.CommandDel:
725 return d.FlowDelEventMap, nil
726 case of.CommandAdd:
727 return d.FlowAddEventMap, nil
728 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530729 logger.Warnw(ctx, "Unknown Flow Mod received", log.Fields{"flowModtype": flowModType})
Naveen Sampath04696f72022-06-13 15:19:14 +0530730 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530731 return util.NewConcurrentMap(), errors.New("unknown flow mod")
Naveen Sampath04696f72022-06-13 15:19:14 +0530732}
733
734// RegisterFlowAddEvent to register a flow event.
735func (d *VoltDevice) RegisterFlowAddEvent(cookie string, event *FlowEvent) {
736 logger.Debugw(ctx, "Registered Flow Add Event", log.Fields{"Cookie": cookie, "Event": event})
737 d.FlowAddEventMap.MapLock.Lock()
738 defer d.FlowAddEventMap.MapLock.Unlock()
739 d.FlowAddEventMap.Set(cookie, event)
740}
741
742// RegisterFlowDelEvent to register a flow event.
743func (d *VoltDevice) RegisterFlowDelEvent(cookie string, event *FlowEvent) {
744 logger.Debugw(ctx, "Registered Flow Del Event", log.Fields{"Cookie": cookie, "Event": event})
745 d.FlowDelEventMap.MapLock.Lock()
746 defer d.FlowDelEventMap.MapLock.Unlock()
747 d.FlowDelEventMap.Set(cookie, event)
748}
749
750// UnRegisterFlowEvent to unregister a flow event.
751func (d *VoltDevice) UnRegisterFlowEvent(cookie string, flowModType of.Command) {
752 logger.Debugw(ctx, "UnRegistered Flow Add Event", log.Fields{"Cookie": cookie, "Type": flowModType})
753 flowEventMap, err := d.GetFlowEventRegister(flowModType)
754 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530755 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowModType, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530756 return
757 }
758 flowEventMap.MapLock.Lock()
759 defer flowEventMap.MapLock.Unlock()
760 flowEventMap.Remove(cookie)
761}
762
763// AddIgmpGroups to add Igmp groups.
764func (va *VoltApplication) AddIgmpGroups(numOfGroups uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530765 logger.Debugw(ctx, "AddIgmpGroups", log.Fields{"NumOfGroups": numOfGroups})
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530766 var i uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530767 //TODO: Temp change to resolve group id issue in pOLT
768 //for i := 1; uint32(i) <= numOfGroups; i++ {
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530769 for i = 2; i <= (numOfGroups + 1); i++ {
Naveen Sampath04696f72022-06-13 15:19:14 +0530770 ig := IgmpGroup{}
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530771 ig.GroupID = i
Naveen Sampath04696f72022-06-13 15:19:14 +0530772 va.IgmpGroupIds = append(va.IgmpGroupIds, &ig)
773 }
774}
775
776// GetAvailIgmpGroupID to get id of available igmp group.
777func (va *VoltApplication) GetAvailIgmpGroupID() *IgmpGroup {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530778 logger.Info(ctx, "GetAvailIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530779 var ig *IgmpGroup
780 if len(va.IgmpGroupIds) > 0 {
781 ig, va.IgmpGroupIds = va.IgmpGroupIds[0], va.IgmpGroupIds[1:]
782 return ig
783 }
784 return nil
785}
786
787// GetIgmpGroupID to get id of igmp group.
788func (va *VoltApplication) GetIgmpGroupID(gid uint32) (*IgmpGroup, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530789 logger.Info(ctx, "GetIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530790 for id, ig := range va.IgmpGroupIds {
791 if ig.GroupID == gid {
792 va.IgmpGroupIds = append(va.IgmpGroupIds[0:id], va.IgmpGroupIds[id+1:]...)
793 return ig, nil
794 }
795 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530796 return nil, errors.New("group id missing")
Naveen Sampath04696f72022-06-13 15:19:14 +0530797}
798
799// PutIgmpGroupID to add id of igmp group.
800func (va *VoltApplication) PutIgmpGroupID(ig *IgmpGroup) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530801 logger.Debugw(ctx, "GetIgmpGroupID", log.Fields{"GroupID": ig.GroupID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530802 va.IgmpGroupIds = append([]*IgmpGroup{ig}, va.IgmpGroupIds[0:]...)
803}
804
vinokuma926cb3e2023-03-29 11:41:06 +0530805// RestoreUpgradeStatus - gets upgrade/migration status from DB and updates local flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530806func (va *VoltApplication) RestoreUpgradeStatus(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530807 logger.Info(ctx, "Received Restore Upgrade Status")
Naveen Sampath04696f72022-06-13 15:19:14 +0530808 Migrate := new(DataMigration)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530809 if err := GetMigrationInfo(cntx, Migrate); err == nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530810 if Migrate.Status == MigrationInProgress {
811 isUpgradeComplete = false
812 return
813 }
814 }
815 isUpgradeComplete = true
816
817 logger.Infow(ctx, "Upgrade Status Restored", log.Fields{"Upgrade Completed": isUpgradeComplete})
818}
819
820// ReadAllFromDb : If we are restarted, learn from the database the current execution
821// stage
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530822func (va *VoltApplication) ReadAllFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530823 logger.Info(ctx, "Reading the meters from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530824 va.RestoreMetersFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530825 logger.Info(ctx, "Reading the VNETs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826 va.RestoreVnetsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530827 logger.Info(ctx, "Reading the VPVs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530828 va.RestoreVpvsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530829 logger.Info(ctx, "Reading the Services from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530830 va.RestoreSvcsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530831 logger.Info(ctx, "Reading the MVLANs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530832 va.RestoreMvlansFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530833 logger.Info(ctx, "Reading the IGMP profiles from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530834 va.RestoreIGMPProfilesFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530835 logger.Info(ctx, "Reading the Mcast configs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530836 va.RestoreMcastConfigsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530837 logger.Info(ctx, "Reading the IGMP groups for DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530838 va.RestoreIgmpGroupsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530839 logger.Info(ctx, "Reading Upgrade status from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530840 va.RestoreUpgradeStatus(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530841 logger.Info(ctx, "Reading OltFlowService from DB")
842 va.RestoreOltFlowService(cntx)
Akash Sonia8246972023-01-03 10:37:08 +0530843 logger.Info(ctx, "Reading device config from DB")
844 va.RestoreDeviceConfigFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530845 logger.Info(ctx, "Reconciled from DB")
846}
847
vinokuma926cb3e2023-03-29 11:41:06 +0530848// InitStaticConfig to initialize static config.
Naveen Sampath04696f72022-06-13 15:19:14 +0530849func (va *VoltApplication) InitStaticConfig() {
850 va.InitIgmpSrcMac()
851}
852
853// SetVendorID to set vendor id
854func (va *VoltApplication) SetVendorID(vendorID string) {
855 va.vendorID = vendorID
856}
857
858// GetVendorID to get vendor id
859func (va *VoltApplication) GetVendorID() string {
860 return va.vendorID
861}
862
863// SetRebootFlag to set reboot flag
864func (va *VoltApplication) SetRebootFlag(flag bool) {
865 vgcRebooted = flag
866}
867
868// GetUpgradeFlag to get reboot status
869func (va *VoltApplication) GetUpgradeFlag() bool {
870 return isUpgradeComplete
871}
872
873// SetUpgradeFlag to set reboot status
874func (va *VoltApplication) SetUpgradeFlag(flag bool) {
875 isUpgradeComplete = flag
876}
877
878// ------------------------------------------------------------
879// Device related functions
880
881// AddDevice : Add a device and typically the device stores the NNI port on the device
882// The NNI port is used when the packets are emitted towards the network.
883// The outport is selected as the NNI port of the device. Today, we support
884// a single NNI port per OLT. This is true whether the network uses any
885// protection mechanism (LAG, ERPS, etc.). The aggregate of the such protection
886// is represented by a single NNI port
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530887func (va *VoltApplication) AddDevice(cntx context.Context, device string, slno, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530888 logger.Debugw(ctx, "Received Device Ind: Add", log.Fields{"Device": device, "SrNo": slno, "southBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530889 if _, ok := va.DevicesDisc.Load(device); ok {
890 logger.Warnw(ctx, "Device Exists", log.Fields{"Device": device})
891 }
892 d := NewVoltDevice(device, slno, southBoundID)
893
894 addPort := func(key, value interface{}) bool {
895 portID := key.(uint32)
896 port := value.(*PonPortCfg)
897 va.AggActiveChannelsCountForPonPort(device, portID, port)
898 d.ActiveChannelsPerPon.Store(portID, port)
899 return true
900 }
901 if nbDevice, exists := va.NbDevice.Load(southBoundID); exists {
902 // Pon Ports added before OLT activate.
903 nbDevice.(*NbDevice).PonPorts.Range(addPort)
904 } else {
905 // Check if NbPort exists in DB. VGC restart case.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530906 nbd := va.RestoreNbDeviceFromDb(cntx, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530907 nbd.PonPorts.Range(addPort)
908 }
909 va.DevicesDisc.Store(device, d)
910}
911
912// GetDevice to get a device.
913func (va *VoltApplication) GetDevice(device string) *VoltDevice {
914 if d, ok := va.DevicesDisc.Load(device); ok {
915 return d.(*VoltDevice)
916 }
917 return nil
918}
919
920// DelDevice to delete a device.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530921func (va *VoltApplication) DelDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530922 logger.Debugw(ctx, "Received Device Ind: Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530923 if vdIntf, ok := va.DevicesDisc.Load(device); ok {
924 vd := vdIntf.(*VoltDevice)
925 va.DevicesDisc.Delete(device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530926 _ = db.DelAllRoutesForDevice(cntx, device)
927 va.HandleFlowClearFlag(cntx, device, vd.SerialNum, vd.SouthBoundID)
928 _ = db.DelAllGroup(cntx, device)
929 _ = db.DelAllMeter(cntx, device)
930 _ = db.DelAllPorts(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530931 logger.Debugw(ctx, "Device deleted", log.Fields{"Device": device})
932 } else {
933 logger.Warnw(ctx, "Device Doesn't Exist", log.Fields{"Device": device})
934 }
935}
936
Akash Sonief452f12024-12-12 18:20:28 +0530937// CheckServiceExists to check if service exists for the given uniport and tech profile ID.
938func (va *VoltApplication) CheckServiceExists(port string, techProfID uint16) bool {
939 var serviceExists bool
940 va.ServiceByName.Range(func(key, existingServiceIntf interface{}) bool {
941 existingService := existingServiceIntf.(*VoltService)
942 if existingService.Port == port && existingService.TechProfileID == techProfID {
943 logger.Warnw(ctx, "Service already exists for same Port and TP. Ignoring add service request", log.Fields{"ExistingService": existingService.Name})
944 serviceExists = true
945 return false
946 }
947 return true
948 })
949 return serviceExists
950}
951
Naveen Sampath04696f72022-06-13 15:19:14 +0530952// GetDeviceBySerialNo to get a device by serial number.
953// TODO - Transform this into a MAP instead
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530954func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530955 logger.Debugw(ctx, "Received Device Ind: Get", log.Fields{"Serial Num": slno})
Naveen Sampath04696f72022-06-13 15:19:14 +0530956 var device *VoltDevice
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530957 var deviceID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530958 getserial := func(key interface{}, value interface{}) bool {
959 device = value.(*VoltDevice)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530960 deviceID = key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +0530961 return device.SerialNum != slno
962 }
963 va.DevicesDisc.Range(getserial)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530964 return device, deviceID
Naveen Sampath04696f72022-06-13 15:19:14 +0530965}
966
967// PortAddInd : This is a PORT add indication coming from the VPAgent, which is essentially
968// a request coming from VOLTHA. The device and identity of the port is provided
969// in this request. Add them to the application for further use
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530970func (va *VoltApplication) PortAddInd(cntx context.Context, device string, id uint32, portName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530971 logger.Debugw(ctx, "Received Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530972 va.portLock.Lock()
973 if d := va.GetDevice(device); d != nil {
974 p := d.AddPort(portName, id)
975 va.PortsDisc.Store(portName, p)
976 va.portLock.Unlock()
977 nni, _ := va.GetNniPort(device)
978 if nni == portName {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530979 d.pushFlowsForUnis(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530980 }
981 } else {
982 va.portLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530983 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 +0530984 }
985}
986
987// PortDelInd : Only the NNI ports are recorded in the device for now. When port delete
988// arrives, only the NNI ports need adjustments.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530989func (va *VoltApplication) PortDelInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530990 logger.Debugw(ctx, "Received Port Ind: Delete", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530991 if d := va.GetDevice(device); d != nil {
992 p := d.GetPort(port)
993 if p != nil && p.State == PortStateUp {
994 logger.Infow(ctx, "Port state is UP. Trigerring Port Down Ind before deleting", log.Fields{"Port": p})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530995 va.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530996 }
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530997 // if RemoveFlowsOnDisable is flase, then flows will be existing till port delete. Remove the flows now
998 if !va.OltFlowServiceConfig.RemoveFlowsOnDisable {
Akash Sonia8246972023-01-03 10:37:08 +0530999 vpvs, ok := va.VnetsByPort.Load(port)
1000 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05301001 logger.Infow(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
1002 } else {
1003 for _, vpv := range vpvs.([]*VoltPortVnet) {
1004 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301005 // Set delFlowsInDevice to true to delete flows only in DB/device during Port Delete.
1006 vpv.PortDownInd(cntx, device, port, true, true)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05301007 vpv.VpvLock.Unlock()
1008 }
1009 }
1010 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301011 va.portLock.Lock()
1012 defer va.portLock.Unlock()
1013 d.DelPort(port)
1014 if _, ok := va.PortsDisc.Load(port); ok {
1015 va.PortsDisc.Delete(port)
1016 }
1017 } else {
1018 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Delete", log.Fields{"Device": device, "Port": port})
1019 }
1020}
1021
vinokuma926cb3e2023-03-29 11:41:06 +05301022// PortUpdateInd Updates port Id incase of ONU movement
Naveen Sampath04696f72022-06-13 15:19:14 +05301023func (va *VoltApplication) PortUpdateInd(device string, portName string, id uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301024 logger.Debugw(ctx, "Received Port Ind: Update", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301025 va.portLock.Lock()
1026 defer va.portLock.Unlock()
1027 if d := va.GetDevice(device); d != nil {
1028 vp := d.GetPort(portName)
1029 vp.ID = id
1030 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301031 logger.Warnw(ctx, "Device Not Found", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301032 }
1033}
1034
1035// AddNbPonPort Add pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301036func (va *VoltApplication) AddNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +05301037 enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301038 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 +05301039 var nbd *NbDevice
1040 nbDevice, ok := va.NbDevice.Load(oltSbID)
1041
1042 if !ok {
1043 nbd = NewNbDevice()
1044 nbd.SouthBoundID = oltSbID
1045 } else {
1046 nbd = nbDevice.(*NbDevice)
1047 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301048 port := nbd.AddPortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301049 logger.Debugw(ctx, "Added Port To NbDevice", log.Fields{"port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301050 // Add this port to voltDevice
1051 addPort := func(key, value interface{}) bool {
1052 voltDevice := value.(*VoltDevice)
1053 if oltSbID == voltDevice.SouthBoundID {
1054 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); !exists {
1055 voltDevice.ActiveChannelsPerPon.Store(portID, port)
1056 }
1057 return false
1058 }
1059 return true
1060 }
1061 va.DevicesDisc.Range(addPort)
1062 va.NbDevice.Store(oltSbID, nbd)
1063
1064 return nil
1065}
1066
1067// UpdateNbPonPort update pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301068func (va *VoltApplication) UpdateNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301069 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 +05301070 var nbd *NbDevice
1071 nbDevice, ok := va.NbDevice.Load(oltSbID)
1072
1073 if !ok {
1074 logger.Errorw(ctx, "Device-doesn't-exists", log.Fields{"deviceID": oltSbID})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301075 return fmt.Errorf("device-doesn't-exists - %s", oltSbID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301076 }
1077 nbd = nbDevice.(*NbDevice)
1078
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301079 port := nbd.UpdatePortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301080 if port == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301081 return fmt.Errorf("port-doesn't-exists-%d", portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301082 }
1083 va.NbDevice.Store(oltSbID, nbd)
1084
1085 // Add this port to voltDevice
1086 updPort := func(key, value interface{}) bool {
1087 voltDevice := value.(*VoltDevice)
1088 if oltSbID == voltDevice.SouthBoundID {
1089 voltDevice.ActiveChannelCountLock.Lock()
1090 if p, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1091 oldPort := p.(*PonPortCfg)
1092 if port.MaxActiveChannels != 0 {
1093 oldPort.MaxActiveChannels = port.MaxActiveChannels
1094 oldPort.EnableMulticastKPI = port.EnableMulticastKPI
1095 voltDevice.ActiveChannelsPerPon.Store(portID, oldPort)
1096 }
1097 }
1098 voltDevice.ActiveChannelCountLock.Unlock()
1099 return false
1100 }
1101 return true
1102 }
1103 va.DevicesDisc.Range(updPort)
1104
1105 return nil
1106}
1107
1108// DeleteNbPonPort Delete pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301109func (va *VoltApplication) DeleteNbPonPort(cntx context.Context, oltSbID string, portID uint32) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301110 logger.Debugw(ctx, "Received NbPonPort Ind: Delete", log.Fields{"oltSbID": oltSbID, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301111 nbDevice, ok := va.NbDevice.Load(oltSbID)
1112 if ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301113 nbDevice.(*NbDevice).DeletePortFromNbDevice(cntx, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301114 va.NbDevice.Store(oltSbID, nbDevice.(*NbDevice))
1115 } else {
1116 logger.Warnw(ctx, "Delete pon received for unknown device", log.Fields{"oltSbID": oltSbID})
1117 return nil
1118 }
1119 // Delete this port from voltDevice
1120 delPort := func(key, value interface{}) bool {
1121 voltDevice := value.(*VoltDevice)
1122 if oltSbID == voltDevice.SouthBoundID {
1123 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1124 voltDevice.ActiveChannelsPerPon.Delete(portID)
1125 }
1126 return false
1127 }
1128 return true
1129 }
1130 va.DevicesDisc.Range(delPort)
1131 return nil
1132}
1133
1134// GetNniPort : Get the NNI port for a device. Called from different other applications
1135// as a port to match or destination for a packet out. The VOLT application
1136// is written with the assumption that there is a single NNI port. The OLT
1137// device is responsible for translating the combination of VLAN and the
1138// NNI port ID to identify possibly a single physical port or a logical
1139// port which is a result of protection methods applied.
1140func (va *VoltApplication) GetNniPort(device string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301141 logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301142 va.portLock.Lock()
1143 defer va.portLock.Unlock()
1144 d, ok := va.DevicesDisc.Load(device)
1145 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301146 return "", errors.New("device doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301147 }
1148 return d.(*VoltDevice).NniPort, nil
1149}
1150
1151// NniDownInd process for Nni down indication.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301152func (va *VoltApplication) NniDownInd(cntx context.Context, deviceID string, devSrNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301153 logger.Debugw(ctx, "NNI Down Ind", log.Fields{"DeviceID": deviceID, "Device SrNo": devSrNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301154
1155 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1156 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301157 mvProfile.removeIgmpMcastFlows(cntx, devSrNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301158 return true
1159 }
1160 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1161
1162 //Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301163 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301164}
1165
1166// DeviceUpInd changes device state to up.
1167func (va *VoltApplication) DeviceUpInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301168 logger.Infow(ctx, "Received Device Ind: UP", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301169 if d := va.GetDevice(device); d != nil {
1170 d.State = controller.DeviceStateUP
1171 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301172 logger.Warnw(ctx, "Ignoring Device indication: UP. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301173 }
1174}
1175
1176// DeviceDownInd changes device state to down.
1177func (va *VoltApplication) DeviceDownInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301178 logger.Infow(ctx, "Received Device Ind: DOWN", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301179 if d := va.GetDevice(device); d != nil {
1180 d.State = controller.DeviceStateDOWN
1181 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301182 logger.Warnw(ctx, "Ignoring Device indication: DOWN. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301183 }
1184}
1185
1186// DeviceRebootInd process for handling flow clear flag for device reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301187func (va *VoltApplication) DeviceRebootInd(cntx context.Context, device string, serialNum string, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301188 logger.Infow(ctx, "Received Device Ind: Reboot", log.Fields{"Device": device, "SerialNumber": serialNum, "SouthBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301189
1190 if d := va.GetDevice(device); d != nil {
1191 if d.State == controller.DeviceStateREBOOTED {
1192 logger.Warnw(ctx, "Ignoring Device Ind: Reboot, Device already in Reboot state", log.Fields{"Device": device, "SerialNumber": serialNum, "State": d.State})
1193 return
1194 }
1195 d.State = controller.DeviceStateREBOOTED
1196 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301197 va.HandleFlowClearFlag(cntx, device, serialNum, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301198}
1199
1200// DeviceDisableInd handles device deactivation process
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301201func (va *VoltApplication) DeviceDisableInd(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301202 logger.Infow(ctx, "Received Device Ind: Disable", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301203
1204 d := va.GetDevice(device)
1205 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301206 logger.Warnw(ctx, "Ignoring Device indication: DISABLED. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301207 return
1208 }
1209
1210 d.State = controller.DeviceStateDISABLED
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301211 va.HandleFlowClearFlag(cntx, device, d.SerialNum, d.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301212}
1213
1214// ProcessIgmpDSFlowForMvlan for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301215func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301216 logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
1217 portState := false
1218 p := d.GetPort(d.NniPort)
1219 if p != nil && p.State == PortStateUp {
1220 portState = true
1221 }
1222
1223 if addFlow {
1224 if portState {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301225 mvp.pushIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301226 }
1227 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301228 mvp.removeIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301229 }
1230}
1231
1232// ProcessIgmpDSFlowForDevice for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301233func (va *VoltApplication) ProcessIgmpDSFlowForDevice(cntx context.Context, d *VoltDevice, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301234 logger.Debugw(ctx, "Process IGMP DS Flows for device", log.Fields{"device": d.Name, "addFlow": addFlow})
1235
1236 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1237 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301238 va.ProcessIgmpDSFlowForMvlan(cntx, d, mvProfile, addFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301239 return true
1240 }
1241 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1242}
1243
1244// GetDeviceFromPort : This is suitable only for access ports as their naming convention
1245// makes them unique across all the OLTs. This must be called with
1246// port name that is an access port. Currently called from VNETs, attached
1247// only to access ports, and the services which are also attached only
1248// to access ports
1249func (va *VoltApplication) GetDeviceFromPort(port string) (*VoltDevice, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301250 logger.Debugw(ctx, "Received Get Device From Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301251 va.portLock.Lock()
1252 defer va.portLock.Unlock()
1253 var err error
1254 err = nil
1255 p, ok := va.PortsDisc.Load(port)
1256 if !ok {
1257 return nil, errorCodes.ErrPortNotFound
1258 }
1259 d := va.GetDevice(p.(*VoltPort).Device)
1260 if d == nil {
1261 err = errorCodes.ErrDeviceNotFound
1262 }
1263 return d, err
1264}
1265
1266// GetPortID : This too applies only to access ports. The ports can be indexed
1267// purely by their names without the device forming part of the key
1268func (va *VoltApplication) GetPortID(port string) (uint32, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301269 logger.Debugw(ctx, "Received Get Port ID", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301270 va.portLock.Lock()
1271 defer va.portLock.Unlock()
1272 p, ok := va.PortsDisc.Load(port)
1273 if !ok {
1274 return 0, errorCodes.ErrPortNotFound
1275 }
1276 return p.(*VoltPort).ID, nil
1277}
1278
1279// GetPortName : This too applies only to access ports. The ports can be indexed
1280// purely by their names without the device forming part of the key
1281func (va *VoltApplication) GetPortName(port uint32) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301282 logger.Debugw(ctx, "Received Get Port Name", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301283 va.portLock.Lock()
1284 defer va.portLock.Unlock()
1285 var portName string
1286 va.PortsDisc.Range(func(key interface{}, value interface{}) bool {
1287 portInfo := value.(*VoltPort)
1288 if portInfo.ID == port {
1289 portName = portInfo.Name
1290 return false
1291 }
1292 return true
1293 })
1294 return portName, nil
1295}
1296
1297// GetPonFromUniPort to get Pon info from UniPort
1298func (va *VoltApplication) GetPonFromUniPort(port string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301299 logger.Debugw(ctx, "Received Get Pon From UniPort", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301300 uniPortID, err := va.GetPortID(port)
1301 if err == nil {
1302 ponPortID := (uniPortID & 0x0FF00000) >> 20 //pon(8) + onu(8) + uni(12)
1303 return strconv.FormatUint(uint64(ponPortID), 10), nil
1304 }
1305 return "", err
1306}
1307
1308// GetPortState : This too applies only to access ports. The ports can be indexed
1309// purely by their names without the device forming part of the key
1310func (va *VoltApplication) GetPortState(port string) (PortState, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301311 logger.Debugw(ctx, "Received Get Port State", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 va.portLock.Lock()
1313 defer va.portLock.Unlock()
1314 p, ok := va.PortsDisc.Load(port)
1315 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301316 return 0, errors.New("port not configured")
Naveen Sampath04696f72022-06-13 15:19:14 +05301317 }
1318 return p.(*VoltPort).State, nil
1319}
1320
1321// GetIcmpv6Receivers to get Icmp v6 receivers
1322func (va *VoltApplication) GetIcmpv6Receivers(device string) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301323 logger.Debugw(ctx, "Get Icmpv6 Receivers", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301324 var receiverList []uint32
1325 receivers, _ := va.Icmpv6Receivers.Load(device)
1326 if receivers != nil {
1327 receiverList = receivers.([]uint32)
1328 }
1329 return receiverList
1330}
1331
1332// AddIcmpv6Receivers to add Icmp v6 receivers
1333func (va *VoltApplication) AddIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301334 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301335 var receiverList []uint32
1336 receivers, _ := va.Icmpv6Receivers.Load(device)
1337 if receivers != nil {
1338 receiverList = receivers.([]uint32)
1339 }
1340 receiverList = append(receiverList, portID)
1341 va.Icmpv6Receivers.Store(device, receiverList)
1342 logger.Debugw(ctx, "Receivers after addition", log.Fields{"Receivers": receiverList})
1343 return receiverList
1344}
1345
1346// DelIcmpv6Receivers to delete Icmp v6 receievers
1347func (va *VoltApplication) DelIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301348 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301349 var receiverList []uint32
1350 receivers, _ := va.Icmpv6Receivers.Load(device)
1351 if receivers != nil {
1352 receiverList = receivers.([]uint32)
1353 }
1354 for i, port := range receiverList {
1355 if port == portID {
1356 receiverList = append(receiverList[0:i], receiverList[i+1:]...)
1357 va.Icmpv6Receivers.Store(device, receiverList)
1358 break
1359 }
1360 }
1361 logger.Debugw(ctx, "Receivers After deletion", log.Fields{"Receivers": receiverList})
1362 return receiverList
1363}
1364
1365// ProcessDevFlowForDevice - Process DS ICMPv6 & ARP flow for provided device and vnet profile
1366// device - Device Obj
1367// vnet - vnet profile name
1368// enabled - vlan enabled/disabled - based on the status, the flow shall be added/removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301369func (va *VoltApplication) ProcessDevFlowForDevice(cntx context.Context, device *VoltDevice, vnet *VoltVnet, enabled bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301370 logger.Debugw(ctx, "Process Dev Flow For Device", log.Fields{"Device": device, "VnetName": vnet.Name, "Enabled": enabled})
Naveen Sampath04696f72022-06-13 15:19:14 +05301371 _, applied := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0))
1372 if enabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301373 va.PushDevFlowForVlan(cntx, vnet)
Naveen Sampath04696f72022-06-13 15:19:14 +05301374 } else if !enabled && applied {
1375 //va.DeleteDevFlowForVlan(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301376 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, device.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301377 }
1378}
1379
vinokuma926cb3e2023-03-29 11:41:06 +05301380// NniVlanIndToIgmp - Trigger receiver up indication to all ports with igmp enabled
1381// and has the provided mvlan
Naveen Sampath04696f72022-06-13 15:19:14 +05301382func (va *VoltApplication) NniVlanIndToIgmp(device *VoltDevice, mvp *MvlanProfile) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301383 logger.Infow(ctx, "Received Nni Vlan Ind To Igmp", log.Fields{"Vlan": mvp.Mvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301384
vinokuma926cb3e2023-03-29 11:41:06 +05301385 // Trigger nni indication for receiver only for first time
Naveen Sampath04696f72022-06-13 15:19:14 +05301386 if device.IgmpDsFlowAppliedForMvlan[uint16(mvp.Mvlan)] {
1387 return
1388 }
1389 device.Ports.Range(func(key, value interface{}) bool {
1390 port := key.(string)
1391
1392 if state, _ := va.GetPortState(port); state == PortStateUp {
1393 vpvs, _ := va.VnetsByPort.Load(port)
1394 if vpvs == nil {
1395 return true
1396 }
1397 for _, vpv := range vpvs.([]*VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05301398 // Send indication only for subscribers with the received mvlan profile
Naveen Sampath04696f72022-06-13 15:19:14 +05301399 if vpv.IgmpEnabled && vpv.MvlanProfileName == mvp.Name {
1400 vpv.services.Range(ReceiverUpInd)
1401 }
1402 }
1403 }
1404 return true
1405 })
1406}
1407
1408// PortUpInd :
1409// -----------------------------------------------------------------------
1410// Port status change handling
1411// ----------------------------------------------------------------------
1412// Port UP indication is passed to all services associated with the port
1413// so that the services can configure flows applicable when the port goes
1414// up from down state
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301415func (va *VoltApplication) PortUpInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301416 logger.Infow(ctx, "Received Southbound Port Ind: UP", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301417 d := va.GetDevice(device)
1418
1419 if d == nil {
1420 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: UP", log.Fields{"Device": device, "Port": port})
1421 return
1422 }
1423
vinokuma926cb3e2023-03-29 11:41:06 +05301424 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301425 va.portLock.Lock()
1426 // Do not defer the port mutex unlock here
1427 // Some of the following func calls needs the port lock, so defering the lock here
1428 // may lead to dead-lock
1429 p := d.GetPort(port)
1430
1431 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301432 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 +05301433 va.portLock.Unlock()
1434 return
1435 }
1436 p.State = PortStateUp
1437 va.portLock.Unlock()
1438
Naveen Sampath04696f72022-06-13 15:19:14 +05301439 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301440 logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301441 //va.PushDevFlowForDevice(d)
1442 //Build Igmp TrapFlowRule
1443 //va.ProcessIgmpDSFlowForDevice(d, true)
1444 }
1445 vpvs, ok := va.VnetsByPort.Load(port)
1446 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301447 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301448 //msgbus.ProcessPortInd(msgbus.PortUp, d.SerialNum, p.Name, false, getServiceList(port))
1449 return
1450 }
1451
vinokuma926cb3e2023-03-29 11:41:06 +05301452 // If NNI port is not UP, do not push Flows
Naveen Sampath04696f72022-06-13 15:19:14 +05301453 if d.NniPort == "" {
1454 logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
1455 return
1456 }
1457
Naveen Sampath04696f72022-06-13 15:19:14 +05301458 for _, vpv := range vpvs.([]*VoltPortVnet) {
1459 vpv.VpvLock.Lock()
vinokuma926cb3e2023-03-29 11:41:06 +05301460 // If no service is activated drop the portUpInd
Tinoj Josephec742f62022-09-29 19:11:10 +05301461 if vpv.IsServiceActivated(cntx) {
vinokuma926cb3e2023-03-29 11:41:06 +05301462 // Do not trigger indication for the vpv which is already removed from vpv list as
Tinoj Josephec742f62022-09-29 19:11:10 +05301463 // part of service delete (during the lock wait duration)
1464 // In that case, the services associated wil be zero
1465 if vpv.servicesCount.Load() != 0 {
1466 vpv.PortUpInd(cntx, d, port)
1467 }
1468 } else {
1469 // Service not activated, still attach device to service
1470 vpv.setDevice(d.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301471 }
1472 vpv.VpvLock.Unlock()
1473 }
1474 // At the end of processing inform the other entities that
1475 // are interested in the events
1476}
1477
1478/*
1479func getServiceList(port string) map[string]bool {
1480 serviceList := make(map[string]bool)
1481
1482 getServiceNames := func(key interface{}, value interface{}) bool {
1483 serviceList[key.(string)] = value.(*VoltService).DsHSIAFlowsApplied
1484 return true
1485 }
1486
1487 if vpvs, _ := GetApplication().VnetsByPort.Load(port); vpvs != nil {
1488 vpvList := vpvs.([]*VoltPortVnet)
1489 for _, vpv := range vpvList {
1490 vpv.services.Range(getServiceNames)
1491 }
1492 }
1493 return serviceList
1494
1495}*/
1496
vinokuma926cb3e2023-03-29 11:41:06 +05301497// ReceiverUpInd - Send receiver up indication for service with Igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301498func ReceiverUpInd(key, value interface{}) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301499 logger.Info(ctx, "Receiver Indication: UP")
Naveen Sampath04696f72022-06-13 15:19:14 +05301500 svc := value.(*VoltService)
1501 var vlan of.VlanType
1502
1503 if !svc.IPAssigned() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301504 logger.Warnw(ctx, "IP Not assigned, skipping general query", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +05301505 return false
1506 }
1507
vinokuma926cb3e2023-03-29 11:41:06 +05301508 // Send port up indication to igmp only for service with igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301509 if svc.IgmpEnabled {
1510 if svc.VlanControl == ONUCVlan || svc.VlanControl == ONUCVlanOLTSVlan {
1511 vlan = svc.CVlan
1512 } else {
1513 vlan = svc.UniVlan
1514 }
1515 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
1516 GetApplication().ReceiverUpInd(device.Name, svc.Port, svc.MvlanProfileName, vlan, svc.Pbits)
1517 }
1518 return false
1519 }
1520 return true
1521}
1522
1523// PortDownInd : Port down indication is passed on to the services so that the services
1524// can make changes at this transition.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301525func (va *VoltApplication) PortDownInd(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301526 logger.Infow(ctx, "Received SouthBound Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1527 d := va.GetDevice(device)
1528
1529 if d == nil {
1530 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1531 return
1532 }
vinokuma926cb3e2023-03-29 11:41:06 +05301533 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301534 va.portLock.Lock()
1535 // Do not defer the port mutex unlock here
1536 // Some of the following func calls needs the port lock, so defering the lock here
1537 // may lead to dead-lock
1538 p := d.GetPort(port)
1539 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301540 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 +05301541 va.portLock.Unlock()
1542 return
1543 }
1544 p.State = PortStateDown
1545 va.portLock.Unlock()
1546
1547 if d.State == controller.DeviceStateREBOOTED {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301548 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 +05301549 return
1550 }
1551
1552 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301553 logger.Debugw(ctx, "Received NNI Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301554 va.DeleteDevFlowForDevice(cntx, d)
1555 va.NniDownInd(cntx, device, d.SerialNum)
1556 va.RemovePendingGroups(cntx, device, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301557 }
1558 vpvs, ok := va.VnetsByPort.Load(port)
1559 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301560 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301561 //msgbus.ProcessPortInd(msgbus.PortDown, d.SerialNum, p.Name, false, getServiceList(port))
1562 return
1563 }
Akash Sonia8246972023-01-03 10:37:08 +05301564
Naveen Sampath04696f72022-06-13 15:19:14 +05301565 for _, vpv := range vpvs.([]*VoltPortVnet) {
1566 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301567 vpv.PortDownInd(cntx, device, port, false, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301568 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301569 va.ReceiverDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301570 }
1571 vpv.VpvLock.Unlock()
1572 }
1573}
1574
1575// PacketInInd :
1576// -----------------------------------------------------------------------
1577// PacketIn Processing
1578// Packet In Indication processing. It arrives with the identities of
1579// the device and port on which the packet is received. At first, the
1580// packet is decoded and the right processor is called. Currently, we
1581// plan to support only DHCP and IGMP. In future, we can add more
1582// capabilities as needed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301583func (va *VoltApplication) PacketInInd(cntx context.Context, device string, port string, pkt []byte) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301584 logger.Infow(ctx, "Received a Packet-In Indication", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301585 // Decode the incoming packet
1586 packetSide := US
1587 if strings.Contains(port, NNI) {
1588 packetSide = DS
1589 }
1590
Naveen Sampath04696f72022-06-13 15:19:14 +05301591 gopkt := gopacket.NewPacket(pkt, layers.LayerTypeEthernet, gopacket.Default)
1592
1593 var dot1qFound = false
1594 for _, l := range gopkt.Layers() {
1595 if l.LayerType() == layers.LayerTypeDot1Q {
1596 dot1qFound = true
1597 break
1598 }
1599 }
1600
1601 if !dot1qFound {
1602 logger.Debugw(ctx, "Ignoring Received Packet-In Indication without Dot1Q Header",
1603 log.Fields{"Device": device, "Port": port})
1604 return
1605 }
1606
1607 logger.Debugw(ctx, "Received Southbound Packet In", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1608
1609 // Classify the packet into packet types that we support
1610 // The supported types are DHCP and IGMP. The DHCP packet is
1611 // identified by matching the L4 protocol to UDP. The IGMP packet
1612 // is identified by matching L3 protocol to IGMP
1613 arpl := gopkt.Layer(layers.LayerTypeARP)
1614 if arpl != nil {
1615 if callBack, ok := PacketHandlers[ARP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301616 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301617 } else {
1618 logger.Debugw(ctx, "ARP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1619 }
1620 return
1621 }
1622 ipv4l := gopkt.Layer(layers.LayerTypeIPv4)
1623 if ipv4l != nil {
1624 ip := ipv4l.(*layers.IPv4)
1625
1626 if ip.Protocol == layers.IPProtocolUDP {
1627 logger.Debugw(ctx, "Received Southbound UDP ipv4 packet in", log.Fields{"StreamSide": packetSide})
1628 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv4)
1629 if dhcpl != nil {
1630 if callBack, ok := PacketHandlers[DHCPv4]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301631 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301632 } else {
1633 logger.Debugw(ctx, "DHCPv4 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1634 }
1635 }
1636 } else if ip.Protocol == layers.IPProtocolIGMP {
1637 logger.Debugw(ctx, "Received Southbound IGMP packet in", log.Fields{"StreamSide": packetSide})
1638 if callBack, ok := PacketHandlers[IGMP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301639 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301640 } else {
1641 logger.Debugw(ctx, "IGMP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1642 }
1643 }
1644 return
1645 }
1646 ipv6l := gopkt.Layer(layers.LayerTypeIPv6)
1647 if ipv6l != nil {
1648 ip := ipv6l.(*layers.IPv6)
1649 if ip.NextHeader == layers.IPProtocolUDP {
1650 logger.Debug(ctx, "Received Southbound UDP ipv6 packet in")
1651 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv6)
1652 if dhcpl != nil {
1653 if callBack, ok := PacketHandlers[DHCPv6]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301654 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301655 } else {
1656 logger.Debugw(ctx, "DHCPv6 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1657 }
1658 }
1659 }
1660 return
1661 }
1662
1663 pppoel := gopkt.Layer(layers.LayerTypePPPoE)
1664 if pppoel != nil {
1665 logger.Debugw(ctx, "Received Southbound PPPoE packet in", log.Fields{"StreamSide": packetSide})
1666 if callBack, ok := PacketHandlers[PPPOE]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301667 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301668 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301669 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 +05301670 }
1671 }
1672}
1673
1674// GetVlans : This utility gets the VLANs from the packet. The VLANs are
1675// used to identify the right service that must process the incoming
1676// packet
1677func GetVlans(pkt gopacket.Packet) []of.VlanType {
1678 var vlans []of.VlanType
1679 for _, l := range pkt.Layers() {
1680 if l.LayerType() == layers.LayerTypeDot1Q {
1681 q, ok := l.(*layers.Dot1Q)
1682 if ok {
1683 vlans = append(vlans, of.VlanType(q.VLANIdentifier))
1684 }
1685 }
1686 }
1687 return vlans
1688}
1689
1690// GetPriority to get priority
1691func GetPriority(pkt gopacket.Packet) uint8 {
1692 for _, l := range pkt.Layers() {
1693 if l.LayerType() == layers.LayerTypeDot1Q {
1694 q, ok := l.(*layers.Dot1Q)
1695 if ok {
1696 return q.Priority
1697 }
1698 }
1699 }
1700 return PriorityNone
1701}
1702
1703// HandleFlowClearFlag to handle flow clear flag during reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301704func (va *VoltApplication) HandleFlowClearFlag(cntx context.Context, deviceID string, serialNum, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301705 logger.Infow(ctx, "Clear All flags for Device", log.Fields{"Device": deviceID, "SerialNum": serialNum, "SBID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301706 dev, ok := va.DevicesDisc.Load(deviceID)
1707 if ok && dev != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301708 logger.Debugw(ctx, "Clear Flags for device", log.Fields{"voltDevice": dev.(*VoltDevice).Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301709 dev.(*VoltDevice).icmpv6GroupAdded = false
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301710 logger.Debugw(ctx, "Clearing DS Icmpv6 Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301711 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1712 dev.(*VoltDevice).ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301713 logger.Debugw(ctx, "Clearing DS IGMP Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301714 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1715 for k := range dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan {
1716 delete(dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan, k)
1717 }
vinokuma926cb3e2023-03-29 11:41:06 +05301718 // Delete group 1 - ICMPv6/ARP group
Naveen Sampath04696f72022-06-13 15:19:14 +05301719 if err := ProcessIcmpv6McGroup(deviceID, true); err != nil {
1720 logger.Errorw(ctx, "ProcessIcmpv6McGroup failed", log.Fields{"Device": deviceID, "Error": err})
1721 }
1722 } else {
1723 logger.Warnw(ctx, "VoltDevice not found for device ", log.Fields{"deviceID": deviceID})
1724 }
1725
1726 getVpvs := func(key interface{}, value interface{}) bool {
1727 vpvs := value.([]*VoltPortVnet)
1728 for _, vpv := range vpvs {
1729 if vpv.Device == deviceID {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301730 logger.Debugw(ctx, "Clear Flags for vpv",
Naveen Sampath04696f72022-06-13 15:19:14 +05301731 log.Fields{"device": vpv.Device, "port": vpv.Port,
1732 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301733 vpv.ClearAllServiceFlags(cntx)
1734 vpv.ClearAllVpvFlags(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301735
1736 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301737 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05301738 // Also clear service igmp stats
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301739 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301740 }
1741 }
1742 }
1743 return true
1744 }
1745 va.VnetsByPort.Range(getVpvs)
1746
vinokuma926cb3e2023-03-29 11:41:06 +05301747 // Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301748 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301749
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301750 logger.Infow(ctx, "All flags cleared for device", log.Fields{"Device": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301751
vinokuma926cb3e2023-03-29 11:41:06 +05301752 // Reset pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301753 va.RemovePendingGroups(cntx, deviceID, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301754
vinokuma926cb3e2023-03-29 11:41:06 +05301755 // Process all Migrate Service Request - force udpate all profiles since resources are already cleaned up
Naveen Sampath04696f72022-06-13 15:19:14 +05301756 if dev != nil {
1757 triggerForceUpdate := func(key, value interface{}) bool {
1758 msrList := value.(*util.ConcurrentMap)
1759 forceUpdateServices := func(key, value interface{}) bool {
1760 msr := value.(*MigrateServicesRequest)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301761 forceUpdateAllServices(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301762 return true
1763 }
1764 msrList.Range(forceUpdateServices)
1765 return true
1766 }
1767 dev.(*VoltDevice).MigratingServices.Range(triggerForceUpdate)
1768 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301769 va.FetchAndProcessAllMigrateServicesReq(cntx, deviceID, forceUpdateAllServices)
Naveen Sampath04696f72022-06-13 15:19:14 +05301770 }
1771}
1772
vinokuma926cb3e2023-03-29 11:41:06 +05301773// GetPonPortIDFromUNIPort to get pon port id from uni port
Naveen Sampath04696f72022-06-13 15:19:14 +05301774func GetPonPortIDFromUNIPort(uniPortID uint32) uint32 {
1775 ponPortID := (uniPortID & 0x0FF00000) >> 20
1776 return ponPortID
1777}
1778
vinokuma926cb3e2023-03-29 11:41:06 +05301779// ProcessFlowModResultIndication - Processes Flow mod operation indications from controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301780func (va *VoltApplication) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301781 logger.Debugw(ctx, "Received Flow Mod Result Indication.", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301782 d := va.GetDevice(flowStatus.Device)
1783 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301784 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 +05301785 return
1786 }
1787
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301788 cookieExists := ExecuteFlowEvent(cntx, d, flowStatus.Cookie, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +05301789
1790 if flowStatus.Flow != nil {
1791 flowAdd := (flowStatus.FlowModType == of.CommandAdd)
1792 if !cookieExists && !isFlowStatusSuccess(flowStatus.Status, flowAdd) {
1793 pushFlowFailureNotif(flowStatus)
1794 }
1795 }
1796}
1797
Akash Sonief452f12024-12-12 18:20:28 +05301798// CheckAndDeactivateService - check if the attempts for flow delete has reached threshold or not
1799func (va *VoltApplication) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
1800 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 +05301801 if flow.FlowCount >= uint32(controller.GetController().GetMaxFlowRetryAttempt()) {
Akash Sonief452f12024-12-12 18:20:28 +05301802 devConfig := va.GetDeviceConfig(devSerialNum)
1803 if devConfig != nil {
1804 portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, flow)
1805 portName, err := va.GetPortName(portNo)
1806 if err != nil {
1807 logger.Warnw(ctx, "Error getting port name", log.Fields{"Reason": err.Error(), "PortID": portNo})
1808 return
1809 } else if portName == "" {
1810 logger.Warnw(ctx, "Port does not exist", log.Fields{"PortID": portNo})
1811 return
1812 }
1813 svc := va.GetServiceNameFromCookie(flow.Cookie, portName, uint8(of.PbitMatchNone), devID, flow.Match.TableMetadata)
1814 if svc != nil {
1815 va.DeactivateServiceForPort(ctx, svc, devID, portName)
1816 }
1817 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301818 }
Akash Sonief452f12024-12-12 18:20:28 +05301819}
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301820
Akash Sonief452f12024-12-12 18:20:28 +05301821// DeactivateServiceForPort - deactivate service for given UNI and remove flows from DB, after max flow install threshold has reached
1822func (va *VoltApplication) DeactivateServiceForPort(cntx context.Context, vs *VoltService, devID string, portName string) {
1823 logger.Debugw(ctx, "Flow install threshold reached. Deactivating service", log.Fields{"Service": vs.Name, "Port": portName})
1824
1825 if devID == vs.Device && portName == vs.Port && vs.IsActivated {
1826 vs.SetSvcDeactivationFlags(SvcDeacRsn_Controller)
1827 va.ServiceByName.Store(vs.Name, vs)
1828 vs.WriteToDb(cntx)
1829 device, err := va.GetDeviceFromPort(portName)
1830 if err != nil {
1831 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
1832 // So no error is returned
1833 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portName})
1834 }
1835 p := device.GetPort(vs.Port)
1836 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
1837 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
1838 // Port down call internally deletes all the flows
1839 vpv.PortDownInd(cntx, device.Name, portName, true, true)
1840 if vpv.IgmpEnabled {
1841 va.ReceiverDownInd(cntx, device.Name, portName)
1842 }
1843 } else {
1844 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": device.Name, "port": portName, "SvcName": vs.Name})
1845 }
1846 logger.Infow(ctx, "Service deactivated after flow install threshold", log.Fields{"Device": device.Name, "Service": vs.Name, "Port": portName})
1847 }
1848 vs.DeactivateInProgress = false
1849 va.ServiceByName.Store(vs.Name, vs)
1850 vs.WriteToDb(cntx)
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301851 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301852}
1853
Naveen Sampath04696f72022-06-13 15:19:14 +05301854func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1855 subFlow := flowStatus.Flow
1856 cookie := subFlow.Cookie
1857 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301858 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301859}
1860
vinokuma926cb3e2023-03-29 11:41:06 +05301861// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301862func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301863 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301864 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1865 mvp := value.(*MvlanProfile)
1866 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301867 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301868 }
1869 return true
1870 }
1871 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1872}
1873
1874// TaskInfo structure that is used to store the task Info.
1875type TaskInfo struct {
1876 ID string
1877 Name string
1878 Timestamp string
1879}
1880
1881// GetTaskList to get task list information.
1882func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301883 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301884 taskList := cntlr.GetController().GetTaskList(device)
1885 taskMap := make(map[int]*TaskInfo)
1886 for i, task := range taskList {
1887 taskID := strconv.Itoa(int(task.TaskID()))
1888 name := task.Name()
1889 timestamp := task.Timestamp()
1890 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1891 taskMap[i] = taskInfo
1892 }
1893 return taskMap
1894}
1895
1896// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1897func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301898 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301899 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301900
1901 if voltDevice != nil {
1902 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301903 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 +05301904 } else {
1905 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301906 // Add Serial Number to Blocked Devices List.
1907 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1908 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1909
1910 updateSlNoForVnet := func(key, value interface{}) bool {
1911 vnet := value.(*VoltVnet)
1912 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1913 if deviceSlNo == oldOltSlNo {
1914 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1915 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1916 break
1917 }
1918 }
1919 return true
1920 }
1921
1922 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1923 mvProfile := value.(*MvlanProfile)
1924 for deviceSlNo := range mvProfile.DevicesList {
1925 if deviceSlNo == oldOltSlNo {
1926 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1927 delete(mvProfile.DevicesList, oldOltSlNo)
1928 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1929 break
1930 }
1931 }
1932 return true
1933 }
1934
1935 va.VnetsByName.Range(updateSlNoForVnet)
1936 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1937
1938 // Clear the serial number from Blocked Devices List
1939 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1940 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301941 }
1942}
1943
1944// GetVpvsForDsPkt to get vpv for downstream packets
1945func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1946 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301947 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301948 var matchVPVs []*VoltPortVnet
1949 findVpv := func(key, value interface{}) bool {
1950 vpvs := value.([]*VoltPortVnet)
1951 for _, vpv := range vpvs {
1952 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1953 var subMac net.HardwareAddr
1954 if NonZeroMacAddress(vpv.MacAddr) {
1955 subMac = vpv.MacAddr
1956 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
1957 subMac = vpv.LearntMacAddr
1958 } else {
1959 matchVPVs = append(matchVPVs, vpv)
1960 continue
1961 }
1962 if util.MacAddrsMatch(subMac, clientMAC) {
1963 matchVPVs = append([]*VoltPortVnet{}, vpv)
1964 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
1965 return false
1966 }
1967 }
1968 }
1969 return true
1970 }
1971 va.VnetsByPort.Range(findVpv)
1972
1973 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301974 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
1975 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301976 }
1977 return matchVPVs, nil
1978}
1979
1980// GetMacInPortMap to get PORT value based on MAC key
1981func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301982 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301983 if NonZeroMacAddress(macAddr) {
1984 va.macPortLock.Lock()
1985 defer va.macPortLock.Unlock()
1986 if port, ok := va.macPortMap[macAddr.String()]; ok {
1987 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1988 return port
1989 }
1990 }
1991 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
1992 return ""
1993}
1994
1995// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
1996func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301997 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301998 if NonZeroMacAddress(macAddr) {
1999 va.macPortLock.Lock()
2000 va.macPortMap[macAddr.String()] = port
2001 va.macPortLock.Unlock()
2002 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2003 }
2004}
2005
2006// DeleteMacInPortMap to remove MAC key from MacPortMap
2007func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302008 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05302009 if NonZeroMacAddress(macAddr) {
2010 port := va.GetMacInPortMap(macAddr)
2011 va.macPortLock.Lock()
2012 delete(va.macPortMap, macAddr.String())
2013 va.macPortLock.Unlock()
2014 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2015 }
2016}
2017
vinokuma926cb3e2023-03-29 11:41:06 +05302018// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302019func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
2020 var grpMap map[*IgmpGroup]bool
2021 var ok bool
2022
2023 va.PendingPoolLock.Lock()
2024 defer va.PendingPoolLock.Unlock()
2025
2026 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
2027 // Do Not Reset any current profile info since group table entry tied to mvlan profile
2028 // The PonVlan is part of set field in group installed
2029 // Hence, Group created is always tied to the same mvlan profile until deleted
2030
2031 for device := range ig.Devices {
2032 key := getPendingPoolKey(ig.Mvlan, device)
2033
2034 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
2035 grpMap = make(map[*IgmpGroup]bool)
2036 }
2037 grpMap[ig] = true
2038
2039 //Add grpObj reference to all associated devices
2040 va.IgmpPendingPool[key] = grpMap
2041 }
2042}
2043
vinokuma926cb3e2023-03-29 11:41:06 +05302044// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302045func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
2046 GetApplication().PendingPoolLock.Lock()
2047 defer GetApplication().PendingPoolLock.Unlock()
2048
2049 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)})
2050
2051 key := getPendingPoolKey(ig.Mvlan, device)
2052 if _, ok := va.IgmpPendingPool[key]; ok {
2053 delete(va.IgmpPendingPool[key], ig)
2054 return true
2055 }
2056 return false
2057}
2058
vinokuma926cb3e2023-03-29 11:41:06 +05302059// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302060func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302061 GetApplication().PendingPoolLock.Lock()
2062 defer GetApplication().PendingPoolLock.Unlock()
2063
2064 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
2065
2066 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302067 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302068}
2069
vinokuma926cb3e2023-03-29 11:41:06 +05302070// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05302071// 1. Deletes the group from device
2072// 2. Delete the IgmpGroup obj and release the group ID to pool
2073// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302074func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302075 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05302076 if grpMap, ok := va.IgmpPendingPool[key]; ok {
2077 delete(va.IgmpPendingPool, key)
2078 for ig := range grpMap {
2079 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302080 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302081 }
2082 }
2083 }
2084}
2085
vinokuma926cb3e2023-03-29 11:41:06 +05302086// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302087func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302088 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)})
2089 for device := range ig.PendingGroupForDevice {
2090 va.RemoveGroupFromPendingPool(device, ig)
2091 }
2092}
2093
vinokuma926cb3e2023-03-29 11:41:06 +05302094// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302095func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302096 var ig *IgmpGroup
2097
2098 va.PendingPoolLock.Lock()
2099 defer va.PendingPoolLock.Unlock()
2100
2101 key := getPendingPoolKey(mvlan, device)
2102 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2103
vinokuma926cb3e2023-03-29 11:41:06 +05302104 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302105 grpMap, ok := va.IgmpPendingPool[key]
2106 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302107 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 +05302108 return nil
2109 }
2110
vinokuma926cb3e2023-03-29 11:41:06 +05302111 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302112 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302113 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302114 for dev := range ig.Devices {
2115 key := getPendingPoolKey(mvlan, dev)
2116 delete(va.IgmpPendingPool[key], ig)
2117 }
2118
vinokuma926cb3e2023-03-29 11:41:06 +05302119 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302120 if ig.NumDevicesActive() == 0 {
2121 return ig
2122 }
2123
vinokuma926cb3e2023-03-29 11:41:06 +05302124 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302125 }
2126 return nil
2127}
2128
vinokuma926cb3e2023-03-29 11:41:06 +05302129// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302130// reference - mvlan/device ID
2131// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302132// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302133func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302134 va.PendingPoolLock.Lock()
2135 defer va.PendingPoolLock.Unlock()
2136
2137 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2138
vinokuma926cb3e2023-03-29 11:41:06 +05302139 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302140 paramPosition := 0
2141 if isRefDevice {
2142 paramPosition = 1
2143 }
2144
2145 // 1.Remove the Entry from pending pool
2146 // 2.Deletes the group from device
2147 // 3.Delete the IgmpGroup obj and release the group ID to pool
2148 for key := range va.IgmpPendingPool {
2149 keyParams := strings.Split(key, "_")
2150 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302151 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302152 }
2153 }
2154}
2155
2156func getPendingPoolKey(mvlan of.VlanType, device string) string {
2157 return mvlan.String() + "_" + device
2158}
2159
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302160func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302161 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302162 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2163 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302164 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302165 return true
2166 }
2167 va.IgmpGroups.Range(removeExpiredGroups)
2168}
2169
vinokuma926cb3e2023-03-29 11:41:06 +05302170// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302171func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302172 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302173 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302174 va.TriggerPendingServiceDeleteReq(cntx, device)
2175 va.TriggerPendingVpvDeleteReq(cntx, device)
2176 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302177 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302178}
2179
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302180// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2181func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302182 va.ServicesToDeactivate.Range(func(key, value interface{}) bool {
2183 serviceName := key.(string)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302184 if vs := va.GetService(serviceName); vs != nil {
2185 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302186 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302187 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2188 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302189 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 +05302190 return true
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302191 }
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302192 vpv.DelTrapFlows(cntx)
2193 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302194 // Set the flag to false and clear the SevicesToDeactivate map entry so that when core restarts, VGC will not
2195 // try to deactivate the service again
2196 vs.DeactivateInProgress = false
2197 va.ServicesToDeactivate.Delete(serviceName)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302198 vs.WriteToDb(cntx)
2199 vpv.ClearServiceCounters(cntx)
2200 }
2201 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302202 logger.Warnw(ctx, "Pending Service Not found during Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302203 }
Akash Sonief452f12024-12-12 18:20:28 +05302204 return true
2205 })
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302206}
2207
vinokuma926cb3e2023-03-29 11:41:06 +05302208// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302209func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302210 va.ServicesToDelete.Range(func(key, value interface{}) bool {
2211 serviceName := key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +05302212 if vs := va.GetService(serviceName); vs != nil {
2213 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302214 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302215 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302216 // Clear the SevicesToDelete map so that when core restarts, VGC will not try to deactivate the service again
2217 va.ServicesToDelete.Delete(serviceName)
Naveen Sampath04696f72022-06-13 15:19:14 +05302218 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302219 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302220 }
2221 }
2222 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302223 logger.Warnw(ctx, "Pending Service Not found during Delete", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302224 }
Akash Sonief452f12024-12-12 18:20:28 +05302225 return true
2226 })
Naveen Sampath04696f72022-06-13 15:19:14 +05302227}
2228
vinokuma926cb3e2023-03-29 11:41:06 +05302229// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302230func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302231 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302232 for vpv := range va.VoltPortVnetsToDelete {
2233 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302234 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 +05302235 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302236 }
2237 }
2238}
2239
vinokuma926cb3e2023-03-29 11:41:06 +05302240// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302241func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302242 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302243 for vnetName := range va.VnetsToDelete {
2244 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2245 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302246 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302247 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302248 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302249 va.deleteVnetConfig(vnet)
2250 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302251 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302252 }
2253 }
2254 }
2255}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302256
2257type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302258 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302259 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302260 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2261 EnableEapol bool `json:"enableEapol"`
2262 EnableDhcpV6 bool `json:"enableDhcpV6"`
2263 EnableDhcpV4 bool `json:"enableDhcpV4"`
2264 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302265}
2266
2267func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2268 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2269 va.OltFlowServiceConfig = oltFlowService
2270 b, err := json.Marshal(va.OltFlowServiceConfig)
2271 if err != nil {
2272 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2273 return
2274 }
2275 _ = db.PutOltFlowService(cntx, string(b))
2276}
Akash Sonia8246972023-01-03 10:37:08 +05302277
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302278// RestoreOltFlowService to read from the DB and restore olt flow service config
2279func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2280 oltflowService, err := db.GetOltFlowService(cntx)
2281 if err != nil {
2282 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2283 return
2284 }
2285 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2286 if err != nil {
2287 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2288 return
2289 }
2290 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2291}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302292
Akash Soni87a19072023-02-28 00:46:59 +05302293func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302294 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302295 var dc *DeviceConfig
2296 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2297 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2298 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302299 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302300 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302301 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302302 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302303 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302304 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302305 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302306 va.DevicesDisc.Store(id, device)
2307 }
2308}