blob: 7c61725b1d6ea2159332fd3f49a0ada1dba88cfe [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
212 IgmpDsFlowAppliedForMvlan map[uint16]bool
213 State controller.DeviceState
214 SouthBoundID string
215 NniPort string
216 Name string
217 SerialNum string
218 Ports sync.Map
219 VlanPortStatus sync.Map
220 ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
221 PonPortList sync.Map // [PonPortID]map[string]string
222 ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530223 NniDhcpTrapVid of.VlanType
vinokuma926cb3e2023-03-29 11:41:06 +0530224 GlobalDhcpFlowAdded bool
225 icmpv6GroupAdded bool
Akash Soni6f369452023-09-19 11:18:28 +0530226}
227
228type VoltDevInterface interface {
229 GetPortNameFromPortID(portID uint32) string
Naveen Sampath04696f72022-06-13 15:19:14 +0530230}
231
232// NewVoltDevice : Constructor for the device
233func NewVoltDevice(name string, slno, southBoundID string) *VoltDevice {
234 var d VoltDevice
235 d.Name = name
236 d.SouthBoundID = southBoundID
237 d.State = controller.DeviceStateDOWN
238 d.NniPort = ""
239 d.SouthBoundID = southBoundID
240 d.SerialNum = slno
241 d.icmpv6GroupAdded = false
242 d.IgmpDsFlowAppliedForMvlan = make(map[uint16]bool)
243 d.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
244 d.MigratingServices = util.NewConcurrentMap()
245 d.VpvsBySvlan = util.NewConcurrentMap()
246 d.FlowAddEventMap = util.NewConcurrentMap()
247 d.FlowDelEventMap = util.NewConcurrentMap()
248 d.GlobalDhcpFlowAdded = false
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530249 if config, ok := GetApplication().DevicesConfig.Load(slno); ok {
250 //Update nni dhcp vid
Akash Soni53da2852023-03-15 00:31:31 +0530251 deviceConfig := config.(*DeviceConfig)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530252 d.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
253 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530254 return &d
255}
256
vinokuma926cb3e2023-03-29 11:41:06 +0530257// GetAssociatedVpvsForDevice - return the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530258func (va *VoltApplication) GetAssociatedVpvsForDevice(device string, svlan of.VlanType) *util.ConcurrentMap {
259 if d := va.GetDevice(device); d != nil {
260 return d.GetAssociatedVpvs(svlan)
261 }
262 return nil
263}
264
vinokuma926cb3e2023-03-29 11:41:06 +0530265// AssociateVpvsToDevice - updates the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530266func (va *VoltApplication) AssociateVpvsToDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530267 logger.Debugw(ctx, "AssociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530268 if d := va.GetDevice(device); d != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530269 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
270 vpvMap.Set(vpv, true)
271 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530272 logger.Debugw(ctx, "VPVMap: SET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530273 return
274 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530275 logger.Warnw(ctx, "Set VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530276}
277
vinokuma926cb3e2023-03-29 11:41:06 +0530278// DisassociateVpvsFromDevice - disassociated VPVs from given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530279func (va *VoltApplication) DisassociateVpvsFromDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530280 logger.Debugw(ctx, "DisassociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530281 if d := va.GetDevice(device); d != nil {
282 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
283 vpvMap.Remove(vpv)
284 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530285 logger.Debugw(ctx, "VPVMap: Remove", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530286 return
287 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530288 logger.Warnw(ctx, "Remove VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530289}
290
vinokuma926cb3e2023-03-29 11:41:06 +0530291// GetAssociatedVpvs - returns the associated VPVs for the given Svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530292func (d *VoltDevice) GetAssociatedVpvs(svlan of.VlanType) *util.ConcurrentMap {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530293 logger.Debugw(ctx, "Received Get Associated Vpvs", log.Fields{"svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530294 var vpvMap *util.ConcurrentMap
295 var mapIntf interface{}
296 var ok bool
297
298 if mapIntf, ok = d.VpvsBySvlan.Get(svlan); ok {
299 vpvMap = mapIntf.(*util.ConcurrentMap)
300 } else {
301 vpvMap = util.NewConcurrentMap()
302 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530303 logger.Debugw(ctx, "VPVMap: GET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530304 return vpvMap
305}
306
307// AddPort add port to the device.
308func (d *VoltDevice) AddPort(port string, id uint32) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530309 logger.Debugw(ctx, "Add Port", log.Fields{"Port": port, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530310 addPonPortFromUniPort := func(vPort *VoltPort) {
311 if vPort.Type == VoltPortTypeAccess {
312 ponPortID := GetPonPortIDFromUNIPort(vPort.ID)
313
314 if ponPortUniList, ok := d.PonPortList.Load(ponPortID); !ok {
315 uniList := make(map[string]uint32)
316 uniList[port] = vPort.ID
317 d.PonPortList.Store(ponPortID, uniList)
318 } else {
319 ponPortUniList.(map[string]uint32)[port] = vPort.ID
320 d.PonPortList.Store(ponPortID, ponPortUniList)
321 }
322 }
323 }
324 va := GetApplication()
325 if pIntf, ok := d.Ports.Load(port); ok {
326 voltPort := pIntf.(*VoltPort)
327 addPonPortFromUniPort(voltPort)
328 va.AggActiveChannelsCountPerSub(d.Name, port, voltPort)
329 d.Ports.Store(port, voltPort)
330 return voltPort
331 }
332 p := NewVoltPort(d.Name, port, id)
333 va.AggActiveChannelsCountPerSub(d.Name, port, p)
334 d.Ports.Store(port, p)
335 if util.IsNniPort(id) {
336 d.NniPort = port
337 }
338 addPonPortFromUniPort(p)
339 return p
340}
341
342// GetPort to get port information from the device.
343func (d *VoltDevice) GetPort(port string) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530344 logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530345 if pIntf, ok := d.Ports.Load(port); ok {
346 return pIntf.(*VoltPort)
347 }
348 return nil
349}
350
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530351// GetPortByPortID to get port information from the device.
352func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530353 logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530354 portName := ""
355 d.Ports.Range(func(key, value interface{}) bool {
356 vp := value.(*VoltPort)
357 if vp.ID == portID {
358 portName = vp.Name
359 }
360 return true
361 })
362 return portName
363}
364
Naveen Sampath04696f72022-06-13 15:19:14 +0530365// DelPort to delete port from the device
366func (d *VoltDevice) DelPort(port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530367 logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530368 if _, ok := d.Ports.Load(port); ok {
369 d.Ports.Delete(port)
370 } else {
371 logger.Warnw(ctx, "Port doesn't exist", log.Fields{"Device": d.Name, "Port": port})
372 }
373}
374
375// pushFlowsForUnis to send port-up-indication for uni ports.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530376func (d *VoltDevice) pushFlowsForUnis(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530377 logger.Info(ctx, "NNI Discovered, Sending Port UP Ind for UNIs")
378 d.Ports.Range(func(key, value interface{}) bool {
379 port := key.(string)
380 vp := value.(*VoltPort)
381
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530382 logger.Debugw(ctx, "NNI Discovered. Sending Port UP Ind for UNI", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530383 //Ignore if UNI port is not UP
384 if vp.State != PortStateUp {
385 return true
386 }
387
388 //Obtain all VPVs associated with the port
389 vnets, ok := GetApplication().VnetsByPort.Load(port)
390 if !ok {
391 return true
392 }
393
394 for _, vpv := range vnets.([]*VoltPortVnet) {
395 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530396 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530397 vpv.VpvLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +0530398 }
399 return true
400 })
401}
402
403// ----------------------------------------------------------
404// VOLT Application - hosts all other objects
405// ----------------------------------------------------------
406//
407// The VOLT application is a singleton implementation where
408// there is just one instance in the system and is the gateway
409// to all other components within the controller
410// The declaration of the singleton object
411var vapplication *VoltApplication
412
Akash Soni6f369452023-09-19 11:18:28 +0530413type VoltAppInterface interface {
414 AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
415 AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
416 AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error
417 GetFlowProvisionStatus(portNo string) FlowProvisionStatus
418 DelServiceWithPrefix(cntx context.Context, prefix string) error
419 GetDevice(device string) *VoltDevice
420 GetTaskList(device string) map[int]*TaskInfo
421 AddMeterProf(cntx context.Context, cfg VoltMeter)
422 AddMvlanProfile(cntx context.Context, name string, mvlan of.VlanType, ponVlan of.VlanType, groups map[string][]string, isChannelBasedGroup bool, OLTSerialNum []string, activeChannelsPerPon int, proxy map[string]common.MulticastGroupProxy) error
423 DelMvlanProfile(cntx context.Context, name string) error
424 GetMvlanProfileByTag(vlan of.VlanType) *MvlanProfile
425 AddMcastConfig(cntx context.Context, MvlanProfileID string, IgmpProfileID string, IgmpProxyIP string, OltSerialNum string) error
426 DelMeterProf(cntx context.Context, name string) error
427 GetMeterByName(name string) (*VoltMeter, bool)
428 UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig)
429 GetDeviceConfig(serNum string) *DeviceConfig
430 GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error)
431 GetAllMacLearnerInfo() ([]MacLearnerInfo, error)
432 GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error)
433 ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
434 DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
435 GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error)
436 UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService)
437 GetIgnoredPorts() (map[string][]string, error)
438}
439
Naveen Sampath04696f72022-06-13 15:19:14 +0530440// VoltApplication fields :
441// ServiceByName - Stores the services by the name as key
vinokuma926cb3e2023-03-29 11:41:06 +0530442// A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530443// VnetsByPort - Stores the VNETs by the ports configured
vinokuma926cb3e2023-03-29 11:41:06 +0530444// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530445// VnetsByTag - Stores the VNETs by the VLANS configured
vinokuma926cb3e2023-03-29 11:41:06 +0530446// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530447// VnetsByName - Stores the VNETs by the name configured
vinokuma926cb3e2023-03-29 11:41:06 +0530448// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530449// DevicesDisc - Stores the devices discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530450// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530451// PortsDisc - Stores the ports discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530452// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530453type VoltApplication struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530454 MeterMgr
vinokuma926cb3e2023-03-29 11:41:06 +0530455 DataMigrationInfo DataMigration
456 VnetsBySvlan *util.ConcurrentMap
457 IgmpGroupIds []*IgmpGroup
458 VoltPortVnetsToDelete map[*VoltPortVnet]bool
Akash Sonia8246972023-01-03 10:37:08 +0530459 IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
vinokuma926cb3e2023-03-29 11:41:06 +0530460 macPortMap map[string]string
Akash Sonia8246972023-01-03 10:37:08 +0530461 VnetsToDelete map[string]bool
Akash Sonief452f12024-12-12 18:20:28 +0530462 ServicesToDelete sync.Map
463 ServicesToDeactivate sync.Map
Akash Sonia8246972023-01-03 10:37:08 +0530464 PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
465 vendorID string
vinokuma926cb3e2023-03-29 11:41:06 +0530466 ServiceByName sync.Map // [serName]*VoltService
467 VnetsByPort sync.Map // [portName][]*VoltPortVnet
468 VnetsByTag sync.Map // [svlan-cvlan-uvlan]*VoltVnet
469 VnetsByName sync.Map // [vnetName]*VoltVnet
470 DevicesDisc sync.Map
471 PortsDisc sync.Map
472 IgmpGroups sync.Map // [grpKey]*IgmpGroup
473 MvlanProfilesByTag sync.Map
474 MvlanProfilesByName sync.Map
475 Icmpv6Receivers sync.Map
476 DeviceCounters sync.Map //[logicalDeviceId]*DeviceCounters
477 ServiceCounters sync.Map //[serviceName]*ServiceCounters
478 NbDevice sync.Map // [OLTSouthBoundID]*NbDevice
479 OltIgmpInfoBySerial sync.Map
480 McastConfigMap sync.Map //[OltSerialNo_MvlanProfileID]*McastConfig
Akash Sonia8246972023-01-03 10:37:08 +0530481 DevicesConfig sync.Map //[serialNumber]*DeviceConfig
vinokuma926cb3e2023-03-29 11:41:06 +0530482 IgmpProfilesByName sync.Map
483 IgmpTasks tasks.Tasks
484 IndicationsTasks tasks.Tasks
485 MulticastAlarmTasks tasks.Tasks
486 IgmpKPIsTasks tasks.Tasks
487 pppoeTasks tasks.Tasks
488 OltFlowServiceConfig OltFlowService
489 PendingPoolLock sync.RWMutex
490 // MacAddress-Port MAP to avoid swap of mac across ports.
491 macPortLock sync.RWMutex
492 portLock sync.Mutex
Akash Sonia8246972023-01-03 10:37:08 +0530493}
Naveen Sampath04696f72022-06-13 15:19:14 +0530494
Akash Sonia8246972023-01-03 10:37:08 +0530495type DeviceConfig struct {
496 SerialNumber string `json:"id"`
497 HardwareIdentifier string `json:"hardwareIdentifier"`
Akash Soni87a19072023-02-28 00:46:59 +0530498 IPAddress string `json:"ipAddress"`
Akash Soni53da2852023-03-15 00:31:31 +0530499 UplinkPort string `json:"uplinkPort"`
Akash Sonia8246972023-01-03 10:37:08 +0530500 NasID string `json:"nasId"`
501 NniDhcpTrapVid int `json:"nniDhcpTrapVid"`
Naveen Sampath04696f72022-06-13 15:19:14 +0530502}
503
504// PonPortCfg contains NB port config and activeIGMPChannels count
505type PonPortCfg struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530506 PortAlarmProfileID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530507 PortID uint32
508 MaxActiveChannels uint32
509 ActiveIGMPChannels uint32
510 EnableMulticastKPI bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530511}
512
513// NbDevice OLT Device info
514type NbDevice struct {
515 SouthBoundID string
516 PonPorts sync.Map // [PortID]*PonPortCfg
517}
518
519// RestoreNbDeviceFromDb restores the NB Device in case of VGC pod restart.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530520func (va *VoltApplication) RestoreNbDeviceFromDb(cntx context.Context, deviceID string) *NbDevice {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530521 logger.Debugw(ctx, "Received Restore Nb Device From Db", log.Fields{"deviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530522 nbDevice := NewNbDevice()
523 nbDevice.SouthBoundID = deviceID
524
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530525 nbPorts, _ := db.GetAllNbPorts(cntx, deviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530526
527 for key, p := range nbPorts {
528 b, ok := p.Value.([]byte)
529 if !ok {
530 logger.Warn(ctx, "The value type is not []byte")
531 continue
532 }
533 var port PonPortCfg
534 err := json.Unmarshal(b, &port)
535 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530536 logger.Warnw(ctx, "Unmarshal of PonPortCfg failed", log.Fields{"deviceID": deviceID, "port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530537 continue
538 }
539 logger.Debugw(ctx, "Port recovered", log.Fields{"port": port})
540 ponPortID, _ := strconv.Atoi(key)
541 nbDevice.PonPorts.Store(uint32(ponPortID), &port)
542 }
543 va.NbDevice.Store(deviceID, nbDevice)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530544 logger.Debugw(ctx, "Recovered NbDevice From Db", log.Fields{"deviceID": deviceID, "nbDevice": nbDevice})
Naveen Sampath04696f72022-06-13 15:19:14 +0530545 return nbDevice
546}
547
548// NewNbDevice Constructor for NbDevice
549func NewNbDevice() *NbDevice {
550 var nbDevice NbDevice
551 return &nbDevice
552}
553
554// WriteToDb writes nb device port config to kv store
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530555func (nbd *NbDevice) WriteToDb(cntx context.Context, portID uint32, ponPort *PonPortCfg) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530556 b, err := json.Marshal(ponPort)
557 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530558 logger.Errorw(ctx, "PonPortConfig-marshal-failed", log.Fields{"err": err, "ponPort": ponPort})
Naveen Sampath04696f72022-06-13 15:19:14 +0530559 return
560 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530561 db.PutNbDevicePort(cntx, nbd.SouthBoundID, portID, string(b))
Naveen Sampath04696f72022-06-13 15:19:14 +0530562}
563
564// AddPortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530565func (nbd *NbDevice) AddPortToNbDevice(cntx context.Context, portID, allowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +0530566 enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530567 logger.Debugw(ctx, "AddPortToNbDevice", log.Fields{"PortID": portID, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530568 ponPort := &PonPortCfg{
569 PortID: portID,
570 MaxActiveChannels: allowedChannels,
571 EnableMulticastKPI: enableMulticastKPI,
572 PortAlarmProfileID: portAlarmProfileID,
573 }
574 nbd.PonPorts.Store(portID, ponPort)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530575 nbd.WriteToDb(cntx, portID, ponPort)
Naveen Sampath04696f72022-06-13 15:19:14 +0530576 return ponPort
577}
578
Akash Sonia8246972023-01-03 10:37:08 +0530579// RestoreDeviceConfigFromDb to restore vnet from port
580func (va *VoltApplication) RestoreDeviceConfigFromDb(cntx context.Context) {
581 // VNETS must be learnt first
582 dConfig, _ := db.GetDeviceConfig(cntx)
583 for _, device := range dConfig {
584 b, ok := device.Value.([]byte)
585 if !ok {
586 logger.Warn(ctx, "The value type is not []byte")
587 continue
588 }
589 devConfig := DeviceConfig{}
590 err := json.Unmarshal(b, &devConfig)
591 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530592 logger.Warnw(ctx, "Unmarshal of device configuration failed", log.Fields{"Device Config": devConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530593 continue
594 }
595 logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
596 if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid); err != nil {
597 logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
598 }
Akash Sonia8246972023-01-03 10:37:08 +0530599 }
600}
601
602// WriteDeviceConfigToDb writes sb device config to kv store
603func (dc *DeviceConfig) WriteDeviceConfigToDb(cntx context.Context, serialNum string, deviceConfig *DeviceConfig) error {
604 b, err := json.Marshal(deviceConfig)
605 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530606 return fmt.Errorf("deviceConfig-marshal-failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530607 }
608 dberr := db.PutDeviceConfig(cntx, serialNum, string(b))
609 if dberr != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530610 return fmt.Errorf("update device config failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530611 }
612 return nil
613}
614
vinokuma926cb3e2023-03-29 11:41:06 +0530615func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530616 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 +0530617 var dc *DeviceConfig
618
Akash Soni87a19072023-02-28 00:46:59 +0530619 deviceConfig := &DeviceConfig{
620 SerialNumber: serialNum,
621 HardwareIdentifier: hardwareIdentifier,
622 NasID: nasID,
623 UplinkPort: uplinkPort,
624 IPAddress: ipAddress,
vinokuma926cb3e2023-03-29 11:41:06 +0530625 NniDhcpTrapVid: nniDhcpTrapID,
Akash Sonia8246972023-01-03 10:37:08 +0530626 }
Akash Soni87a19072023-02-28 00:46:59 +0530627 va.DevicesConfig.Store(serialNum, deviceConfig)
628 err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
629 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530630 return fmt.Errorf("DB update for device config failed - %w ", err)
Akash Soni87a19072023-02-28 00:46:59 +0530631 }
632
633 // If device is already discovered update the VoltDevice structure
634 device, id := va.GetDeviceBySerialNo(serialNum)
635 if device != nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530636 device.NniDhcpTrapVid = of.VlanType(nniDhcpTrapID)
Akash Soni87a19072023-02-28 00:46:59 +0530637 va.DevicesDisc.Store(id, device)
638 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530639 logger.Debugw(ctx, "Added device config", log.Fields{"Device Config": deviceConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530640 return nil
641}
642
643// GetDeviceConfig to get a device config.
644func (va *VoltApplication) GetDeviceConfig(serNum string) *DeviceConfig {
645 if d, ok := va.DevicesConfig.Load(serNum); ok {
646 return d.(*DeviceConfig)
647 }
648 return nil
649}
650
Naveen Sampath04696f72022-06-13 15:19:14 +0530651// UpdatePortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530652func (nbd *NbDevice) UpdatePortToNbDevice(cntx context.Context, portID, allowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530653 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 +0530654 p, exists := nbd.PonPorts.Load(portID)
655 if !exists {
656 logger.Errorw(ctx, "PON port not exists in nb-device", log.Fields{"portID": portID})
657 return nil
658 }
659 port := p.(*PonPortCfg)
660 if allowedChannels != 0 {
661 port.MaxActiveChannels = allowedChannels
662 port.EnableMulticastKPI = enableMulticastKPI
663 port.PortAlarmProfileID = portAlarmProfileID
664 }
665
666 nbd.PonPorts.Store(portID, port)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530667 nbd.WriteToDb(cntx, portID, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530668 return port
669}
670
671// DeletePortFromNbDevice Deletes pon port from NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530672func (nbd *NbDevice) DeletePortFromNbDevice(cntx context.Context, portID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530673 logger.Debugw(ctx, "Received Delete Port from NbDevice", log.Fields{"portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530674 if _, ok := nbd.PonPorts.Load(portID); ok {
675 nbd.PonPorts.Delete(portID)
676 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530677 db.DelNbDevicePort(cntx, nbd.SouthBoundID, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530678}
679
680// GetApplication : Interface to access the singleton object
681func GetApplication() *VoltApplication {
682 if vapplication == nil {
683 vapplication = newVoltApplication()
684 }
685 return vapplication
686}
687
688// newVoltApplication : Constructor for the singleton object. Hence this is not
689// an exported function
690func newVoltApplication() *VoltApplication {
691 var va VoltApplication
692 va.IgmpTasks.Initialize(context.TODO())
693 va.MulticastAlarmTasks.Initialize(context.TODO())
694 va.IgmpKPIsTasks.Initialize(context.TODO())
695 va.pppoeTasks.Initialize(context.TODO())
696 va.storeIgmpProfileMap(DefaultIgmpProfID, newDefaultIgmpProfile())
697 va.MeterMgr.Init()
698 va.AddIgmpGroups(5000)
699 va.macPortMap = make(map[string]string)
700 va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
701 va.VnetsBySvlan = util.NewConcurrentMap()
702 va.VnetsToDelete = make(map[string]bool)
Naveen Sampath04696f72022-06-13 15:19:14 +0530703 va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530704 go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
705 go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
Naveen Sampath04696f72022-06-13 15:19:14 +0530706 InitEventFuncMapper()
707 db = database.GetDatabase()
Akash Soni6f369452023-09-19 11:18:28 +0530708
Naveen Sampath04696f72022-06-13 15:19:14 +0530709 return &va
710}
711
vinokuma926cb3e2023-03-29 11:41:06 +0530712// GetFlowEventRegister - returs the register based on flow mod type
Naveen Sampath04696f72022-06-13 15:19:14 +0530713func (d *VoltDevice) GetFlowEventRegister(flowModType of.Command) (*util.ConcurrentMap, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530714 switch flowModType {
715 case of.CommandDel:
716 return d.FlowDelEventMap, nil
717 case of.CommandAdd:
718 return d.FlowAddEventMap, nil
719 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530720 logger.Warnw(ctx, "Unknown Flow Mod received", log.Fields{"flowModtype": flowModType})
Naveen Sampath04696f72022-06-13 15:19:14 +0530721 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530722 return util.NewConcurrentMap(), errors.New("unknown flow mod")
Naveen Sampath04696f72022-06-13 15:19:14 +0530723}
724
725// RegisterFlowAddEvent to register a flow event.
726func (d *VoltDevice) RegisterFlowAddEvent(cookie string, event *FlowEvent) {
727 logger.Debugw(ctx, "Registered Flow Add Event", log.Fields{"Cookie": cookie, "Event": event})
728 d.FlowAddEventMap.MapLock.Lock()
729 defer d.FlowAddEventMap.MapLock.Unlock()
730 d.FlowAddEventMap.Set(cookie, event)
731}
732
733// RegisterFlowDelEvent to register a flow event.
734func (d *VoltDevice) RegisterFlowDelEvent(cookie string, event *FlowEvent) {
735 logger.Debugw(ctx, "Registered Flow Del Event", log.Fields{"Cookie": cookie, "Event": event})
736 d.FlowDelEventMap.MapLock.Lock()
737 defer d.FlowDelEventMap.MapLock.Unlock()
738 d.FlowDelEventMap.Set(cookie, event)
739}
740
741// UnRegisterFlowEvent to unregister a flow event.
742func (d *VoltDevice) UnRegisterFlowEvent(cookie string, flowModType of.Command) {
743 logger.Debugw(ctx, "UnRegistered Flow Add Event", log.Fields{"Cookie": cookie, "Type": flowModType})
744 flowEventMap, err := d.GetFlowEventRegister(flowModType)
745 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530746 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowModType, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530747 return
748 }
749 flowEventMap.MapLock.Lock()
750 defer flowEventMap.MapLock.Unlock()
751 flowEventMap.Remove(cookie)
752}
753
754// AddIgmpGroups to add Igmp groups.
755func (va *VoltApplication) AddIgmpGroups(numOfGroups uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530756 logger.Debugw(ctx, "AddIgmpGroups", log.Fields{"NumOfGroups": numOfGroups})
Naveen Sampath04696f72022-06-13 15:19:14 +0530757 //TODO: Temp change to resolve group id issue in pOLT
758 //for i := 1; uint32(i) <= numOfGroups; i++ {
759 for i := 2; uint32(i) <= (numOfGroups + 1); i++ {
760 ig := IgmpGroup{}
761 ig.GroupID = uint32(i)
762 va.IgmpGroupIds = append(va.IgmpGroupIds, &ig)
763 }
764}
765
766// GetAvailIgmpGroupID to get id of available igmp group.
767func (va *VoltApplication) GetAvailIgmpGroupID() *IgmpGroup {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530768 logger.Info(ctx, "GetAvailIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530769 var ig *IgmpGroup
770 if len(va.IgmpGroupIds) > 0 {
771 ig, va.IgmpGroupIds = va.IgmpGroupIds[0], va.IgmpGroupIds[1:]
772 return ig
773 }
774 return nil
775}
776
777// GetIgmpGroupID to get id of igmp group.
778func (va *VoltApplication) GetIgmpGroupID(gid uint32) (*IgmpGroup, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530779 logger.Info(ctx, "GetIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530780 for id, ig := range va.IgmpGroupIds {
781 if ig.GroupID == gid {
782 va.IgmpGroupIds = append(va.IgmpGroupIds[0:id], va.IgmpGroupIds[id+1:]...)
783 return ig, nil
784 }
785 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530786 return nil, errors.New("group id missing")
Naveen Sampath04696f72022-06-13 15:19:14 +0530787}
788
789// PutIgmpGroupID to add id of igmp group.
790func (va *VoltApplication) PutIgmpGroupID(ig *IgmpGroup) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530791 logger.Debugw(ctx, "GetIgmpGroupID", log.Fields{"GroupID": ig.GroupID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530792 va.IgmpGroupIds = append([]*IgmpGroup{ig}, va.IgmpGroupIds[0:]...)
793}
794
vinokuma926cb3e2023-03-29 11:41:06 +0530795// RestoreUpgradeStatus - gets upgrade/migration status from DB and updates local flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530796func (va *VoltApplication) RestoreUpgradeStatus(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530797 logger.Info(ctx, "Received Restore Upgrade Status")
Naveen Sampath04696f72022-06-13 15:19:14 +0530798 Migrate := new(DataMigration)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530799 if err := GetMigrationInfo(cntx, Migrate); err == nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530800 if Migrate.Status == MigrationInProgress {
801 isUpgradeComplete = false
802 return
803 }
804 }
805 isUpgradeComplete = true
806
807 logger.Infow(ctx, "Upgrade Status Restored", log.Fields{"Upgrade Completed": isUpgradeComplete})
808}
809
810// ReadAllFromDb : If we are restarted, learn from the database the current execution
811// stage
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530812func (va *VoltApplication) ReadAllFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530813 logger.Info(ctx, "Reading the meters from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530814 va.RestoreMetersFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530815 logger.Info(ctx, "Reading the VNETs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530816 va.RestoreVnetsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530817 logger.Info(ctx, "Reading the VPVs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530818 va.RestoreVpvsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530819 logger.Info(ctx, "Reading the Services from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530820 va.RestoreSvcsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530821 logger.Info(ctx, "Reading the MVLANs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530822 va.RestoreMvlansFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530823 logger.Info(ctx, "Reading the IGMP profiles from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530824 va.RestoreIGMPProfilesFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530825 logger.Info(ctx, "Reading the Mcast configs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826 va.RestoreMcastConfigsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530827 logger.Info(ctx, "Reading the IGMP groups for DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530828 va.RestoreIgmpGroupsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530829 logger.Info(ctx, "Reading Upgrade status from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530830 va.RestoreUpgradeStatus(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530831 logger.Info(ctx, "Reading OltFlowService from DB")
832 va.RestoreOltFlowService(cntx)
Akash Sonia8246972023-01-03 10:37:08 +0530833 logger.Info(ctx, "Reading device config from DB")
834 va.RestoreDeviceConfigFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530835 logger.Info(ctx, "Reconciled from DB")
836}
837
vinokuma926cb3e2023-03-29 11:41:06 +0530838// InitStaticConfig to initialize static config.
Naveen Sampath04696f72022-06-13 15:19:14 +0530839func (va *VoltApplication) InitStaticConfig() {
840 va.InitIgmpSrcMac()
841}
842
843// SetVendorID to set vendor id
844func (va *VoltApplication) SetVendorID(vendorID string) {
845 va.vendorID = vendorID
846}
847
848// GetVendorID to get vendor id
849func (va *VoltApplication) GetVendorID() string {
850 return va.vendorID
851}
852
853// SetRebootFlag to set reboot flag
854func (va *VoltApplication) SetRebootFlag(flag bool) {
855 vgcRebooted = flag
856}
857
858// GetUpgradeFlag to get reboot status
859func (va *VoltApplication) GetUpgradeFlag() bool {
860 return isUpgradeComplete
861}
862
863// SetUpgradeFlag to set reboot status
864func (va *VoltApplication) SetUpgradeFlag(flag bool) {
865 isUpgradeComplete = flag
866}
867
868// ------------------------------------------------------------
869// Device related functions
870
871// AddDevice : Add a device and typically the device stores the NNI port on the device
872// The NNI port is used when the packets are emitted towards the network.
873// The outport is selected as the NNI port of the device. Today, we support
874// a single NNI port per OLT. This is true whether the network uses any
875// protection mechanism (LAG, ERPS, etc.). The aggregate of the such protection
876// is represented by a single NNI port
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530877func (va *VoltApplication) AddDevice(cntx context.Context, device string, slno, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530878 logger.Debugw(ctx, "Received Device Ind: Add", log.Fields{"Device": device, "SrNo": slno, "southBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530879 if _, ok := va.DevicesDisc.Load(device); ok {
880 logger.Warnw(ctx, "Device Exists", log.Fields{"Device": device})
881 }
882 d := NewVoltDevice(device, slno, southBoundID)
883
884 addPort := func(key, value interface{}) bool {
885 portID := key.(uint32)
886 port := value.(*PonPortCfg)
887 va.AggActiveChannelsCountForPonPort(device, portID, port)
888 d.ActiveChannelsPerPon.Store(portID, port)
889 return true
890 }
891 if nbDevice, exists := va.NbDevice.Load(southBoundID); exists {
892 // Pon Ports added before OLT activate.
893 nbDevice.(*NbDevice).PonPorts.Range(addPort)
894 } else {
895 // Check if NbPort exists in DB. VGC restart case.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530896 nbd := va.RestoreNbDeviceFromDb(cntx, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530897 nbd.PonPorts.Range(addPort)
898 }
899 va.DevicesDisc.Store(device, d)
900}
901
902// GetDevice to get a device.
903func (va *VoltApplication) GetDevice(device string) *VoltDevice {
904 if d, ok := va.DevicesDisc.Load(device); ok {
905 return d.(*VoltDevice)
906 }
907 return nil
908}
909
910// DelDevice to delete a device.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530911func (va *VoltApplication) DelDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530912 logger.Debugw(ctx, "Received Device Ind: Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530913 if vdIntf, ok := va.DevicesDisc.Load(device); ok {
914 vd := vdIntf.(*VoltDevice)
915 va.DevicesDisc.Delete(device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530916 _ = db.DelAllRoutesForDevice(cntx, device)
917 va.HandleFlowClearFlag(cntx, device, vd.SerialNum, vd.SouthBoundID)
918 _ = db.DelAllGroup(cntx, device)
919 _ = db.DelAllMeter(cntx, device)
920 _ = db.DelAllPorts(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530921 logger.Debugw(ctx, "Device deleted", log.Fields{"Device": device})
922 } else {
923 logger.Warnw(ctx, "Device Doesn't Exist", log.Fields{"Device": device})
924 }
925}
926
Akash Sonief452f12024-12-12 18:20:28 +0530927// CheckServiceExists to check if service exists for the given uniport and tech profile ID.
928func (va *VoltApplication) CheckServiceExists(port string, techProfID uint16) bool {
929 var serviceExists bool
930 va.ServiceByName.Range(func(key, existingServiceIntf interface{}) bool {
931 existingService := existingServiceIntf.(*VoltService)
932 if existingService.Port == port && existingService.TechProfileID == techProfID {
933 logger.Warnw(ctx, "Service already exists for same Port and TP. Ignoring add service request", log.Fields{"ExistingService": existingService.Name})
934 serviceExists = true
935 return false
936 }
937 return true
938 })
939 return serviceExists
940}
941
Naveen Sampath04696f72022-06-13 15:19:14 +0530942// GetDeviceBySerialNo to get a device by serial number.
943// TODO - Transform this into a MAP instead
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530944func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530945 logger.Debugw(ctx, "Received Device Ind: Get", log.Fields{"Serial Num": slno})
Naveen Sampath04696f72022-06-13 15:19:14 +0530946 var device *VoltDevice
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530947 var deviceID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530948 getserial := func(key interface{}, value interface{}) bool {
949 device = value.(*VoltDevice)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530950 deviceID = key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +0530951 return device.SerialNum != slno
952 }
953 va.DevicesDisc.Range(getserial)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530954 return device, deviceID
Naveen Sampath04696f72022-06-13 15:19:14 +0530955}
956
957// PortAddInd : This is a PORT add indication coming from the VPAgent, which is essentially
958// a request coming from VOLTHA. The device and identity of the port is provided
959// in this request. Add them to the application for further use
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530960func (va *VoltApplication) PortAddInd(cntx context.Context, device string, id uint32, portName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530961 logger.Debugw(ctx, "Received Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530962 va.portLock.Lock()
963 if d := va.GetDevice(device); d != nil {
964 p := d.AddPort(portName, id)
965 va.PortsDisc.Store(portName, p)
966 va.portLock.Unlock()
967 nni, _ := va.GetNniPort(device)
968 if nni == portName {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530969 d.pushFlowsForUnis(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530970 }
971 } else {
972 va.portLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530973 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 +0530974 }
975}
976
977// PortDelInd : Only the NNI ports are recorded in the device for now. When port delete
978// arrives, only the NNI ports need adjustments.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530979func (va *VoltApplication) PortDelInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530980 logger.Debugw(ctx, "Received Port Ind: Delete", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530981 if d := va.GetDevice(device); d != nil {
982 p := d.GetPort(port)
983 if p != nil && p.State == PortStateUp {
984 logger.Infow(ctx, "Port state is UP. Trigerring Port Down Ind before deleting", log.Fields{"Port": p})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530985 va.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530986 }
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530987 // if RemoveFlowsOnDisable is flase, then flows will be existing till port delete. Remove the flows now
988 if !va.OltFlowServiceConfig.RemoveFlowsOnDisable {
Akash Sonia8246972023-01-03 10:37:08 +0530989 vpvs, ok := va.VnetsByPort.Load(port)
990 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530991 logger.Infow(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
992 } else {
993 for _, vpv := range vpvs.([]*VoltPortVnet) {
994 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530995 // Set delFlowsInDevice to true to delete flows only in DB/device during Port Delete.
996 vpv.PortDownInd(cntx, device, port, true, true)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530997 vpv.VpvLock.Unlock()
998 }
999 }
1000 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301001 va.portLock.Lock()
1002 defer va.portLock.Unlock()
1003 d.DelPort(port)
1004 if _, ok := va.PortsDisc.Load(port); ok {
1005 va.PortsDisc.Delete(port)
1006 }
1007 } else {
1008 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Delete", log.Fields{"Device": device, "Port": port})
1009 }
1010}
1011
vinokuma926cb3e2023-03-29 11:41:06 +05301012// PortUpdateInd Updates port Id incase of ONU movement
Naveen Sampath04696f72022-06-13 15:19:14 +05301013func (va *VoltApplication) PortUpdateInd(device string, portName string, id uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301014 logger.Debugw(ctx, "Received Port Ind: Update", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301015 va.portLock.Lock()
1016 defer va.portLock.Unlock()
1017 if d := va.GetDevice(device); d != nil {
1018 vp := d.GetPort(portName)
1019 vp.ID = id
1020 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301021 logger.Warnw(ctx, "Device Not Found", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301022 }
1023}
1024
1025// AddNbPonPort Add pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301026func (va *VoltApplication) AddNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +05301027 enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301028 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 +05301029 var nbd *NbDevice
1030 nbDevice, ok := va.NbDevice.Load(oltSbID)
1031
1032 if !ok {
1033 nbd = NewNbDevice()
1034 nbd.SouthBoundID = oltSbID
1035 } else {
1036 nbd = nbDevice.(*NbDevice)
1037 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301038 port := nbd.AddPortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301039 logger.Debugw(ctx, "Added Port To NbDevice", log.Fields{"port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301040 // Add this port to voltDevice
1041 addPort := func(key, value interface{}) bool {
1042 voltDevice := value.(*VoltDevice)
1043 if oltSbID == voltDevice.SouthBoundID {
1044 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); !exists {
1045 voltDevice.ActiveChannelsPerPon.Store(portID, port)
1046 }
1047 return false
1048 }
1049 return true
1050 }
1051 va.DevicesDisc.Range(addPort)
1052 va.NbDevice.Store(oltSbID, nbd)
1053
1054 return nil
1055}
1056
1057// UpdateNbPonPort update pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301058func (va *VoltApplication) UpdateNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301059 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 +05301060 var nbd *NbDevice
1061 nbDevice, ok := va.NbDevice.Load(oltSbID)
1062
1063 if !ok {
1064 logger.Errorw(ctx, "Device-doesn't-exists", log.Fields{"deviceID": oltSbID})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301065 return fmt.Errorf("device-doesn't-exists - %s", oltSbID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301066 }
1067 nbd = nbDevice.(*NbDevice)
1068
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301069 port := nbd.UpdatePortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301070 if port == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301071 return fmt.Errorf("port-doesn't-exists-%d", portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301072 }
1073 va.NbDevice.Store(oltSbID, nbd)
1074
1075 // Add this port to voltDevice
1076 updPort := func(key, value interface{}) bool {
1077 voltDevice := value.(*VoltDevice)
1078 if oltSbID == voltDevice.SouthBoundID {
1079 voltDevice.ActiveChannelCountLock.Lock()
1080 if p, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1081 oldPort := p.(*PonPortCfg)
1082 if port.MaxActiveChannels != 0 {
1083 oldPort.MaxActiveChannels = port.MaxActiveChannels
1084 oldPort.EnableMulticastKPI = port.EnableMulticastKPI
1085 voltDevice.ActiveChannelsPerPon.Store(portID, oldPort)
1086 }
1087 }
1088 voltDevice.ActiveChannelCountLock.Unlock()
1089 return false
1090 }
1091 return true
1092 }
1093 va.DevicesDisc.Range(updPort)
1094
1095 return nil
1096}
1097
1098// DeleteNbPonPort Delete pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301099func (va *VoltApplication) DeleteNbPonPort(cntx context.Context, oltSbID string, portID uint32) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301100 logger.Debugw(ctx, "Received NbPonPort Ind: Delete", log.Fields{"oltSbID": oltSbID, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301101 nbDevice, ok := va.NbDevice.Load(oltSbID)
1102 if ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301103 nbDevice.(*NbDevice).DeletePortFromNbDevice(cntx, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301104 va.NbDevice.Store(oltSbID, nbDevice.(*NbDevice))
1105 } else {
1106 logger.Warnw(ctx, "Delete pon received for unknown device", log.Fields{"oltSbID": oltSbID})
1107 return nil
1108 }
1109 // Delete this port from voltDevice
1110 delPort := func(key, value interface{}) bool {
1111 voltDevice := value.(*VoltDevice)
1112 if oltSbID == voltDevice.SouthBoundID {
1113 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1114 voltDevice.ActiveChannelsPerPon.Delete(portID)
1115 }
1116 return false
1117 }
1118 return true
1119 }
1120 va.DevicesDisc.Range(delPort)
1121 return nil
1122}
1123
1124// GetNniPort : Get the NNI port for a device. Called from different other applications
1125// as a port to match or destination for a packet out. The VOLT application
1126// is written with the assumption that there is a single NNI port. The OLT
1127// device is responsible for translating the combination of VLAN and the
1128// NNI port ID to identify possibly a single physical port or a logical
1129// port which is a result of protection methods applied.
1130func (va *VoltApplication) GetNniPort(device string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301131 logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301132 va.portLock.Lock()
1133 defer va.portLock.Unlock()
1134 d, ok := va.DevicesDisc.Load(device)
1135 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301136 return "", errors.New("device doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301137 }
1138 return d.(*VoltDevice).NniPort, nil
1139}
1140
1141// NniDownInd process for Nni down indication.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301142func (va *VoltApplication) NniDownInd(cntx context.Context, deviceID string, devSrNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301143 logger.Debugw(ctx, "NNI Down Ind", log.Fields{"DeviceID": deviceID, "Device SrNo": devSrNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301144
1145 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1146 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301147 mvProfile.removeIgmpMcastFlows(cntx, devSrNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301148 return true
1149 }
1150 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1151
1152 //Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301153 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301154}
1155
1156// DeviceUpInd changes device state to up.
1157func (va *VoltApplication) DeviceUpInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301158 logger.Infow(ctx, "Received Device Ind: UP", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301159 if d := va.GetDevice(device); d != nil {
1160 d.State = controller.DeviceStateUP
1161 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301162 logger.Warnw(ctx, "Ignoring Device indication: UP. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301163 }
1164}
1165
1166// DeviceDownInd changes device state to down.
1167func (va *VoltApplication) DeviceDownInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301168 logger.Infow(ctx, "Received Device Ind: DOWN", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301169 if d := va.GetDevice(device); d != nil {
1170 d.State = controller.DeviceStateDOWN
1171 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301172 logger.Warnw(ctx, "Ignoring Device indication: DOWN. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301173 }
1174}
1175
1176// DeviceRebootInd process for handling flow clear flag for device reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301177func (va *VoltApplication) DeviceRebootInd(cntx context.Context, device string, serialNum string, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301178 logger.Infow(ctx, "Received Device Ind: Reboot", log.Fields{"Device": device, "SerialNumber": serialNum, "SouthBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301179
1180 if d := va.GetDevice(device); d != nil {
1181 if d.State == controller.DeviceStateREBOOTED {
1182 logger.Warnw(ctx, "Ignoring Device Ind: Reboot, Device already in Reboot state", log.Fields{"Device": device, "SerialNumber": serialNum, "State": d.State})
1183 return
1184 }
1185 d.State = controller.DeviceStateREBOOTED
1186 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301187 va.HandleFlowClearFlag(cntx, device, serialNum, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301188}
1189
1190// DeviceDisableInd handles device deactivation process
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301191func (va *VoltApplication) DeviceDisableInd(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301192 logger.Infow(ctx, "Received Device Ind: Disable", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301193
1194 d := va.GetDevice(device)
1195 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301196 logger.Warnw(ctx, "Ignoring Device indication: DISABLED. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301197 return
1198 }
1199
1200 d.State = controller.DeviceStateDISABLED
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301201 va.HandleFlowClearFlag(cntx, device, d.SerialNum, d.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301202}
1203
1204// ProcessIgmpDSFlowForMvlan for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301205func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301206 logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
1207 portState := false
1208 p := d.GetPort(d.NniPort)
1209 if p != nil && p.State == PortStateUp {
1210 portState = true
1211 }
1212
1213 if addFlow {
1214 if portState {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301215 mvp.pushIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301216 }
1217 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301218 mvp.removeIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301219 }
1220}
1221
1222// ProcessIgmpDSFlowForDevice for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301223func (va *VoltApplication) ProcessIgmpDSFlowForDevice(cntx context.Context, d *VoltDevice, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301224 logger.Debugw(ctx, "Process IGMP DS Flows for device", log.Fields{"device": d.Name, "addFlow": addFlow})
1225
1226 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1227 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301228 va.ProcessIgmpDSFlowForMvlan(cntx, d, mvProfile, addFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301229 return true
1230 }
1231 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1232}
1233
1234// GetDeviceFromPort : This is suitable only for access ports as their naming convention
1235// makes them unique across all the OLTs. This must be called with
1236// port name that is an access port. Currently called from VNETs, attached
1237// only to access ports, and the services which are also attached only
1238// to access ports
1239func (va *VoltApplication) GetDeviceFromPort(port string) (*VoltDevice, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301240 logger.Debugw(ctx, "Received Get Device From Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301241 va.portLock.Lock()
1242 defer va.portLock.Unlock()
1243 var err error
1244 err = nil
1245 p, ok := va.PortsDisc.Load(port)
1246 if !ok {
1247 return nil, errorCodes.ErrPortNotFound
1248 }
1249 d := va.GetDevice(p.(*VoltPort).Device)
1250 if d == nil {
1251 err = errorCodes.ErrDeviceNotFound
1252 }
1253 return d, err
1254}
1255
1256// GetPortID : This too applies only to access ports. The ports can be indexed
1257// purely by their names without the device forming part of the key
1258func (va *VoltApplication) GetPortID(port string) (uint32, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301259 logger.Debugw(ctx, "Received Get Port ID", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301260 va.portLock.Lock()
1261 defer va.portLock.Unlock()
1262 p, ok := va.PortsDisc.Load(port)
1263 if !ok {
1264 return 0, errorCodes.ErrPortNotFound
1265 }
1266 return p.(*VoltPort).ID, nil
1267}
1268
1269// GetPortName : This too applies only to access ports. The ports can be indexed
1270// purely by their names without the device forming part of the key
1271func (va *VoltApplication) GetPortName(port uint32) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301272 logger.Debugw(ctx, "Received Get Port Name", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301273 va.portLock.Lock()
1274 defer va.portLock.Unlock()
1275 var portName string
1276 va.PortsDisc.Range(func(key interface{}, value interface{}) bool {
1277 portInfo := value.(*VoltPort)
1278 if portInfo.ID == port {
1279 portName = portInfo.Name
1280 return false
1281 }
1282 return true
1283 })
1284 return portName, nil
1285}
1286
1287// GetPonFromUniPort to get Pon info from UniPort
1288func (va *VoltApplication) GetPonFromUniPort(port string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301289 logger.Debugw(ctx, "Received Get Pon From UniPort", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301290 uniPortID, err := va.GetPortID(port)
1291 if err == nil {
1292 ponPortID := (uniPortID & 0x0FF00000) >> 20 //pon(8) + onu(8) + uni(12)
1293 return strconv.FormatUint(uint64(ponPortID), 10), nil
1294 }
1295 return "", err
1296}
1297
1298// GetPortState : This too applies only to access ports. The ports can be indexed
1299// purely by their names without the device forming part of the key
1300func (va *VoltApplication) GetPortState(port string) (PortState, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301301 logger.Debugw(ctx, "Received Get Port State", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301302 va.portLock.Lock()
1303 defer va.portLock.Unlock()
1304 p, ok := va.PortsDisc.Load(port)
1305 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301306 return 0, errors.New("port not configured")
Naveen Sampath04696f72022-06-13 15:19:14 +05301307 }
1308 return p.(*VoltPort).State, nil
1309}
1310
1311// GetIcmpv6Receivers to get Icmp v6 receivers
1312func (va *VoltApplication) GetIcmpv6Receivers(device string) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301313 logger.Debugw(ctx, "Get Icmpv6 Receivers", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301314 var receiverList []uint32
1315 receivers, _ := va.Icmpv6Receivers.Load(device)
1316 if receivers != nil {
1317 receiverList = receivers.([]uint32)
1318 }
1319 return receiverList
1320}
1321
1322// AddIcmpv6Receivers to add Icmp v6 receivers
1323func (va *VoltApplication) AddIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301324 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301325 var receiverList []uint32
1326 receivers, _ := va.Icmpv6Receivers.Load(device)
1327 if receivers != nil {
1328 receiverList = receivers.([]uint32)
1329 }
1330 receiverList = append(receiverList, portID)
1331 va.Icmpv6Receivers.Store(device, receiverList)
1332 logger.Debugw(ctx, "Receivers after addition", log.Fields{"Receivers": receiverList})
1333 return receiverList
1334}
1335
1336// DelIcmpv6Receivers to delete Icmp v6 receievers
1337func (va *VoltApplication) DelIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301338 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301339 var receiverList []uint32
1340 receivers, _ := va.Icmpv6Receivers.Load(device)
1341 if receivers != nil {
1342 receiverList = receivers.([]uint32)
1343 }
1344 for i, port := range receiverList {
1345 if port == portID {
1346 receiverList = append(receiverList[0:i], receiverList[i+1:]...)
1347 va.Icmpv6Receivers.Store(device, receiverList)
1348 break
1349 }
1350 }
1351 logger.Debugw(ctx, "Receivers After deletion", log.Fields{"Receivers": receiverList})
1352 return receiverList
1353}
1354
1355// ProcessDevFlowForDevice - Process DS ICMPv6 & ARP flow for provided device and vnet profile
1356// device - Device Obj
1357// vnet - vnet profile name
1358// enabled - vlan enabled/disabled - based on the status, the flow shall be added/removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301359func (va *VoltApplication) ProcessDevFlowForDevice(cntx context.Context, device *VoltDevice, vnet *VoltVnet, enabled bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301360 logger.Debugw(ctx, "Process Dev Flow For Device", log.Fields{"Device": device, "VnetName": vnet.Name, "Enabled": enabled})
Naveen Sampath04696f72022-06-13 15:19:14 +05301361 _, applied := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0))
1362 if enabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301363 va.PushDevFlowForVlan(cntx, vnet)
Naveen Sampath04696f72022-06-13 15:19:14 +05301364 } else if !enabled && applied {
1365 //va.DeleteDevFlowForVlan(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301366 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, device.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301367 }
1368}
1369
vinokuma926cb3e2023-03-29 11:41:06 +05301370// NniVlanIndToIgmp - Trigger receiver up indication to all ports with igmp enabled
1371// and has the provided mvlan
Naveen Sampath04696f72022-06-13 15:19:14 +05301372func (va *VoltApplication) NniVlanIndToIgmp(device *VoltDevice, mvp *MvlanProfile) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301373 logger.Infow(ctx, "Received Nni Vlan Ind To Igmp", log.Fields{"Vlan": mvp.Mvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301374
vinokuma926cb3e2023-03-29 11:41:06 +05301375 // Trigger nni indication for receiver only for first time
Naveen Sampath04696f72022-06-13 15:19:14 +05301376 if device.IgmpDsFlowAppliedForMvlan[uint16(mvp.Mvlan)] {
1377 return
1378 }
1379 device.Ports.Range(func(key, value interface{}) bool {
1380 port := key.(string)
1381
1382 if state, _ := va.GetPortState(port); state == PortStateUp {
1383 vpvs, _ := va.VnetsByPort.Load(port)
1384 if vpvs == nil {
1385 return true
1386 }
1387 for _, vpv := range vpvs.([]*VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05301388 // Send indication only for subscribers with the received mvlan profile
Naveen Sampath04696f72022-06-13 15:19:14 +05301389 if vpv.IgmpEnabled && vpv.MvlanProfileName == mvp.Name {
1390 vpv.services.Range(ReceiverUpInd)
1391 }
1392 }
1393 }
1394 return true
1395 })
1396}
1397
1398// PortUpInd :
1399// -----------------------------------------------------------------------
1400// Port status change handling
1401// ----------------------------------------------------------------------
1402// Port UP indication is passed to all services associated with the port
1403// so that the services can configure flows applicable when the port goes
1404// up from down state
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301405func (va *VoltApplication) PortUpInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301406 logger.Infow(ctx, "Received Southbound Port Ind: UP", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301407 d := va.GetDevice(device)
1408
1409 if d == nil {
1410 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: UP", log.Fields{"Device": device, "Port": port})
1411 return
1412 }
1413
vinokuma926cb3e2023-03-29 11:41:06 +05301414 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301415 va.portLock.Lock()
1416 // Do not defer the port mutex unlock here
1417 // Some of the following func calls needs the port lock, so defering the lock here
1418 // may lead to dead-lock
1419 p := d.GetPort(port)
1420
1421 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301422 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 +05301423 va.portLock.Unlock()
1424 return
1425 }
1426 p.State = PortStateUp
1427 va.portLock.Unlock()
1428
Naveen Sampath04696f72022-06-13 15:19:14 +05301429 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301430 logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301431 //va.PushDevFlowForDevice(d)
1432 //Build Igmp TrapFlowRule
1433 //va.ProcessIgmpDSFlowForDevice(d, true)
1434 }
1435 vpvs, ok := va.VnetsByPort.Load(port)
1436 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301437 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301438 //msgbus.ProcessPortInd(msgbus.PortUp, d.SerialNum, p.Name, false, getServiceList(port))
1439 return
1440 }
1441
vinokuma926cb3e2023-03-29 11:41:06 +05301442 // If NNI port is not UP, do not push Flows
Naveen Sampath04696f72022-06-13 15:19:14 +05301443 if d.NniPort == "" {
1444 logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
1445 return
1446 }
1447
Naveen Sampath04696f72022-06-13 15:19:14 +05301448 for _, vpv := range vpvs.([]*VoltPortVnet) {
1449 vpv.VpvLock.Lock()
vinokuma926cb3e2023-03-29 11:41:06 +05301450 // If no service is activated drop the portUpInd
Tinoj Josephec742f62022-09-29 19:11:10 +05301451 if vpv.IsServiceActivated(cntx) {
vinokuma926cb3e2023-03-29 11:41:06 +05301452 // Do not trigger indication for the vpv which is already removed from vpv list as
Tinoj Josephec742f62022-09-29 19:11:10 +05301453 // part of service delete (during the lock wait duration)
1454 // In that case, the services associated wil be zero
1455 if vpv.servicesCount.Load() != 0 {
1456 vpv.PortUpInd(cntx, d, port)
1457 }
1458 } else {
1459 // Service not activated, still attach device to service
1460 vpv.setDevice(d.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301461 }
1462 vpv.VpvLock.Unlock()
1463 }
1464 // At the end of processing inform the other entities that
1465 // are interested in the events
1466}
1467
1468/*
1469func getServiceList(port string) map[string]bool {
1470 serviceList := make(map[string]bool)
1471
1472 getServiceNames := func(key interface{}, value interface{}) bool {
1473 serviceList[key.(string)] = value.(*VoltService).DsHSIAFlowsApplied
1474 return true
1475 }
1476
1477 if vpvs, _ := GetApplication().VnetsByPort.Load(port); vpvs != nil {
1478 vpvList := vpvs.([]*VoltPortVnet)
1479 for _, vpv := range vpvList {
1480 vpv.services.Range(getServiceNames)
1481 }
1482 }
1483 return serviceList
1484
1485}*/
1486
vinokuma926cb3e2023-03-29 11:41:06 +05301487// ReceiverUpInd - Send receiver up indication for service with Igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301488func ReceiverUpInd(key, value interface{}) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301489 logger.Info(ctx, "Receiver Indication: UP")
Naveen Sampath04696f72022-06-13 15:19:14 +05301490 svc := value.(*VoltService)
1491 var vlan of.VlanType
1492
1493 if !svc.IPAssigned() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301494 logger.Warnw(ctx, "IP Not assigned, skipping general query", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +05301495 return false
1496 }
1497
vinokuma926cb3e2023-03-29 11:41:06 +05301498 // Send port up indication to igmp only for service with igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301499 if svc.IgmpEnabled {
1500 if svc.VlanControl == ONUCVlan || svc.VlanControl == ONUCVlanOLTSVlan {
1501 vlan = svc.CVlan
1502 } else {
1503 vlan = svc.UniVlan
1504 }
1505 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
1506 GetApplication().ReceiverUpInd(device.Name, svc.Port, svc.MvlanProfileName, vlan, svc.Pbits)
1507 }
1508 return false
1509 }
1510 return true
1511}
1512
1513// PortDownInd : Port down indication is passed on to the services so that the services
1514// can make changes at this transition.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301515func (va *VoltApplication) PortDownInd(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301516 logger.Infow(ctx, "Received SouthBound Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1517 d := va.GetDevice(device)
1518
1519 if d == nil {
1520 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1521 return
1522 }
vinokuma926cb3e2023-03-29 11:41:06 +05301523 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301524 va.portLock.Lock()
1525 // Do not defer the port mutex unlock here
1526 // Some of the following func calls needs the port lock, so defering the lock here
1527 // may lead to dead-lock
1528 p := d.GetPort(port)
1529 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301530 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 +05301531 va.portLock.Unlock()
1532 return
1533 }
1534 p.State = PortStateDown
1535 va.portLock.Unlock()
1536
1537 if d.State == controller.DeviceStateREBOOTED {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301538 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 +05301539 return
1540 }
1541
1542 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301543 logger.Debugw(ctx, "Received NNI Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301544 va.DeleteDevFlowForDevice(cntx, d)
1545 va.NniDownInd(cntx, device, d.SerialNum)
1546 va.RemovePendingGroups(cntx, device, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301547 }
1548 vpvs, ok := va.VnetsByPort.Load(port)
1549 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301550 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301551 //msgbus.ProcessPortInd(msgbus.PortDown, d.SerialNum, p.Name, false, getServiceList(port))
1552 return
1553 }
Akash Sonia8246972023-01-03 10:37:08 +05301554
Naveen Sampath04696f72022-06-13 15:19:14 +05301555 for _, vpv := range vpvs.([]*VoltPortVnet) {
1556 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301557 vpv.PortDownInd(cntx, device, port, false, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301558 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301559 va.ReceiverDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301560 }
1561 vpv.VpvLock.Unlock()
1562 }
1563}
1564
1565// PacketInInd :
1566// -----------------------------------------------------------------------
1567// PacketIn Processing
1568// Packet In Indication processing. It arrives with the identities of
1569// the device and port on which the packet is received. At first, the
1570// packet is decoded and the right processor is called. Currently, we
1571// plan to support only DHCP and IGMP. In future, we can add more
1572// capabilities as needed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301573func (va *VoltApplication) PacketInInd(cntx context.Context, device string, port string, pkt []byte) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301574 logger.Infow(ctx, "Received a Packet-In Indication", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301575 // Decode the incoming packet
1576 packetSide := US
1577 if strings.Contains(port, NNI) {
1578 packetSide = DS
1579 }
1580
Naveen Sampath04696f72022-06-13 15:19:14 +05301581 gopkt := gopacket.NewPacket(pkt, layers.LayerTypeEthernet, gopacket.Default)
1582
1583 var dot1qFound = false
1584 for _, l := range gopkt.Layers() {
1585 if l.LayerType() == layers.LayerTypeDot1Q {
1586 dot1qFound = true
1587 break
1588 }
1589 }
1590
1591 if !dot1qFound {
1592 logger.Debugw(ctx, "Ignoring Received Packet-In Indication without Dot1Q Header",
1593 log.Fields{"Device": device, "Port": port})
1594 return
1595 }
1596
1597 logger.Debugw(ctx, "Received Southbound Packet In", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1598
1599 // Classify the packet into packet types that we support
1600 // The supported types are DHCP and IGMP. The DHCP packet is
1601 // identified by matching the L4 protocol to UDP. The IGMP packet
1602 // is identified by matching L3 protocol to IGMP
1603 arpl := gopkt.Layer(layers.LayerTypeARP)
1604 if arpl != nil {
1605 if callBack, ok := PacketHandlers[ARP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301606 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301607 } else {
1608 logger.Debugw(ctx, "ARP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1609 }
1610 return
1611 }
1612 ipv4l := gopkt.Layer(layers.LayerTypeIPv4)
1613 if ipv4l != nil {
1614 ip := ipv4l.(*layers.IPv4)
1615
1616 if ip.Protocol == layers.IPProtocolUDP {
1617 logger.Debugw(ctx, "Received Southbound UDP ipv4 packet in", log.Fields{"StreamSide": packetSide})
1618 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv4)
1619 if dhcpl != nil {
1620 if callBack, ok := PacketHandlers[DHCPv4]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301621 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301622 } else {
1623 logger.Debugw(ctx, "DHCPv4 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1624 }
1625 }
1626 } else if ip.Protocol == layers.IPProtocolIGMP {
1627 logger.Debugw(ctx, "Received Southbound IGMP packet in", log.Fields{"StreamSide": packetSide})
1628 if callBack, ok := PacketHandlers[IGMP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301629 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301630 } else {
1631 logger.Debugw(ctx, "IGMP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1632 }
1633 }
1634 return
1635 }
1636 ipv6l := gopkt.Layer(layers.LayerTypeIPv6)
1637 if ipv6l != nil {
1638 ip := ipv6l.(*layers.IPv6)
1639 if ip.NextHeader == layers.IPProtocolUDP {
1640 logger.Debug(ctx, "Received Southbound UDP ipv6 packet in")
1641 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv6)
1642 if dhcpl != nil {
1643 if callBack, ok := PacketHandlers[DHCPv6]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301644 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301645 } else {
1646 logger.Debugw(ctx, "DHCPv6 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1647 }
1648 }
1649 }
1650 return
1651 }
1652
1653 pppoel := gopkt.Layer(layers.LayerTypePPPoE)
1654 if pppoel != nil {
1655 logger.Debugw(ctx, "Received Southbound PPPoE packet in", log.Fields{"StreamSide": packetSide})
1656 if callBack, ok := PacketHandlers[PPPOE]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301657 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301658 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301659 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 +05301660 }
1661 }
1662}
1663
1664// GetVlans : This utility gets the VLANs from the packet. The VLANs are
1665// used to identify the right service that must process the incoming
1666// packet
1667func GetVlans(pkt gopacket.Packet) []of.VlanType {
1668 var vlans []of.VlanType
1669 for _, l := range pkt.Layers() {
1670 if l.LayerType() == layers.LayerTypeDot1Q {
1671 q, ok := l.(*layers.Dot1Q)
1672 if ok {
1673 vlans = append(vlans, of.VlanType(q.VLANIdentifier))
1674 }
1675 }
1676 }
1677 return vlans
1678}
1679
1680// GetPriority to get priority
1681func GetPriority(pkt gopacket.Packet) uint8 {
1682 for _, l := range pkt.Layers() {
1683 if l.LayerType() == layers.LayerTypeDot1Q {
1684 q, ok := l.(*layers.Dot1Q)
1685 if ok {
1686 return q.Priority
1687 }
1688 }
1689 }
1690 return PriorityNone
1691}
1692
1693// HandleFlowClearFlag to handle flow clear flag during reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301694func (va *VoltApplication) HandleFlowClearFlag(cntx context.Context, deviceID string, serialNum, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301695 logger.Infow(ctx, "Clear All flags for Device", log.Fields{"Device": deviceID, "SerialNum": serialNum, "SBID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301696 dev, ok := va.DevicesDisc.Load(deviceID)
1697 if ok && dev != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301698 logger.Debugw(ctx, "Clear Flags for device", log.Fields{"voltDevice": dev.(*VoltDevice).Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301699 dev.(*VoltDevice).icmpv6GroupAdded = false
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301700 logger.Debugw(ctx, "Clearing DS Icmpv6 Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301701 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1702 dev.(*VoltDevice).ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301703 logger.Debugw(ctx, "Clearing DS IGMP Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301704 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1705 for k := range dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan {
1706 delete(dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan, k)
1707 }
vinokuma926cb3e2023-03-29 11:41:06 +05301708 // Delete group 1 - ICMPv6/ARP group
Naveen Sampath04696f72022-06-13 15:19:14 +05301709 if err := ProcessIcmpv6McGroup(deviceID, true); err != nil {
1710 logger.Errorw(ctx, "ProcessIcmpv6McGroup failed", log.Fields{"Device": deviceID, "Error": err})
1711 }
1712 } else {
1713 logger.Warnw(ctx, "VoltDevice not found for device ", log.Fields{"deviceID": deviceID})
1714 }
1715
1716 getVpvs := func(key interface{}, value interface{}) bool {
1717 vpvs := value.([]*VoltPortVnet)
1718 for _, vpv := range vpvs {
1719 if vpv.Device == deviceID {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301720 logger.Debugw(ctx, "Clear Flags for vpv",
Naveen Sampath04696f72022-06-13 15:19:14 +05301721 log.Fields{"device": vpv.Device, "port": vpv.Port,
1722 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301723 vpv.ClearAllServiceFlags(cntx)
1724 vpv.ClearAllVpvFlags(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301725
1726 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301727 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05301728 // Also clear service igmp stats
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301729 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301730 }
1731 }
1732 }
1733 return true
1734 }
1735 va.VnetsByPort.Range(getVpvs)
1736
vinokuma926cb3e2023-03-29 11:41:06 +05301737 // Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301738 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301739
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301740 logger.Infow(ctx, "All flags cleared for device", log.Fields{"Device": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301741
vinokuma926cb3e2023-03-29 11:41:06 +05301742 // Reset pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301743 va.RemovePendingGroups(cntx, deviceID, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301744
vinokuma926cb3e2023-03-29 11:41:06 +05301745 // Process all Migrate Service Request - force udpate all profiles since resources are already cleaned up
Naveen Sampath04696f72022-06-13 15:19:14 +05301746 if dev != nil {
1747 triggerForceUpdate := func(key, value interface{}) bool {
1748 msrList := value.(*util.ConcurrentMap)
1749 forceUpdateServices := func(key, value interface{}) bool {
1750 msr := value.(*MigrateServicesRequest)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301751 forceUpdateAllServices(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301752 return true
1753 }
1754 msrList.Range(forceUpdateServices)
1755 return true
1756 }
1757 dev.(*VoltDevice).MigratingServices.Range(triggerForceUpdate)
1758 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301759 va.FetchAndProcessAllMigrateServicesReq(cntx, deviceID, forceUpdateAllServices)
Naveen Sampath04696f72022-06-13 15:19:14 +05301760 }
1761}
1762
vinokuma926cb3e2023-03-29 11:41:06 +05301763// GetPonPortIDFromUNIPort to get pon port id from uni port
Naveen Sampath04696f72022-06-13 15:19:14 +05301764func GetPonPortIDFromUNIPort(uniPortID uint32) uint32 {
1765 ponPortID := (uniPortID & 0x0FF00000) >> 20
1766 return ponPortID
1767}
1768
vinokuma926cb3e2023-03-29 11:41:06 +05301769// ProcessFlowModResultIndication - Processes Flow mod operation indications from controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301770func (va *VoltApplication) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301771 logger.Debugw(ctx, "Received Flow Mod Result Indication.", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301772 d := va.GetDevice(flowStatus.Device)
1773 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301774 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 +05301775 return
1776 }
1777
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301778 cookieExists := ExecuteFlowEvent(cntx, d, flowStatus.Cookie, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +05301779
1780 if flowStatus.Flow != nil {
1781 flowAdd := (flowStatus.FlowModType == of.CommandAdd)
1782 if !cookieExists && !isFlowStatusSuccess(flowStatus.Status, flowAdd) {
1783 pushFlowFailureNotif(flowStatus)
1784 }
1785 }
1786}
1787
Akash Sonief452f12024-12-12 18:20:28 +05301788// CheckAndDeactivateService - check if the attempts for flow delete has reached threshold or not
1789func (va *VoltApplication) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
1790 logger.Debugw(ctx, "Check and Deactivate service", log.Fields{"Cookie": flow.Cookie, "FlowCount": flow.FlowCount, "DeviceSerial": devSerialNum})
1791 if flow.FlowCount >= controller.GetController().GetMaxFlowRetryAttempt() {
1792 devConfig := va.GetDeviceConfig(devSerialNum)
1793 if devConfig != nil {
1794 portNo := util.GetUniPortFromFlow(devConfig.UplinkPort, flow)
1795 portName, err := va.GetPortName(portNo)
1796 if err != nil {
1797 logger.Warnw(ctx, "Error getting port name", log.Fields{"Reason": err.Error(), "PortID": portNo})
1798 return
1799 } else if portName == "" {
1800 logger.Warnw(ctx, "Port does not exist", log.Fields{"PortID": portNo})
1801 return
1802 }
1803 svc := va.GetServiceNameFromCookie(flow.Cookie, portName, uint8(of.PbitMatchNone), devID, flow.Match.TableMetadata)
1804 if svc != nil {
1805 va.DeactivateServiceForPort(ctx, svc, devID, portName)
1806 }
1807 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301808 }
Akash Sonief452f12024-12-12 18:20:28 +05301809}
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301810
Akash Sonief452f12024-12-12 18:20:28 +05301811// DeactivateServiceForPort - deactivate service for given UNI and remove flows from DB, after max flow install threshold has reached
1812func (va *VoltApplication) DeactivateServiceForPort(cntx context.Context, vs *VoltService, devID string, portName string) {
1813 logger.Debugw(ctx, "Flow install threshold reached. Deactivating service", log.Fields{"Service": vs.Name, "Port": portName})
1814
1815 if devID == vs.Device && portName == vs.Port && vs.IsActivated {
1816 vs.SetSvcDeactivationFlags(SvcDeacRsn_Controller)
1817 va.ServiceByName.Store(vs.Name, vs)
1818 vs.WriteToDb(cntx)
1819 device, err := va.GetDeviceFromPort(portName)
1820 if err != nil {
1821 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
1822 // So no error is returned
1823 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portName})
1824 }
1825 p := device.GetPort(vs.Port)
1826 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
1827 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
1828 // Port down call internally deletes all the flows
1829 vpv.PortDownInd(cntx, device.Name, portName, true, true)
1830 if vpv.IgmpEnabled {
1831 va.ReceiverDownInd(cntx, device.Name, portName)
1832 }
1833 } else {
1834 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": device.Name, "port": portName, "SvcName": vs.Name})
1835 }
1836 logger.Infow(ctx, "Service deactivated after flow install threshold", log.Fields{"Device": device.Name, "Service": vs.Name, "Port": portName})
1837 }
1838 vs.DeactivateInProgress = false
1839 va.ServiceByName.Store(vs.Name, vs)
1840 vs.WriteToDb(cntx)
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301841 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301842}
1843
Naveen Sampath04696f72022-06-13 15:19:14 +05301844func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1845 subFlow := flowStatus.Flow
1846 cookie := subFlow.Cookie
1847 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301848 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301849}
1850
vinokuma926cb3e2023-03-29 11:41:06 +05301851// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301852func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301853 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301854 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1855 mvp := value.(*MvlanProfile)
1856 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301857 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301858 }
1859 return true
1860 }
1861 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1862}
1863
1864// TaskInfo structure that is used to store the task Info.
1865type TaskInfo struct {
1866 ID string
1867 Name string
1868 Timestamp string
1869}
1870
1871// GetTaskList to get task list information.
1872func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301873 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301874 taskList := cntlr.GetController().GetTaskList(device)
1875 taskMap := make(map[int]*TaskInfo)
1876 for i, task := range taskList {
1877 taskID := strconv.Itoa(int(task.TaskID()))
1878 name := task.Name()
1879 timestamp := task.Timestamp()
1880 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1881 taskMap[i] = taskInfo
1882 }
1883 return taskMap
1884}
1885
1886// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1887func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301888 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301889 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301890
1891 if voltDevice != nil {
1892 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301893 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 +05301894 } else {
1895 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301896 // Add Serial Number to Blocked Devices List.
1897 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1898 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1899
1900 updateSlNoForVnet := func(key, value interface{}) bool {
1901 vnet := value.(*VoltVnet)
1902 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1903 if deviceSlNo == oldOltSlNo {
1904 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1905 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1906 break
1907 }
1908 }
1909 return true
1910 }
1911
1912 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1913 mvProfile := value.(*MvlanProfile)
1914 for deviceSlNo := range mvProfile.DevicesList {
1915 if deviceSlNo == oldOltSlNo {
1916 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1917 delete(mvProfile.DevicesList, oldOltSlNo)
1918 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1919 break
1920 }
1921 }
1922 return true
1923 }
1924
1925 va.VnetsByName.Range(updateSlNoForVnet)
1926 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1927
1928 // Clear the serial number from Blocked Devices List
1929 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1930 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301931 }
1932}
1933
1934// GetVpvsForDsPkt to get vpv for downstream packets
1935func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1936 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301937 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301938 var matchVPVs []*VoltPortVnet
1939 findVpv := func(key, value interface{}) bool {
1940 vpvs := value.([]*VoltPortVnet)
1941 for _, vpv := range vpvs {
1942 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1943 var subMac net.HardwareAddr
1944 if NonZeroMacAddress(vpv.MacAddr) {
1945 subMac = vpv.MacAddr
1946 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
1947 subMac = vpv.LearntMacAddr
1948 } else {
1949 matchVPVs = append(matchVPVs, vpv)
1950 continue
1951 }
1952 if util.MacAddrsMatch(subMac, clientMAC) {
1953 matchVPVs = append([]*VoltPortVnet{}, vpv)
1954 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
1955 return false
1956 }
1957 }
1958 }
1959 return true
1960 }
1961 va.VnetsByPort.Range(findVpv)
1962
1963 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301964 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
1965 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301966 }
1967 return matchVPVs, nil
1968}
1969
1970// GetMacInPortMap to get PORT value based on MAC key
1971func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301972 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301973 if NonZeroMacAddress(macAddr) {
1974 va.macPortLock.Lock()
1975 defer va.macPortLock.Unlock()
1976 if port, ok := va.macPortMap[macAddr.String()]; ok {
1977 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1978 return port
1979 }
1980 }
1981 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
1982 return ""
1983}
1984
1985// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
1986func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301987 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301988 if NonZeroMacAddress(macAddr) {
1989 va.macPortLock.Lock()
1990 va.macPortMap[macAddr.String()] = port
1991 va.macPortLock.Unlock()
1992 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1993 }
1994}
1995
1996// DeleteMacInPortMap to remove MAC key from MacPortMap
1997func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301998 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301999 if NonZeroMacAddress(macAddr) {
2000 port := va.GetMacInPortMap(macAddr)
2001 va.macPortLock.Lock()
2002 delete(va.macPortMap, macAddr.String())
2003 va.macPortLock.Unlock()
2004 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
2005 }
2006}
2007
vinokuma926cb3e2023-03-29 11:41:06 +05302008// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302009func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
2010 var grpMap map[*IgmpGroup]bool
2011 var ok bool
2012
2013 va.PendingPoolLock.Lock()
2014 defer va.PendingPoolLock.Unlock()
2015
2016 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
2017 // Do Not Reset any current profile info since group table entry tied to mvlan profile
2018 // The PonVlan is part of set field in group installed
2019 // Hence, Group created is always tied to the same mvlan profile until deleted
2020
2021 for device := range ig.Devices {
2022 key := getPendingPoolKey(ig.Mvlan, device)
2023
2024 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
2025 grpMap = make(map[*IgmpGroup]bool)
2026 }
2027 grpMap[ig] = true
2028
2029 //Add grpObj reference to all associated devices
2030 va.IgmpPendingPool[key] = grpMap
2031 }
2032}
2033
vinokuma926cb3e2023-03-29 11:41:06 +05302034// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302035func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
2036 GetApplication().PendingPoolLock.Lock()
2037 defer GetApplication().PendingPoolLock.Unlock()
2038
2039 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)})
2040
2041 key := getPendingPoolKey(ig.Mvlan, device)
2042 if _, ok := va.IgmpPendingPool[key]; ok {
2043 delete(va.IgmpPendingPool[key], ig)
2044 return true
2045 }
2046 return false
2047}
2048
vinokuma926cb3e2023-03-29 11:41:06 +05302049// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302050func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302051 GetApplication().PendingPoolLock.Lock()
2052 defer GetApplication().PendingPoolLock.Unlock()
2053
2054 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
2055
2056 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302057 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302058}
2059
vinokuma926cb3e2023-03-29 11:41:06 +05302060// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05302061// 1. Deletes the group from device
2062// 2. Delete the IgmpGroup obj and release the group ID to pool
2063// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302064func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302065 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05302066 if grpMap, ok := va.IgmpPendingPool[key]; ok {
2067 delete(va.IgmpPendingPool, key)
2068 for ig := range grpMap {
2069 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302070 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302071 }
2072 }
2073 }
2074}
2075
vinokuma926cb3e2023-03-29 11:41:06 +05302076// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302077func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302078 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)})
2079 for device := range ig.PendingGroupForDevice {
2080 va.RemoveGroupFromPendingPool(device, ig)
2081 }
2082}
2083
vinokuma926cb3e2023-03-29 11:41:06 +05302084// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302085func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302086 var ig *IgmpGroup
2087
2088 va.PendingPoolLock.Lock()
2089 defer va.PendingPoolLock.Unlock()
2090
2091 key := getPendingPoolKey(mvlan, device)
2092 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2093
vinokuma926cb3e2023-03-29 11:41:06 +05302094 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302095 grpMap, ok := va.IgmpPendingPool[key]
2096 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302097 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 +05302098 return nil
2099 }
2100
vinokuma926cb3e2023-03-29 11:41:06 +05302101 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302102 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302103 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302104 for dev := range ig.Devices {
2105 key := getPendingPoolKey(mvlan, dev)
2106 delete(va.IgmpPendingPool[key], ig)
2107 }
2108
vinokuma926cb3e2023-03-29 11:41:06 +05302109 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302110 if ig.NumDevicesActive() == 0 {
2111 return ig
2112 }
2113
vinokuma926cb3e2023-03-29 11:41:06 +05302114 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302115 }
2116 return nil
2117}
2118
vinokuma926cb3e2023-03-29 11:41:06 +05302119// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302120// reference - mvlan/device ID
2121// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302122// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302123func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302124 va.PendingPoolLock.Lock()
2125 defer va.PendingPoolLock.Unlock()
2126
2127 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2128
vinokuma926cb3e2023-03-29 11:41:06 +05302129 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302130 paramPosition := 0
2131 if isRefDevice {
2132 paramPosition = 1
2133 }
2134
2135 // 1.Remove the Entry from pending pool
2136 // 2.Deletes the group from device
2137 // 3.Delete the IgmpGroup obj and release the group ID to pool
2138 for key := range va.IgmpPendingPool {
2139 keyParams := strings.Split(key, "_")
2140 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302141 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302142 }
2143 }
2144}
2145
2146func getPendingPoolKey(mvlan of.VlanType, device string) string {
2147 return mvlan.String() + "_" + device
2148}
2149
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302150func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302151 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302152 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2153 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302154 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302155 return true
2156 }
2157 va.IgmpGroups.Range(removeExpiredGroups)
2158}
2159
vinokuma926cb3e2023-03-29 11:41:06 +05302160// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302161func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302162 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302163 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302164 va.TriggerPendingServiceDeleteReq(cntx, device)
2165 va.TriggerPendingVpvDeleteReq(cntx, device)
2166 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302167 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302168}
2169
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302170// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2171func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302172 va.ServicesToDeactivate.Range(func(key, value interface{}) bool {
2173 serviceName := key.(string)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302174 if vs := va.GetService(serviceName); vs != nil {
2175 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302176 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302177 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2178 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302179 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 +05302180 return true
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302181 }
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302182 vpv.DelTrapFlows(cntx)
2183 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302184 // Set the flag to false and clear the SevicesToDeactivate map entry so that when core restarts, VGC will not
2185 // try to deactivate the service again
2186 vs.DeactivateInProgress = false
2187 va.ServicesToDeactivate.Delete(serviceName)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302188 vs.WriteToDb(cntx)
2189 vpv.ClearServiceCounters(cntx)
2190 }
2191 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302192 logger.Warnw(ctx, "Pending Service Not found during Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302193 }
Akash Sonief452f12024-12-12 18:20:28 +05302194 return true
2195 })
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302196}
2197
vinokuma926cb3e2023-03-29 11:41:06 +05302198// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302199func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Akash Sonief452f12024-12-12 18:20:28 +05302200 va.ServicesToDelete.Range(func(key, value interface{}) bool {
2201 serviceName := key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +05302202 if vs := va.GetService(serviceName); vs != nil {
2203 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302204 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302205 vs.DelHsiaFlows(cntx)
Akash Sonief452f12024-12-12 18:20:28 +05302206 // Clear the SevicesToDelete map so that when core restarts, VGC will not try to deactivate the service again
2207 va.ServicesToDelete.Delete(serviceName)
Naveen Sampath04696f72022-06-13 15:19:14 +05302208 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302209 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302210 }
2211 }
2212 } else {
Akash Sonief452f12024-12-12 18:20:28 +05302213 logger.Warnw(ctx, "Pending Service Not found during Delete", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302214 }
Akash Sonief452f12024-12-12 18:20:28 +05302215 return true
2216 })
Naveen Sampath04696f72022-06-13 15:19:14 +05302217}
2218
vinokuma926cb3e2023-03-29 11:41:06 +05302219// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302220func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302221 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302222 for vpv := range va.VoltPortVnetsToDelete {
2223 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302224 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 +05302225 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302226 }
2227 }
2228}
2229
vinokuma926cb3e2023-03-29 11:41:06 +05302230// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302231func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302232 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302233 for vnetName := range va.VnetsToDelete {
2234 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2235 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302236 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302237 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302238 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302239 va.deleteVnetConfig(vnet)
2240 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302241 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302242 }
2243 }
2244 }
2245}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302246
2247type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302248 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302249 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302250 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2251 EnableEapol bool `json:"enableEapol"`
2252 EnableDhcpV6 bool `json:"enableDhcpV6"`
2253 EnableDhcpV4 bool `json:"enableDhcpV4"`
2254 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302255}
2256
2257func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2258 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2259 va.OltFlowServiceConfig = oltFlowService
2260 b, err := json.Marshal(va.OltFlowServiceConfig)
2261 if err != nil {
2262 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2263 return
2264 }
2265 _ = db.PutOltFlowService(cntx, string(b))
2266}
Akash Sonia8246972023-01-03 10:37:08 +05302267
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302268// RestoreOltFlowService to read from the DB and restore olt flow service config
2269func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2270 oltflowService, err := db.GetOltFlowService(cntx)
2271 if err != nil {
2272 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2273 return
2274 }
2275 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2276 if err != nil {
2277 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2278 return
2279 }
2280 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2281}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302282
Akash Soni87a19072023-02-28 00:46:59 +05302283func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302284 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302285 var dc *DeviceConfig
2286 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2287 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2288 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302289 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302290 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302291 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302292 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302293 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302294 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302295 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302296 va.DevicesDisc.Store(id, device)
2297 }
2298}