blob: 51c13eaf7521526e54492c28b0e8a417a45a294a [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14 */
15
16package application
17
18import (
19 "context"
20 "encoding/hex"
21 "encoding/json"
22 "errors"
23 "fmt"
24 "net"
25 "strconv"
26 "strings"
27 "sync"
28 "time"
29
30 "github.com/google/gopacket"
31 "github.com/google/gopacket/layers"
32
Akash Sonia8246972023-01-03 10:37:08 +053033 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053034 "voltha-go-controller/internal/pkg/controller"
35 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053036 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053037 "voltha-go-controller/internal/pkg/intf"
38 "voltha-go-controller/internal/pkg/of"
39 "voltha-go-controller/internal/pkg/tasks"
Akash Soni6f369452023-09-19 11:18:28 +053040 common "voltha-go-controller/internal/pkg/types"
Naveen Sampath04696f72022-06-13 15:19:14 +053041 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053042 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053043)
44
45var logger log.CLogger
46var ctx = context.TODO()
47
48func init() {
49 // Setup this package so that it's log level can be modified at run time
50 var err error
Tinoj Joseph1d108322022-07-13 10:07:39 +053051 logger, err = log.AddPackageWithDefaultParam()
Naveen Sampath04696f72022-06-13 15:19:14 +053052 if err != nil {
53 panic(err)
54 }
55}
56
57const (
58 // TODO - Need to identify a right place for this
59
60 // PriorityNone constant.
61 PriorityNone uint8 = 8
62 // AnyVlan constant.
63 AnyVlan uint16 = 0xFFFF
64)
65
66// List of Mac Learning Type
67const (
Tinoj Joseph1d108322022-07-13 10:07:39 +053068 MacLearningNone MacLearningType = iota
69 Learn
70 ReLearn
Naveen Sampath04696f72022-06-13 15:19:14 +053071)
72
73// MacLearningType represents Mac Learning Type
74type MacLearningType int
75
76var (
77 tickCount uint16
78 vgcRebooted bool
79 isUpgradeComplete bool
80)
81
82var db database.DBIntf
83
84// PacketHandlers : packet handler for different protocols
85var PacketHandlers map[string]CallBack
86
87// CallBack : registered call back function for different protocol packets
Tinoj Joseph07cc5372022-07-18 22:53:51 +053088type CallBack func(cntx context.Context, device string, port string, pkt gopacket.Packet)
Naveen Sampath04696f72022-06-13 15:19:14 +053089
90const (
91 // ARP packet
92 ARP string = "ARP"
93 // DHCPv4 packet
94 DHCPv4 string = "DHCPv4"
95 // DHCPv6 packet
96 DHCPv6 string = "DHCPv6"
97 // IGMP packet
98 IGMP string = "IGMP"
99 // PPPOE packet
100 PPPOE string = "PPPOE"
101 // US packet side
102 US string = "US"
103 // DS packet side
104 DS string = "DS"
105 // NNI port name
106 NNI string = "nni"
107)
108
109// RegisterPacketHandler : API to register callback function for every protocol
110func RegisterPacketHandler(protocol string, callback CallBack) {
111 if PacketHandlers == nil {
112 PacketHandlers = make(map[string]CallBack)
113 }
114 PacketHandlers[protocol] = callback
115}
116
117// ---------------------------------------------------------------------
118// VOLT Ports
119// ---------------------------------------------------------------------
120// VOLT Ports are ports associated with VOLT devices. Each port is classified into
121// Access/NNI. Each port is identified by Name (Identity known to the NB) and
122// Id (Identity used on the SB). Both identities are presented when a port is
123// discovered in the SB.
124
125// VoltPortType type for Port Type
126type VoltPortType uint8
127
128const (
129 // VoltPortTypeAccess constant.
130 VoltPortTypeAccess VoltPortType = 0
131 // VoltPortTypeNni constant.
132 VoltPortTypeNni VoltPortType = 1
133)
134
135// PortState type for Port State.
136type PortState uint8
137
138const (
139 // PortStateDown constant.
140 PortStateDown PortState = 0
141 // PortStateUp constant.
142 PortStateUp PortState = 1
143)
144
145// VoltPort structure that is used to store the ports. The name is the
146// the main identity used by the application. The SB and NB both present name
147// as the identity. The SB is abstracted by VPAgent and the VPAgent transacts
148// using name as identity
149type VoltPort struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530150 Name string
151 Device string
152 PonPort uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530153 ActiveChannels uint32
154 ID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530155 Type VoltPortType
156 State PortState
Naveen Sampath04696f72022-06-13 15:19:14 +0530157 ChannelPerSubAlarmRaised bool
158}
159
160// NewVoltPort : Constructor for the port.
161func NewVoltPort(device string, name string, id uint32) *VoltPort {
162 var vp VoltPort
163 vp.Device = device
164 vp.Name = name
165 vp.ID = id
166 if util.IsNniPort(id) {
167 vp.Type = VoltPortTypeNni
168 } else {
169 vp.PonPort = GetPonPortIDFromUNIPort(id)
170 }
171 vp.State = PortStateDown
172 vp.ChannelPerSubAlarmRaised = false
173 return &vp
174}
175
176// SetPortID : The ID is used when constructing flows as the flows require ID.
177func (vp *VoltPort) SetPortID(id uint32) {
178 vp.ID = id
179 if util.IsNniPort(id) {
180 vp.Type = VoltPortTypeNni
181 }
182}
183
184// ---------------------------------------------------------------------
185// VOLT Device
186// ---------------------------------------------------------------------
187//
188// VoltDevice is an OLT which contains ports of type access and NNI. Each OLT
189// can only have one NNI port in the current release. The NNI port always uses
190// identity 65536 and all the access ports use identities less than 65535. The
191// identification of NNI is done by comparing the port identity with 65535
192
193// VoltDevice fields :
194// Name: This is the name presented by the device/VOLTHA. This doesn't
vinokuma926cb3e2023-03-29 11:41:06 +0530195// have any relation to the physical device
Naveen Sampath04696f72022-06-13 15:19:14 +0530196// SerialNum: This is the serial number of the device and can be used to
vinokuma926cb3e2023-03-29 11:41:06 +0530197// correlate the devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530198// NniPort: The identity of the NNI port
199// Ports: List of all ports added to the device
200type VoltDevice struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530201 FlowAddEventMap *util.ConcurrentMap //map[string]*FlowEvent
202 FlowDelEventMap *util.ConcurrentMap //map[string]*FlowEvent
203 MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
vinokuma926cb3e2023-03-29 11:41:06 +0530204 VpvsBySvlan *util.ConcurrentMap // map[svlan]map[vnet_port]*VoltPortVnet
205 ConfiguredVlanForDeviceFlows *util.ConcurrentMap //map[string]map[string]bool
206 IgmpDsFlowAppliedForMvlan map[uint16]bool
207 State controller.DeviceState
208 SouthBoundID string
209 NniPort string
210 Name string
211 SerialNum string
212 Ports sync.Map
213 VlanPortStatus sync.Map
214 ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
215 PonPortList sync.Map // [PonPortID]map[string]string
216 ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530217 NniDhcpTrapVid of.VlanType
vinokuma926cb3e2023-03-29 11:41:06 +0530218 GlobalDhcpFlowAdded bool
219 icmpv6GroupAdded bool
Akash Soni6f369452023-09-19 11:18:28 +0530220 VoltDeviceIntr VoltDevInterface
221}
222
223type VoltDevInterface interface {
224 GetPortNameFromPortID(portID uint32) string
Naveen Sampath04696f72022-06-13 15:19:14 +0530225}
226
227// NewVoltDevice : Constructor for the device
228func NewVoltDevice(name string, slno, southBoundID string) *VoltDevice {
229 var d VoltDevice
230 d.Name = name
231 d.SouthBoundID = southBoundID
232 d.State = controller.DeviceStateDOWN
233 d.NniPort = ""
234 d.SouthBoundID = southBoundID
235 d.SerialNum = slno
236 d.icmpv6GroupAdded = false
237 d.IgmpDsFlowAppliedForMvlan = make(map[uint16]bool)
238 d.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
239 d.MigratingServices = util.NewConcurrentMap()
240 d.VpvsBySvlan = util.NewConcurrentMap()
241 d.FlowAddEventMap = util.NewConcurrentMap()
242 d.FlowDelEventMap = util.NewConcurrentMap()
243 d.GlobalDhcpFlowAdded = false
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530244 if config, ok := GetApplication().DevicesConfig.Load(slno); ok {
245 //Update nni dhcp vid
Akash Soni53da2852023-03-15 00:31:31 +0530246 deviceConfig := config.(*DeviceConfig)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530247 d.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
248 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530249 return &d
250}
251
vinokuma926cb3e2023-03-29 11:41:06 +0530252// GetAssociatedVpvsForDevice - return the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530253func (va *VoltApplication) GetAssociatedVpvsForDevice(device string, svlan of.VlanType) *util.ConcurrentMap {
254 if d := va.GetDevice(device); d != nil {
255 return d.GetAssociatedVpvs(svlan)
256 }
257 return nil
258}
259
vinokuma926cb3e2023-03-29 11:41:06 +0530260// AssociateVpvsToDevice - updates the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530261func (va *VoltApplication) AssociateVpvsToDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530262 logger.Debugw(ctx, "AssociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530263 if d := va.GetDevice(device); d != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530264 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
265 vpvMap.Set(vpv, true)
266 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530267 logger.Debugw(ctx, "VPVMap: SET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530268 return
269 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530270 logger.Warnw(ctx, "Set VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530271}
272
vinokuma926cb3e2023-03-29 11:41:06 +0530273// DisassociateVpvsFromDevice - disassociated VPVs from given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530274func (va *VoltApplication) DisassociateVpvsFromDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530275 logger.Debugw(ctx, "DisassociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530276 if d := va.GetDevice(device); d != nil {
277 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
278 vpvMap.Remove(vpv)
279 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530280 logger.Debugw(ctx, "VPVMap: Remove", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530281 return
282 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530283 logger.Warnw(ctx, "Remove VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530284}
285
vinokuma926cb3e2023-03-29 11:41:06 +0530286// GetAssociatedVpvs - returns the associated VPVs for the given Svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530287func (d *VoltDevice) GetAssociatedVpvs(svlan of.VlanType) *util.ConcurrentMap {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530288 logger.Debugw(ctx, "Received Get Associated Vpvs", log.Fields{"svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530289 var vpvMap *util.ConcurrentMap
290 var mapIntf interface{}
291 var ok bool
292
293 if mapIntf, ok = d.VpvsBySvlan.Get(svlan); ok {
294 vpvMap = mapIntf.(*util.ConcurrentMap)
295 } else {
296 vpvMap = util.NewConcurrentMap()
297 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530298 logger.Debugw(ctx, "VPVMap: GET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530299 return vpvMap
300}
301
302// AddPort add port to the device.
303func (d *VoltDevice) AddPort(port string, id uint32) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530304 logger.Debugw(ctx, "Add Port", log.Fields{"Port": port, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530305 addPonPortFromUniPort := func(vPort *VoltPort) {
306 if vPort.Type == VoltPortTypeAccess {
307 ponPortID := GetPonPortIDFromUNIPort(vPort.ID)
308
309 if ponPortUniList, ok := d.PonPortList.Load(ponPortID); !ok {
310 uniList := make(map[string]uint32)
311 uniList[port] = vPort.ID
312 d.PonPortList.Store(ponPortID, uniList)
313 } else {
314 ponPortUniList.(map[string]uint32)[port] = vPort.ID
315 d.PonPortList.Store(ponPortID, ponPortUniList)
316 }
317 }
318 }
319 va := GetApplication()
320 if pIntf, ok := d.Ports.Load(port); ok {
321 voltPort := pIntf.(*VoltPort)
322 addPonPortFromUniPort(voltPort)
323 va.AggActiveChannelsCountPerSub(d.Name, port, voltPort)
324 d.Ports.Store(port, voltPort)
325 return voltPort
326 }
327 p := NewVoltPort(d.Name, port, id)
328 va.AggActiveChannelsCountPerSub(d.Name, port, p)
329 d.Ports.Store(port, p)
330 if util.IsNniPort(id) {
331 d.NniPort = port
332 }
333 addPonPortFromUniPort(p)
334 return p
335}
336
337// GetPort to get port information from the device.
338func (d *VoltDevice) GetPort(port string) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530339 logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530340 if pIntf, ok := d.Ports.Load(port); ok {
341 return pIntf.(*VoltPort)
342 }
343 return nil
344}
345
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530346// GetPortByPortID to get port information from the device.
347func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530348 logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530349 portName := ""
350 d.Ports.Range(func(key, value interface{}) bool {
351 vp := value.(*VoltPort)
352 if vp.ID == portID {
353 portName = vp.Name
354 }
355 return true
356 })
357 return portName
358}
359
Naveen Sampath04696f72022-06-13 15:19:14 +0530360// DelPort to delete port from the device
361func (d *VoltDevice) DelPort(port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530362 logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530363 if _, ok := d.Ports.Load(port); ok {
364 d.Ports.Delete(port)
365 } else {
366 logger.Warnw(ctx, "Port doesn't exist", log.Fields{"Device": d.Name, "Port": port})
367 }
368}
369
370// pushFlowsForUnis to send port-up-indication for uni ports.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530371func (d *VoltDevice) pushFlowsForUnis(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530372 logger.Info(ctx, "NNI Discovered, Sending Port UP Ind for UNIs")
373 d.Ports.Range(func(key, value interface{}) bool {
374 port := key.(string)
375 vp := value.(*VoltPort)
376
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530377 logger.Debugw(ctx, "NNI Discovered. Sending Port UP Ind for UNI", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530378 //Ignore if UNI port is not UP
379 if vp.State != PortStateUp {
380 return true
381 }
382
383 //Obtain all VPVs associated with the port
384 vnets, ok := GetApplication().VnetsByPort.Load(port)
385 if !ok {
386 return true
387 }
388
389 for _, vpv := range vnets.([]*VoltPortVnet) {
390 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530391 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530392 vpv.VpvLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +0530393 }
394 return true
395 })
396}
397
398// ----------------------------------------------------------
399// VOLT Application - hosts all other objects
400// ----------------------------------------------------------
401//
402// The VOLT application is a singleton implementation where
403// there is just one instance in the system and is the gateway
404// to all other components within the controller
405// The declaration of the singleton object
406var vapplication *VoltApplication
407
Akash Soni6f369452023-09-19 11:18:28 +0530408type VoltAppInterface interface {
409 AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
410 AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
411 AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error
412 GetFlowProvisionStatus(portNo string) FlowProvisionStatus
413 DelServiceWithPrefix(cntx context.Context, prefix string) error
414 GetDevice(device string) *VoltDevice
415 GetTaskList(device string) map[int]*TaskInfo
416 AddMeterProf(cntx context.Context, cfg VoltMeter)
417 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
418 DelMvlanProfile(cntx context.Context, name string) error
419 GetMvlanProfileByTag(vlan of.VlanType) *MvlanProfile
420 AddMcastConfig(cntx context.Context, MvlanProfileID string, IgmpProfileID string, IgmpProxyIP string, OltSerialNum string) error
421 DelMeterProf(cntx context.Context, name string) error
422 GetMeterByName(name string) (*VoltMeter, bool)
423 UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig)
424 GetDeviceConfig(serNum string) *DeviceConfig
425 GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error)
426 GetAllMacLearnerInfo() ([]MacLearnerInfo, error)
427 GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error)
428 ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
429 DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
430 GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error)
431 UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService)
432 GetIgnoredPorts() (map[string][]string, error)
433}
434
Naveen Sampath04696f72022-06-13 15:19:14 +0530435// VoltApplication fields :
436// ServiceByName - Stores the services by the name as key
vinokuma926cb3e2023-03-29 11:41:06 +0530437// A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530438// VnetsByPort - Stores the VNETs by the ports configured
vinokuma926cb3e2023-03-29 11:41:06 +0530439// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530440// VnetsByTag - Stores the VNETs by the VLANS configured
vinokuma926cb3e2023-03-29 11:41:06 +0530441// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530442// VnetsByName - Stores the VNETs by the name configured
vinokuma926cb3e2023-03-29 11:41:06 +0530443// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530444// DevicesDisc - Stores the devices discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530445// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530446// PortsDisc - Stores the ports discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530447// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530448type VoltApplication struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530449 MeterMgr
vinokuma926cb3e2023-03-29 11:41:06 +0530450 DataMigrationInfo DataMigration
451 VnetsBySvlan *util.ConcurrentMap
452 IgmpGroupIds []*IgmpGroup
453 VoltPortVnetsToDelete map[*VoltPortVnet]bool
Akash Sonia8246972023-01-03 10:37:08 +0530454 IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
vinokuma926cb3e2023-03-29 11:41:06 +0530455 macPortMap map[string]string
Akash Sonia8246972023-01-03 10:37:08 +0530456 VnetsToDelete map[string]bool
457 ServicesToDelete map[string]bool
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530458 ServicesToDeactivate map[string]bool
Akash Sonia8246972023-01-03 10:37:08 +0530459 PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
460 vendorID string
vinokuma926cb3e2023-03-29 11:41:06 +0530461 ServiceByName sync.Map // [serName]*VoltService
462 VnetsByPort sync.Map // [portName][]*VoltPortVnet
463 VnetsByTag sync.Map // [svlan-cvlan-uvlan]*VoltVnet
464 VnetsByName sync.Map // [vnetName]*VoltVnet
465 DevicesDisc sync.Map
466 PortsDisc sync.Map
467 IgmpGroups sync.Map // [grpKey]*IgmpGroup
468 MvlanProfilesByTag sync.Map
469 MvlanProfilesByName sync.Map
470 Icmpv6Receivers sync.Map
471 DeviceCounters sync.Map //[logicalDeviceId]*DeviceCounters
472 ServiceCounters sync.Map //[serviceName]*ServiceCounters
473 NbDevice sync.Map // [OLTSouthBoundID]*NbDevice
474 OltIgmpInfoBySerial sync.Map
475 McastConfigMap sync.Map //[OltSerialNo_MvlanProfileID]*McastConfig
Akash Sonia8246972023-01-03 10:37:08 +0530476 DevicesConfig sync.Map //[serialNumber]*DeviceConfig
vinokuma926cb3e2023-03-29 11:41:06 +0530477 IgmpProfilesByName sync.Map
478 IgmpTasks tasks.Tasks
479 IndicationsTasks tasks.Tasks
480 MulticastAlarmTasks tasks.Tasks
481 IgmpKPIsTasks tasks.Tasks
482 pppoeTasks tasks.Tasks
483 OltFlowServiceConfig OltFlowService
484 PendingPoolLock sync.RWMutex
485 // MacAddress-Port MAP to avoid swap of mac across ports.
486 macPortLock sync.RWMutex
487 portLock sync.Mutex
Akash Sonia8246972023-01-03 10:37:08 +0530488}
Naveen Sampath04696f72022-06-13 15:19:14 +0530489
Akash Sonia8246972023-01-03 10:37:08 +0530490type DeviceConfig struct {
491 SerialNumber string `json:"id"`
492 HardwareIdentifier string `json:"hardwareIdentifier"`
Akash Soni87a19072023-02-28 00:46:59 +0530493 IPAddress string `json:"ipAddress"`
Akash Soni53da2852023-03-15 00:31:31 +0530494 UplinkPort string `json:"uplinkPort"`
Akash Sonia8246972023-01-03 10:37:08 +0530495 NasID string `json:"nasId"`
496 NniDhcpTrapVid int `json:"nniDhcpTrapVid"`
Naveen Sampath04696f72022-06-13 15:19:14 +0530497}
498
499// PonPortCfg contains NB port config and activeIGMPChannels count
500type PonPortCfg struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530501 PortAlarmProfileID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530502 PortID uint32
503 MaxActiveChannels uint32
504 ActiveIGMPChannels uint32
505 EnableMulticastKPI bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530506}
507
508// NbDevice OLT Device info
509type NbDevice struct {
510 SouthBoundID string
511 PonPorts sync.Map // [PortID]*PonPortCfg
512}
513
514// RestoreNbDeviceFromDb restores the NB Device in case of VGC pod restart.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530515func (va *VoltApplication) RestoreNbDeviceFromDb(cntx context.Context, deviceID string) *NbDevice {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530516 logger.Debugw(ctx, "Received Restore Nb Device From Db", log.Fields{"deviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530517 nbDevice := NewNbDevice()
518 nbDevice.SouthBoundID = deviceID
519
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530520 nbPorts, _ := db.GetAllNbPorts(cntx, deviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530521
522 for key, p := range nbPorts {
523 b, ok := p.Value.([]byte)
524 if !ok {
525 logger.Warn(ctx, "The value type is not []byte")
526 continue
527 }
528 var port PonPortCfg
529 err := json.Unmarshal(b, &port)
530 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530531 logger.Warnw(ctx, "Unmarshal of PonPortCfg failed", log.Fields{"deviceID": deviceID, "port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530532 continue
533 }
534 logger.Debugw(ctx, "Port recovered", log.Fields{"port": port})
535 ponPortID, _ := strconv.Atoi(key)
536 nbDevice.PonPorts.Store(uint32(ponPortID), &port)
537 }
538 va.NbDevice.Store(deviceID, nbDevice)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530539 logger.Debugw(ctx, "Recovered NbDevice From Db", log.Fields{"deviceID": deviceID, "nbDevice": nbDevice})
Naveen Sampath04696f72022-06-13 15:19:14 +0530540 return nbDevice
541}
542
543// NewNbDevice Constructor for NbDevice
544func NewNbDevice() *NbDevice {
545 var nbDevice NbDevice
546 return &nbDevice
547}
548
549// WriteToDb writes nb device port config to kv store
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530550func (nbd *NbDevice) WriteToDb(cntx context.Context, portID uint32, ponPort *PonPortCfg) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530551 b, err := json.Marshal(ponPort)
552 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530553 logger.Errorw(ctx, "PonPortConfig-marshal-failed", log.Fields{"err": err, "ponPort": ponPort})
Naveen Sampath04696f72022-06-13 15:19:14 +0530554 return
555 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530556 db.PutNbDevicePort(cntx, nbd.SouthBoundID, portID, string(b))
Naveen Sampath04696f72022-06-13 15:19:14 +0530557}
558
559// AddPortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530560func (nbd *NbDevice) AddPortToNbDevice(cntx context.Context, portID, allowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +0530561 enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530562 logger.Debugw(ctx, "AddPortToNbDevice", log.Fields{"PortID": portID, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530563 ponPort := &PonPortCfg{
564 PortID: portID,
565 MaxActiveChannels: allowedChannels,
566 EnableMulticastKPI: enableMulticastKPI,
567 PortAlarmProfileID: portAlarmProfileID,
568 }
569 nbd.PonPorts.Store(portID, ponPort)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530570 nbd.WriteToDb(cntx, portID, ponPort)
Naveen Sampath04696f72022-06-13 15:19:14 +0530571 return ponPort
572}
573
Akash Sonia8246972023-01-03 10:37:08 +0530574// RestoreDeviceConfigFromDb to restore vnet from port
575func (va *VoltApplication) RestoreDeviceConfigFromDb(cntx context.Context) {
576 // VNETS must be learnt first
577 dConfig, _ := db.GetDeviceConfig(cntx)
578 for _, device := range dConfig {
579 b, ok := device.Value.([]byte)
580 if !ok {
581 logger.Warn(ctx, "The value type is not []byte")
582 continue
583 }
584 devConfig := DeviceConfig{}
585 err := json.Unmarshal(b, &devConfig)
586 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530587 logger.Warnw(ctx, "Unmarshal of device configuration failed", log.Fields{"Device Config": devConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530588 continue
589 }
590 logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
591 if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid); err != nil {
592 logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
593 }
Akash Sonia8246972023-01-03 10:37:08 +0530594 }
595}
596
597// WriteDeviceConfigToDb writes sb device config to kv store
598func (dc *DeviceConfig) WriteDeviceConfigToDb(cntx context.Context, serialNum string, deviceConfig *DeviceConfig) error {
599 b, err := json.Marshal(deviceConfig)
600 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530601 return fmt.Errorf("deviceConfig-marshal-failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530602 }
603 dberr := db.PutDeviceConfig(cntx, serialNum, string(b))
604 if dberr != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530605 return fmt.Errorf("update device config failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530606 }
607 return nil
608}
609
vinokuma926cb3e2023-03-29 11:41:06 +0530610func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530611 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 +0530612 var dc *DeviceConfig
613
Akash Soni87a19072023-02-28 00:46:59 +0530614 deviceConfig := &DeviceConfig{
615 SerialNumber: serialNum,
616 HardwareIdentifier: hardwareIdentifier,
617 NasID: nasID,
618 UplinkPort: uplinkPort,
619 IPAddress: ipAddress,
vinokuma926cb3e2023-03-29 11:41:06 +0530620 NniDhcpTrapVid: nniDhcpTrapID,
Akash Sonia8246972023-01-03 10:37:08 +0530621 }
Akash Soni87a19072023-02-28 00:46:59 +0530622 va.DevicesConfig.Store(serialNum, deviceConfig)
623 err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
624 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530625 return fmt.Errorf("DB update for device config failed - %w ", err)
Akash Soni87a19072023-02-28 00:46:59 +0530626 }
627
628 // If device is already discovered update the VoltDevice structure
629 device, id := va.GetDeviceBySerialNo(serialNum)
630 if device != nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530631 device.NniDhcpTrapVid = of.VlanType(nniDhcpTrapID)
Akash Soni87a19072023-02-28 00:46:59 +0530632 va.DevicesDisc.Store(id, device)
633 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530634 logger.Debugw(ctx, "Added device config", log.Fields{"Device Config": deviceConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530635 return nil
636}
637
638// GetDeviceConfig to get a device config.
639func (va *VoltApplication) GetDeviceConfig(serNum string) *DeviceConfig {
640 if d, ok := va.DevicesConfig.Load(serNum); ok {
641 return d.(*DeviceConfig)
642 }
643 return nil
644}
645
Naveen Sampath04696f72022-06-13 15:19:14 +0530646// UpdatePortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530647func (nbd *NbDevice) UpdatePortToNbDevice(cntx context.Context, portID, allowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530648 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 +0530649 p, exists := nbd.PonPorts.Load(portID)
650 if !exists {
651 logger.Errorw(ctx, "PON port not exists in nb-device", log.Fields{"portID": portID})
652 return nil
653 }
654 port := p.(*PonPortCfg)
655 if allowedChannels != 0 {
656 port.MaxActiveChannels = allowedChannels
657 port.EnableMulticastKPI = enableMulticastKPI
658 port.PortAlarmProfileID = portAlarmProfileID
659 }
660
661 nbd.PonPorts.Store(portID, port)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530662 nbd.WriteToDb(cntx, portID, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530663 return port
664}
665
666// DeletePortFromNbDevice Deletes pon port from NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530667func (nbd *NbDevice) DeletePortFromNbDevice(cntx context.Context, portID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530668 logger.Debugw(ctx, "Received Delete Port from NbDevice", log.Fields{"portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530669 if _, ok := nbd.PonPorts.Load(portID); ok {
670 nbd.PonPorts.Delete(portID)
671 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530672 db.DelNbDevicePort(cntx, nbd.SouthBoundID, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530673}
674
675// GetApplication : Interface to access the singleton object
676func GetApplication() *VoltApplication {
677 if vapplication == nil {
678 vapplication = newVoltApplication()
679 }
680 return vapplication
681}
682
683// newVoltApplication : Constructor for the singleton object. Hence this is not
684// an exported function
685func newVoltApplication() *VoltApplication {
686 var va VoltApplication
687 va.IgmpTasks.Initialize(context.TODO())
688 va.MulticastAlarmTasks.Initialize(context.TODO())
689 va.IgmpKPIsTasks.Initialize(context.TODO())
690 va.pppoeTasks.Initialize(context.TODO())
691 va.storeIgmpProfileMap(DefaultIgmpProfID, newDefaultIgmpProfile())
692 va.MeterMgr.Init()
693 va.AddIgmpGroups(5000)
694 va.macPortMap = make(map[string]string)
695 va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
696 va.VnetsBySvlan = util.NewConcurrentMap()
697 va.VnetsToDelete = make(map[string]bool)
698 va.ServicesToDelete = make(map[string]bool)
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530699 va.ServicesToDeactivate = make(map[string]bool)
Naveen Sampath04696f72022-06-13 15:19:14 +0530700 va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530701 go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
702 go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
Naveen Sampath04696f72022-06-13 15:19:14 +0530703 InitEventFuncMapper()
704 db = database.GetDatabase()
Akash Soni6f369452023-09-19 11:18:28 +0530705
Naveen Sampath04696f72022-06-13 15:19:14 +0530706 return &va
707}
708
vinokuma926cb3e2023-03-29 11:41:06 +0530709// GetFlowEventRegister - returs the register based on flow mod type
Naveen Sampath04696f72022-06-13 15:19:14 +0530710func (d *VoltDevice) GetFlowEventRegister(flowModType of.Command) (*util.ConcurrentMap, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530711 switch flowModType {
712 case of.CommandDel:
713 return d.FlowDelEventMap, nil
714 case of.CommandAdd:
715 return d.FlowAddEventMap, nil
716 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530717 logger.Warnw(ctx, "Unknown Flow Mod received", log.Fields{"flowModtype": flowModType})
Naveen Sampath04696f72022-06-13 15:19:14 +0530718 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530719 return util.NewConcurrentMap(), errors.New("unknown flow mod")
Naveen Sampath04696f72022-06-13 15:19:14 +0530720}
721
722// RegisterFlowAddEvent to register a flow event.
723func (d *VoltDevice) RegisterFlowAddEvent(cookie string, event *FlowEvent) {
724 logger.Debugw(ctx, "Registered Flow Add Event", log.Fields{"Cookie": cookie, "Event": event})
725 d.FlowAddEventMap.MapLock.Lock()
726 defer d.FlowAddEventMap.MapLock.Unlock()
727 d.FlowAddEventMap.Set(cookie, event)
728}
729
730// RegisterFlowDelEvent to register a flow event.
731func (d *VoltDevice) RegisterFlowDelEvent(cookie string, event *FlowEvent) {
732 logger.Debugw(ctx, "Registered Flow Del Event", log.Fields{"Cookie": cookie, "Event": event})
733 d.FlowDelEventMap.MapLock.Lock()
734 defer d.FlowDelEventMap.MapLock.Unlock()
735 d.FlowDelEventMap.Set(cookie, event)
736}
737
738// UnRegisterFlowEvent to unregister a flow event.
739func (d *VoltDevice) UnRegisterFlowEvent(cookie string, flowModType of.Command) {
740 logger.Debugw(ctx, "UnRegistered Flow Add Event", log.Fields{"Cookie": cookie, "Type": flowModType})
741 flowEventMap, err := d.GetFlowEventRegister(flowModType)
742 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530743 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowModType, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530744 return
745 }
746 flowEventMap.MapLock.Lock()
747 defer flowEventMap.MapLock.Unlock()
748 flowEventMap.Remove(cookie)
749}
750
751// AddIgmpGroups to add Igmp groups.
752func (va *VoltApplication) AddIgmpGroups(numOfGroups uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530753 logger.Debugw(ctx, "AddIgmpGroups", log.Fields{"NumOfGroups": numOfGroups})
Naveen Sampath04696f72022-06-13 15:19:14 +0530754 //TODO: Temp change to resolve group id issue in pOLT
755 //for i := 1; uint32(i) <= numOfGroups; i++ {
756 for i := 2; uint32(i) <= (numOfGroups + 1); i++ {
757 ig := IgmpGroup{}
758 ig.GroupID = uint32(i)
759 va.IgmpGroupIds = append(va.IgmpGroupIds, &ig)
760 }
761}
762
763// GetAvailIgmpGroupID to get id of available igmp group.
764func (va *VoltApplication) GetAvailIgmpGroupID() *IgmpGroup {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530765 logger.Info(ctx, "GetAvailIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530766 var ig *IgmpGroup
767 if len(va.IgmpGroupIds) > 0 {
768 ig, va.IgmpGroupIds = va.IgmpGroupIds[0], va.IgmpGroupIds[1:]
769 return ig
770 }
771 return nil
772}
773
774// GetIgmpGroupID to get id of igmp group.
775func (va *VoltApplication) GetIgmpGroupID(gid uint32) (*IgmpGroup, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530776 logger.Info(ctx, "GetIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530777 for id, ig := range va.IgmpGroupIds {
778 if ig.GroupID == gid {
779 va.IgmpGroupIds = append(va.IgmpGroupIds[0:id], va.IgmpGroupIds[id+1:]...)
780 return ig, nil
781 }
782 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530783 return nil, errors.New("group id missing")
Naveen Sampath04696f72022-06-13 15:19:14 +0530784}
785
786// PutIgmpGroupID to add id of igmp group.
787func (va *VoltApplication) PutIgmpGroupID(ig *IgmpGroup) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530788 logger.Debugw(ctx, "GetIgmpGroupID", log.Fields{"GroupID": ig.GroupID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530789 va.IgmpGroupIds = append([]*IgmpGroup{ig}, va.IgmpGroupIds[0:]...)
790}
791
vinokuma926cb3e2023-03-29 11:41:06 +0530792// RestoreUpgradeStatus - gets upgrade/migration status from DB and updates local flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530793func (va *VoltApplication) RestoreUpgradeStatus(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530794 logger.Info(ctx, "Received Restore Upgrade Status")
Naveen Sampath04696f72022-06-13 15:19:14 +0530795 Migrate := new(DataMigration)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530796 if err := GetMigrationInfo(cntx, Migrate); err == nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530797 if Migrate.Status == MigrationInProgress {
798 isUpgradeComplete = false
799 return
800 }
801 }
802 isUpgradeComplete = true
803
804 logger.Infow(ctx, "Upgrade Status Restored", log.Fields{"Upgrade Completed": isUpgradeComplete})
805}
806
807// ReadAllFromDb : If we are restarted, learn from the database the current execution
808// stage
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530809func (va *VoltApplication) ReadAllFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530810 logger.Info(ctx, "Reading the meters from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530811 va.RestoreMetersFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530812 logger.Info(ctx, "Reading the VNETs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530813 va.RestoreVnetsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530814 logger.Info(ctx, "Reading the VPVs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530815 va.RestoreVpvsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530816 logger.Info(ctx, "Reading the Services from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530817 va.RestoreSvcsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530818 logger.Info(ctx, "Reading the MVLANs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530819 va.RestoreMvlansFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530820 logger.Info(ctx, "Reading the IGMP profiles from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530821 va.RestoreIGMPProfilesFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530822 logger.Info(ctx, "Reading the Mcast configs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530823 va.RestoreMcastConfigsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530824 logger.Info(ctx, "Reading the IGMP groups for DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530825 va.RestoreIgmpGroupsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530826 logger.Info(ctx, "Reading Upgrade status from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530827 va.RestoreUpgradeStatus(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530828 logger.Info(ctx, "Reading OltFlowService from DB")
829 va.RestoreOltFlowService(cntx)
Akash Sonia8246972023-01-03 10:37:08 +0530830 logger.Info(ctx, "Reading device config from DB")
831 va.RestoreDeviceConfigFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530832 logger.Info(ctx, "Reconciled from DB")
833}
834
vinokuma926cb3e2023-03-29 11:41:06 +0530835// InitStaticConfig to initialize static config.
Naveen Sampath04696f72022-06-13 15:19:14 +0530836func (va *VoltApplication) InitStaticConfig() {
837 va.InitIgmpSrcMac()
838}
839
840// SetVendorID to set vendor id
841func (va *VoltApplication) SetVendorID(vendorID string) {
842 va.vendorID = vendorID
843}
844
845// GetVendorID to get vendor id
846func (va *VoltApplication) GetVendorID() string {
847 return va.vendorID
848}
849
850// SetRebootFlag to set reboot flag
851func (va *VoltApplication) SetRebootFlag(flag bool) {
852 vgcRebooted = flag
853}
854
855// GetUpgradeFlag to get reboot status
856func (va *VoltApplication) GetUpgradeFlag() bool {
857 return isUpgradeComplete
858}
859
860// SetUpgradeFlag to set reboot status
861func (va *VoltApplication) SetUpgradeFlag(flag bool) {
862 isUpgradeComplete = flag
863}
864
865// ------------------------------------------------------------
866// Device related functions
867
868// AddDevice : Add a device and typically the device stores the NNI port on the device
869// The NNI port is used when the packets are emitted towards the network.
870// The outport is selected as the NNI port of the device. Today, we support
871// a single NNI port per OLT. This is true whether the network uses any
872// protection mechanism (LAG, ERPS, etc.). The aggregate of the such protection
873// is represented by a single NNI port
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530874func (va *VoltApplication) AddDevice(cntx context.Context, device string, slno, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530875 logger.Debugw(ctx, "Received Device Ind: Add", log.Fields{"Device": device, "SrNo": slno, "southBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530876 if _, ok := va.DevicesDisc.Load(device); ok {
877 logger.Warnw(ctx, "Device Exists", log.Fields{"Device": device})
878 }
879 d := NewVoltDevice(device, slno, southBoundID)
880
881 addPort := func(key, value interface{}) bool {
882 portID := key.(uint32)
883 port := value.(*PonPortCfg)
884 va.AggActiveChannelsCountForPonPort(device, portID, port)
885 d.ActiveChannelsPerPon.Store(portID, port)
886 return true
887 }
888 if nbDevice, exists := va.NbDevice.Load(southBoundID); exists {
889 // Pon Ports added before OLT activate.
890 nbDevice.(*NbDevice).PonPorts.Range(addPort)
891 } else {
892 // Check if NbPort exists in DB. VGC restart case.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530893 nbd := va.RestoreNbDeviceFromDb(cntx, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530894 nbd.PonPorts.Range(addPort)
895 }
896 va.DevicesDisc.Store(device, d)
897}
898
899// GetDevice to get a device.
900func (va *VoltApplication) GetDevice(device string) *VoltDevice {
901 if d, ok := va.DevicesDisc.Load(device); ok {
902 return d.(*VoltDevice)
903 }
904 return nil
905}
906
907// DelDevice to delete a device.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530908func (va *VoltApplication) DelDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530909 logger.Debugw(ctx, "Received Device Ind: Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530910 if vdIntf, ok := va.DevicesDisc.Load(device); ok {
911 vd := vdIntf.(*VoltDevice)
912 va.DevicesDisc.Delete(device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530913 _ = db.DelAllRoutesForDevice(cntx, device)
914 va.HandleFlowClearFlag(cntx, device, vd.SerialNum, vd.SouthBoundID)
915 _ = db.DelAllGroup(cntx, device)
916 _ = db.DelAllMeter(cntx, device)
917 _ = db.DelAllPorts(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530918 logger.Debugw(ctx, "Device deleted", log.Fields{"Device": device})
919 } else {
920 logger.Warnw(ctx, "Device Doesn't Exist", log.Fields{"Device": device})
921 }
922}
923
924// GetDeviceBySerialNo to get a device by serial number.
925// TODO - Transform this into a MAP instead
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530926func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530927 logger.Debugw(ctx, "Received Device Ind: Get", log.Fields{"Serial Num": slno})
Naveen Sampath04696f72022-06-13 15:19:14 +0530928 var device *VoltDevice
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530929 var deviceID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530930 getserial := func(key interface{}, value interface{}) bool {
931 device = value.(*VoltDevice)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530932 deviceID = key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +0530933 return device.SerialNum != slno
934 }
935 va.DevicesDisc.Range(getserial)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530936 return device, deviceID
Naveen Sampath04696f72022-06-13 15:19:14 +0530937}
938
939// PortAddInd : This is a PORT add indication coming from the VPAgent, which is essentially
940// a request coming from VOLTHA. The device and identity of the port is provided
941// in this request. Add them to the application for further use
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530942func (va *VoltApplication) PortAddInd(cntx context.Context, device string, id uint32, portName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530943 logger.Debugw(ctx, "Received Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530944 va.portLock.Lock()
945 if d := va.GetDevice(device); d != nil {
946 p := d.AddPort(portName, id)
947 va.PortsDisc.Store(portName, p)
948 va.portLock.Unlock()
949 nni, _ := va.GetNniPort(device)
950 if nni == portName {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530951 d.pushFlowsForUnis(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530952 }
953 } else {
954 va.portLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530955 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 +0530956 }
957}
958
959// PortDelInd : Only the NNI ports are recorded in the device for now. When port delete
960// arrives, only the NNI ports need adjustments.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530961func (va *VoltApplication) PortDelInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530962 logger.Debugw(ctx, "Received Port Ind: Delete", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530963 if d := va.GetDevice(device); d != nil {
964 p := d.GetPort(port)
965 if p != nil && p.State == PortStateUp {
966 logger.Infow(ctx, "Port state is UP. Trigerring Port Down Ind before deleting", log.Fields{"Port": p})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530967 va.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530968 }
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530969 // if RemoveFlowsOnDisable is flase, then flows will be existing till port delete. Remove the flows now
970 if !va.OltFlowServiceConfig.RemoveFlowsOnDisable {
Akash Sonia8246972023-01-03 10:37:08 +0530971 vpvs, ok := va.VnetsByPort.Load(port)
972 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530973 logger.Infow(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
974 } else {
975 for _, vpv := range vpvs.([]*VoltPortVnet) {
976 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530977 // Set delFlowsInDevice to true to delete flows only in DB/device during Port Delete.
978 vpv.PortDownInd(cntx, device, port, true, true)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530979 vpv.VpvLock.Unlock()
980 }
981 }
982 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530983 va.portLock.Lock()
984 defer va.portLock.Unlock()
985 d.DelPort(port)
986 if _, ok := va.PortsDisc.Load(port); ok {
987 va.PortsDisc.Delete(port)
988 }
989 } else {
990 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Delete", log.Fields{"Device": device, "Port": port})
991 }
992}
993
vinokuma926cb3e2023-03-29 11:41:06 +0530994// PortUpdateInd Updates port Id incase of ONU movement
Naveen Sampath04696f72022-06-13 15:19:14 +0530995func (va *VoltApplication) PortUpdateInd(device string, portName string, id uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530996 logger.Debugw(ctx, "Received Port Ind: Update", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530997 va.portLock.Lock()
998 defer va.portLock.Unlock()
999 if d := va.GetDevice(device); d != nil {
1000 vp := d.GetPort(portName)
1001 vp.ID = id
1002 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301003 logger.Warnw(ctx, "Device Not Found", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301004 }
1005}
1006
1007// AddNbPonPort Add pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301008func (va *VoltApplication) AddNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +05301009 enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301010 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 +05301011 var nbd *NbDevice
1012 nbDevice, ok := va.NbDevice.Load(oltSbID)
1013
1014 if !ok {
1015 nbd = NewNbDevice()
1016 nbd.SouthBoundID = oltSbID
1017 } else {
1018 nbd = nbDevice.(*NbDevice)
1019 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301020 port := nbd.AddPortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301021 logger.Debugw(ctx, "Added Port To NbDevice", log.Fields{"port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301022 // Add this port to voltDevice
1023 addPort := func(key, value interface{}) bool {
1024 voltDevice := value.(*VoltDevice)
1025 if oltSbID == voltDevice.SouthBoundID {
1026 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); !exists {
1027 voltDevice.ActiveChannelsPerPon.Store(portID, port)
1028 }
1029 return false
1030 }
1031 return true
1032 }
1033 va.DevicesDisc.Range(addPort)
1034 va.NbDevice.Store(oltSbID, nbd)
1035
1036 return nil
1037}
1038
1039// UpdateNbPonPort update pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301040func (va *VoltApplication) UpdateNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301041 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 +05301042 var nbd *NbDevice
1043 nbDevice, ok := va.NbDevice.Load(oltSbID)
1044
1045 if !ok {
1046 logger.Errorw(ctx, "Device-doesn't-exists", log.Fields{"deviceID": oltSbID})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301047 return fmt.Errorf("device-doesn't-exists - %s", oltSbID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301048 }
1049 nbd = nbDevice.(*NbDevice)
1050
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301051 port := nbd.UpdatePortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301052 if port == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301053 return fmt.Errorf("port-doesn't-exists-%d", portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301054 }
1055 va.NbDevice.Store(oltSbID, nbd)
1056
1057 // Add this port to voltDevice
1058 updPort := func(key, value interface{}) bool {
1059 voltDevice := value.(*VoltDevice)
1060 if oltSbID == voltDevice.SouthBoundID {
1061 voltDevice.ActiveChannelCountLock.Lock()
1062 if p, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1063 oldPort := p.(*PonPortCfg)
1064 if port.MaxActiveChannels != 0 {
1065 oldPort.MaxActiveChannels = port.MaxActiveChannels
1066 oldPort.EnableMulticastKPI = port.EnableMulticastKPI
1067 voltDevice.ActiveChannelsPerPon.Store(portID, oldPort)
1068 }
1069 }
1070 voltDevice.ActiveChannelCountLock.Unlock()
1071 return false
1072 }
1073 return true
1074 }
1075 va.DevicesDisc.Range(updPort)
1076
1077 return nil
1078}
1079
1080// DeleteNbPonPort Delete pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301081func (va *VoltApplication) DeleteNbPonPort(cntx context.Context, oltSbID string, portID uint32) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301082 logger.Debugw(ctx, "Received NbPonPort Ind: Delete", log.Fields{"oltSbID": oltSbID, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301083 nbDevice, ok := va.NbDevice.Load(oltSbID)
1084 if ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301085 nbDevice.(*NbDevice).DeletePortFromNbDevice(cntx, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301086 va.NbDevice.Store(oltSbID, nbDevice.(*NbDevice))
1087 } else {
1088 logger.Warnw(ctx, "Delete pon received for unknown device", log.Fields{"oltSbID": oltSbID})
1089 return nil
1090 }
1091 // Delete this port from voltDevice
1092 delPort := func(key, value interface{}) bool {
1093 voltDevice := value.(*VoltDevice)
1094 if oltSbID == voltDevice.SouthBoundID {
1095 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1096 voltDevice.ActiveChannelsPerPon.Delete(portID)
1097 }
1098 return false
1099 }
1100 return true
1101 }
1102 va.DevicesDisc.Range(delPort)
1103 return nil
1104}
1105
1106// GetNniPort : Get the NNI port for a device. Called from different other applications
1107// as a port to match or destination for a packet out. The VOLT application
1108// is written with the assumption that there is a single NNI port. The OLT
1109// device is responsible for translating the combination of VLAN and the
1110// NNI port ID to identify possibly a single physical port or a logical
1111// port which is a result of protection methods applied.
1112func (va *VoltApplication) GetNniPort(device string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301113 logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301114 va.portLock.Lock()
1115 defer va.portLock.Unlock()
1116 d, ok := va.DevicesDisc.Load(device)
1117 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301118 return "", errors.New("device doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301119 }
1120 return d.(*VoltDevice).NniPort, nil
1121}
1122
1123// NniDownInd process for Nni down indication.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301124func (va *VoltApplication) NniDownInd(cntx context.Context, deviceID string, devSrNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301125 logger.Debugw(ctx, "NNI Down Ind", log.Fields{"DeviceID": deviceID, "Device SrNo": devSrNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301126
1127 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1128 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129 mvProfile.removeIgmpMcastFlows(cntx, devSrNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301130 return true
1131 }
1132 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1133
1134 //Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301135 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301136}
1137
1138// DeviceUpInd changes device state to up.
1139func (va *VoltApplication) DeviceUpInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301140 logger.Infow(ctx, "Received Device Ind: UP", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301141 if d := va.GetDevice(device); d != nil {
1142 d.State = controller.DeviceStateUP
1143 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301144 logger.Warnw(ctx, "Ignoring Device indication: UP. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301145 }
1146}
1147
1148// DeviceDownInd changes device state to down.
1149func (va *VoltApplication) DeviceDownInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301150 logger.Infow(ctx, "Received Device Ind: DOWN", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301151 if d := va.GetDevice(device); d != nil {
1152 d.State = controller.DeviceStateDOWN
1153 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301154 logger.Warnw(ctx, "Ignoring Device indication: DOWN. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301155 }
1156}
1157
1158// DeviceRebootInd process for handling flow clear flag for device reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301159func (va *VoltApplication) DeviceRebootInd(cntx context.Context, device string, serialNum string, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301160 logger.Infow(ctx, "Received Device Ind: Reboot", log.Fields{"Device": device, "SerialNumber": serialNum, "SouthBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301161
1162 if d := va.GetDevice(device); d != nil {
1163 if d.State == controller.DeviceStateREBOOTED {
1164 logger.Warnw(ctx, "Ignoring Device Ind: Reboot, Device already in Reboot state", log.Fields{"Device": device, "SerialNumber": serialNum, "State": d.State})
1165 return
1166 }
1167 d.State = controller.DeviceStateREBOOTED
1168 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301169 va.HandleFlowClearFlag(cntx, device, serialNum, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301170}
1171
1172// DeviceDisableInd handles device deactivation process
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301173func (va *VoltApplication) DeviceDisableInd(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301174 logger.Infow(ctx, "Received Device Ind: Disable", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301175
1176 d := va.GetDevice(device)
1177 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301178 logger.Warnw(ctx, "Ignoring Device indication: DISABLED. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301179 return
1180 }
1181
1182 d.State = controller.DeviceStateDISABLED
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301183 va.HandleFlowClearFlag(cntx, device, d.SerialNum, d.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301184}
1185
1186// ProcessIgmpDSFlowForMvlan for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301187func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301188 logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
1189 portState := false
1190 p := d.GetPort(d.NniPort)
1191 if p != nil && p.State == PortStateUp {
1192 portState = true
1193 }
1194
1195 if addFlow {
1196 if portState {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301197 mvp.pushIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301198 }
1199 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301200 mvp.removeIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301201 }
1202}
1203
1204// ProcessIgmpDSFlowForDevice for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301205func (va *VoltApplication) ProcessIgmpDSFlowForDevice(cntx context.Context, d *VoltDevice, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301206 logger.Debugw(ctx, "Process IGMP DS Flows for device", log.Fields{"device": d.Name, "addFlow": addFlow})
1207
1208 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1209 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301210 va.ProcessIgmpDSFlowForMvlan(cntx, d, mvProfile, addFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301211 return true
1212 }
1213 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1214}
1215
1216// GetDeviceFromPort : This is suitable only for access ports as their naming convention
1217// makes them unique across all the OLTs. This must be called with
1218// port name that is an access port. Currently called from VNETs, attached
1219// only to access ports, and the services which are also attached only
1220// to access ports
1221func (va *VoltApplication) GetDeviceFromPort(port string) (*VoltDevice, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301222 logger.Debugw(ctx, "Received Get Device From Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301223 va.portLock.Lock()
1224 defer va.portLock.Unlock()
1225 var err error
1226 err = nil
1227 p, ok := va.PortsDisc.Load(port)
1228 if !ok {
1229 return nil, errorCodes.ErrPortNotFound
1230 }
1231 d := va.GetDevice(p.(*VoltPort).Device)
1232 if d == nil {
1233 err = errorCodes.ErrDeviceNotFound
1234 }
1235 return d, err
1236}
1237
1238// GetPortID : This too applies only to access ports. The ports can be indexed
1239// purely by their names without the device forming part of the key
1240func (va *VoltApplication) GetPortID(port string) (uint32, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301241 logger.Debugw(ctx, "Received Get Port ID", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301242 va.portLock.Lock()
1243 defer va.portLock.Unlock()
1244 p, ok := va.PortsDisc.Load(port)
1245 if !ok {
1246 return 0, errorCodes.ErrPortNotFound
1247 }
1248 return p.(*VoltPort).ID, nil
1249}
1250
1251// GetPortName : This too applies only to access ports. The ports can be indexed
1252// purely by their names without the device forming part of the key
1253func (va *VoltApplication) GetPortName(port uint32) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301254 logger.Debugw(ctx, "Received Get Port Name", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301255 va.portLock.Lock()
1256 defer va.portLock.Unlock()
1257 var portName string
1258 va.PortsDisc.Range(func(key interface{}, value interface{}) bool {
1259 portInfo := value.(*VoltPort)
1260 if portInfo.ID == port {
1261 portName = portInfo.Name
1262 return false
1263 }
1264 return true
1265 })
1266 return portName, nil
1267}
1268
1269// GetPonFromUniPort to get Pon info from UniPort
1270func (va *VoltApplication) GetPonFromUniPort(port string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301271 logger.Debugw(ctx, "Received Get Pon From UniPort", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301272 uniPortID, err := va.GetPortID(port)
1273 if err == nil {
1274 ponPortID := (uniPortID & 0x0FF00000) >> 20 //pon(8) + onu(8) + uni(12)
1275 return strconv.FormatUint(uint64(ponPortID), 10), nil
1276 }
1277 return "", err
1278}
1279
1280// GetPortState : This too applies only to access ports. The ports can be indexed
1281// purely by their names without the device forming part of the key
1282func (va *VoltApplication) GetPortState(port string) (PortState, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301283 logger.Debugw(ctx, "Received Get Port State", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301284 va.portLock.Lock()
1285 defer va.portLock.Unlock()
1286 p, ok := va.PortsDisc.Load(port)
1287 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301288 return 0, errors.New("port not configured")
Naveen Sampath04696f72022-06-13 15:19:14 +05301289 }
1290 return p.(*VoltPort).State, nil
1291}
1292
1293// GetIcmpv6Receivers to get Icmp v6 receivers
1294func (va *VoltApplication) GetIcmpv6Receivers(device string) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301295 logger.Debugw(ctx, "Get Icmpv6 Receivers", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301296 var receiverList []uint32
1297 receivers, _ := va.Icmpv6Receivers.Load(device)
1298 if receivers != nil {
1299 receiverList = receivers.([]uint32)
1300 }
1301 return receiverList
1302}
1303
1304// AddIcmpv6Receivers to add Icmp v6 receivers
1305func (va *VoltApplication) AddIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301306 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301307 var receiverList []uint32
1308 receivers, _ := va.Icmpv6Receivers.Load(device)
1309 if receivers != nil {
1310 receiverList = receivers.([]uint32)
1311 }
1312 receiverList = append(receiverList, portID)
1313 va.Icmpv6Receivers.Store(device, receiverList)
1314 logger.Debugw(ctx, "Receivers after addition", log.Fields{"Receivers": receiverList})
1315 return receiverList
1316}
1317
1318// DelIcmpv6Receivers to delete Icmp v6 receievers
1319func (va *VoltApplication) DelIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301320 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301321 var receiverList []uint32
1322 receivers, _ := va.Icmpv6Receivers.Load(device)
1323 if receivers != nil {
1324 receiverList = receivers.([]uint32)
1325 }
1326 for i, port := range receiverList {
1327 if port == portID {
1328 receiverList = append(receiverList[0:i], receiverList[i+1:]...)
1329 va.Icmpv6Receivers.Store(device, receiverList)
1330 break
1331 }
1332 }
1333 logger.Debugw(ctx, "Receivers After deletion", log.Fields{"Receivers": receiverList})
1334 return receiverList
1335}
1336
1337// ProcessDevFlowForDevice - Process DS ICMPv6 & ARP flow for provided device and vnet profile
1338// device - Device Obj
1339// vnet - vnet profile name
1340// enabled - vlan enabled/disabled - based on the status, the flow shall be added/removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301341func (va *VoltApplication) ProcessDevFlowForDevice(cntx context.Context, device *VoltDevice, vnet *VoltVnet, enabled bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301342 logger.Debugw(ctx, "Process Dev Flow For Device", log.Fields{"Device": device, "VnetName": vnet.Name, "Enabled": enabled})
Naveen Sampath04696f72022-06-13 15:19:14 +05301343 _, applied := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0))
1344 if enabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301345 va.PushDevFlowForVlan(cntx, vnet)
Naveen Sampath04696f72022-06-13 15:19:14 +05301346 } else if !enabled && applied {
1347 //va.DeleteDevFlowForVlan(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301348 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, device.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301349 }
1350}
1351
vinokuma926cb3e2023-03-29 11:41:06 +05301352// NniVlanIndToIgmp - Trigger receiver up indication to all ports with igmp enabled
1353// and has the provided mvlan
Naveen Sampath04696f72022-06-13 15:19:14 +05301354func (va *VoltApplication) NniVlanIndToIgmp(device *VoltDevice, mvp *MvlanProfile) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301355 logger.Infow(ctx, "Received Nni Vlan Ind To Igmp", log.Fields{"Vlan": mvp.Mvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301356
vinokuma926cb3e2023-03-29 11:41:06 +05301357 // Trigger nni indication for receiver only for first time
Naveen Sampath04696f72022-06-13 15:19:14 +05301358 if device.IgmpDsFlowAppliedForMvlan[uint16(mvp.Mvlan)] {
1359 return
1360 }
1361 device.Ports.Range(func(key, value interface{}) bool {
1362 port := key.(string)
1363
1364 if state, _ := va.GetPortState(port); state == PortStateUp {
1365 vpvs, _ := va.VnetsByPort.Load(port)
1366 if vpvs == nil {
1367 return true
1368 }
1369 for _, vpv := range vpvs.([]*VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05301370 // Send indication only for subscribers with the received mvlan profile
Naveen Sampath04696f72022-06-13 15:19:14 +05301371 if vpv.IgmpEnabled && vpv.MvlanProfileName == mvp.Name {
1372 vpv.services.Range(ReceiverUpInd)
1373 }
1374 }
1375 }
1376 return true
1377 })
1378}
1379
1380// PortUpInd :
1381// -----------------------------------------------------------------------
1382// Port status change handling
1383// ----------------------------------------------------------------------
1384// Port UP indication is passed to all services associated with the port
1385// so that the services can configure flows applicable when the port goes
1386// up from down state
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301387func (va *VoltApplication) PortUpInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301388 logger.Infow(ctx, "Received Southbound Port Ind: UP", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301389 d := va.GetDevice(device)
1390
1391 if d == nil {
1392 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: UP", log.Fields{"Device": device, "Port": port})
1393 return
1394 }
1395
vinokuma926cb3e2023-03-29 11:41:06 +05301396 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301397 va.portLock.Lock()
1398 // Do not defer the port mutex unlock here
1399 // Some of the following func calls needs the port lock, so defering the lock here
1400 // may lead to dead-lock
1401 p := d.GetPort(port)
1402
1403 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301404 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 +05301405 va.portLock.Unlock()
1406 return
1407 }
1408 p.State = PortStateUp
1409 va.portLock.Unlock()
1410
Naveen Sampath04696f72022-06-13 15:19:14 +05301411 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301412 logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301413 //va.PushDevFlowForDevice(d)
1414 //Build Igmp TrapFlowRule
1415 //va.ProcessIgmpDSFlowForDevice(d, true)
1416 }
1417 vpvs, ok := va.VnetsByPort.Load(port)
1418 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301419 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301420 //msgbus.ProcessPortInd(msgbus.PortUp, d.SerialNum, p.Name, false, getServiceList(port))
1421 return
1422 }
1423
vinokuma926cb3e2023-03-29 11:41:06 +05301424 // If NNI port is not UP, do not push Flows
Naveen Sampath04696f72022-06-13 15:19:14 +05301425 if d.NniPort == "" {
1426 logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
1427 return
1428 }
1429
Naveen Sampath04696f72022-06-13 15:19:14 +05301430 for _, vpv := range vpvs.([]*VoltPortVnet) {
1431 vpv.VpvLock.Lock()
vinokuma926cb3e2023-03-29 11:41:06 +05301432 // If no service is activated drop the portUpInd
Tinoj Josephec742f62022-09-29 19:11:10 +05301433 if vpv.IsServiceActivated(cntx) {
vinokuma926cb3e2023-03-29 11:41:06 +05301434 // Do not trigger indication for the vpv which is already removed from vpv list as
Tinoj Josephec742f62022-09-29 19:11:10 +05301435 // part of service delete (during the lock wait duration)
1436 // In that case, the services associated wil be zero
1437 if vpv.servicesCount.Load() != 0 {
1438 vpv.PortUpInd(cntx, d, port)
1439 }
1440 } else {
1441 // Service not activated, still attach device to service
1442 vpv.setDevice(d.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301443 }
1444 vpv.VpvLock.Unlock()
1445 }
1446 // At the end of processing inform the other entities that
1447 // are interested in the events
1448}
1449
1450/*
1451func getServiceList(port string) map[string]bool {
1452 serviceList := make(map[string]bool)
1453
1454 getServiceNames := func(key interface{}, value interface{}) bool {
1455 serviceList[key.(string)] = value.(*VoltService).DsHSIAFlowsApplied
1456 return true
1457 }
1458
1459 if vpvs, _ := GetApplication().VnetsByPort.Load(port); vpvs != nil {
1460 vpvList := vpvs.([]*VoltPortVnet)
1461 for _, vpv := range vpvList {
1462 vpv.services.Range(getServiceNames)
1463 }
1464 }
1465 return serviceList
1466
1467}*/
1468
vinokuma926cb3e2023-03-29 11:41:06 +05301469// ReceiverUpInd - Send receiver up indication for service with Igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301470func ReceiverUpInd(key, value interface{}) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301471 logger.Info(ctx, "Receiver Indication: UP")
Naveen Sampath04696f72022-06-13 15:19:14 +05301472 svc := value.(*VoltService)
1473 var vlan of.VlanType
1474
1475 if !svc.IPAssigned() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301476 logger.Warnw(ctx, "IP Not assigned, skipping general query", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +05301477 return false
1478 }
1479
vinokuma926cb3e2023-03-29 11:41:06 +05301480 // Send port up indication to igmp only for service with igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301481 if svc.IgmpEnabled {
1482 if svc.VlanControl == ONUCVlan || svc.VlanControl == ONUCVlanOLTSVlan {
1483 vlan = svc.CVlan
1484 } else {
1485 vlan = svc.UniVlan
1486 }
1487 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
1488 GetApplication().ReceiverUpInd(device.Name, svc.Port, svc.MvlanProfileName, vlan, svc.Pbits)
1489 }
1490 return false
1491 }
1492 return true
1493}
1494
1495// PortDownInd : Port down indication is passed on to the services so that the services
1496// can make changes at this transition.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301497func (va *VoltApplication) PortDownInd(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301498 logger.Infow(ctx, "Received SouthBound Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1499 d := va.GetDevice(device)
1500
1501 if d == nil {
1502 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1503 return
1504 }
vinokuma926cb3e2023-03-29 11:41:06 +05301505 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301506 va.portLock.Lock()
1507 // Do not defer the port mutex unlock here
1508 // Some of the following func calls needs the port lock, so defering the lock here
1509 // may lead to dead-lock
1510 p := d.GetPort(port)
1511 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301512 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 +05301513 va.portLock.Unlock()
1514 return
1515 }
1516 p.State = PortStateDown
1517 va.portLock.Unlock()
1518
1519 if d.State == controller.DeviceStateREBOOTED {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301520 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 +05301521 return
1522 }
1523
1524 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301525 logger.Debugw(ctx, "Received NNI Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301526 va.DeleteDevFlowForDevice(cntx, d)
1527 va.NniDownInd(cntx, device, d.SerialNum)
1528 va.RemovePendingGroups(cntx, device, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301529 }
1530 vpvs, ok := va.VnetsByPort.Load(port)
1531 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301532 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301533 //msgbus.ProcessPortInd(msgbus.PortDown, d.SerialNum, p.Name, false, getServiceList(port))
1534 return
1535 }
Akash Sonia8246972023-01-03 10:37:08 +05301536
Naveen Sampath04696f72022-06-13 15:19:14 +05301537 for _, vpv := range vpvs.([]*VoltPortVnet) {
1538 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301539 vpv.PortDownInd(cntx, device, port, false, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301540 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301541 va.ReceiverDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301542 }
1543 vpv.VpvLock.Unlock()
1544 }
1545}
1546
1547// PacketInInd :
1548// -----------------------------------------------------------------------
1549// PacketIn Processing
1550// Packet In Indication processing. It arrives with the identities of
1551// the device and port on which the packet is received. At first, the
1552// packet is decoded and the right processor is called. Currently, we
1553// plan to support only DHCP and IGMP. In future, we can add more
1554// capabilities as needed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301555func (va *VoltApplication) PacketInInd(cntx context.Context, device string, port string, pkt []byte) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301556 logger.Infow(ctx, "Received a Packet-In Indication", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301557 // Decode the incoming packet
1558 packetSide := US
1559 if strings.Contains(port, NNI) {
1560 packetSide = DS
1561 }
1562
Naveen Sampath04696f72022-06-13 15:19:14 +05301563 gopkt := gopacket.NewPacket(pkt, layers.LayerTypeEthernet, gopacket.Default)
1564
1565 var dot1qFound = false
1566 for _, l := range gopkt.Layers() {
1567 if l.LayerType() == layers.LayerTypeDot1Q {
1568 dot1qFound = true
1569 break
1570 }
1571 }
1572
1573 if !dot1qFound {
1574 logger.Debugw(ctx, "Ignoring Received Packet-In Indication without Dot1Q Header",
1575 log.Fields{"Device": device, "Port": port})
1576 return
1577 }
1578
1579 logger.Debugw(ctx, "Received Southbound Packet In", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1580
1581 // Classify the packet into packet types that we support
1582 // The supported types are DHCP and IGMP. The DHCP packet is
1583 // identified by matching the L4 protocol to UDP. The IGMP packet
1584 // is identified by matching L3 protocol to IGMP
1585 arpl := gopkt.Layer(layers.LayerTypeARP)
1586 if arpl != nil {
1587 if callBack, ok := PacketHandlers[ARP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301588 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301589 } else {
1590 logger.Debugw(ctx, "ARP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1591 }
1592 return
1593 }
1594 ipv4l := gopkt.Layer(layers.LayerTypeIPv4)
1595 if ipv4l != nil {
1596 ip := ipv4l.(*layers.IPv4)
1597
1598 if ip.Protocol == layers.IPProtocolUDP {
1599 logger.Debugw(ctx, "Received Southbound UDP ipv4 packet in", log.Fields{"StreamSide": packetSide})
1600 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv4)
1601 if dhcpl != nil {
1602 if callBack, ok := PacketHandlers[DHCPv4]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301603 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301604 } else {
1605 logger.Debugw(ctx, "DHCPv4 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1606 }
1607 }
1608 } else if ip.Protocol == layers.IPProtocolIGMP {
1609 logger.Debugw(ctx, "Received Southbound IGMP packet in", log.Fields{"StreamSide": packetSide})
1610 if callBack, ok := PacketHandlers[IGMP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301611 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301612 } else {
1613 logger.Debugw(ctx, "IGMP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1614 }
1615 }
1616 return
1617 }
1618 ipv6l := gopkt.Layer(layers.LayerTypeIPv6)
1619 if ipv6l != nil {
1620 ip := ipv6l.(*layers.IPv6)
1621 if ip.NextHeader == layers.IPProtocolUDP {
1622 logger.Debug(ctx, "Received Southbound UDP ipv6 packet in")
1623 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv6)
1624 if dhcpl != nil {
1625 if callBack, ok := PacketHandlers[DHCPv6]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301626 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301627 } else {
1628 logger.Debugw(ctx, "DHCPv6 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1629 }
1630 }
1631 }
1632 return
1633 }
1634
1635 pppoel := gopkt.Layer(layers.LayerTypePPPoE)
1636 if pppoel != nil {
1637 logger.Debugw(ctx, "Received Southbound PPPoE packet in", log.Fields{"StreamSide": packetSide})
1638 if callBack, ok := PacketHandlers[PPPOE]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301639 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301640 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301641 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 +05301642 }
1643 }
1644}
1645
1646// GetVlans : This utility gets the VLANs from the packet. The VLANs are
1647// used to identify the right service that must process the incoming
1648// packet
1649func GetVlans(pkt gopacket.Packet) []of.VlanType {
1650 var vlans []of.VlanType
1651 for _, l := range pkt.Layers() {
1652 if l.LayerType() == layers.LayerTypeDot1Q {
1653 q, ok := l.(*layers.Dot1Q)
1654 if ok {
1655 vlans = append(vlans, of.VlanType(q.VLANIdentifier))
1656 }
1657 }
1658 }
1659 return vlans
1660}
1661
1662// GetPriority to get priority
1663func GetPriority(pkt gopacket.Packet) uint8 {
1664 for _, l := range pkt.Layers() {
1665 if l.LayerType() == layers.LayerTypeDot1Q {
1666 q, ok := l.(*layers.Dot1Q)
1667 if ok {
1668 return q.Priority
1669 }
1670 }
1671 }
1672 return PriorityNone
1673}
1674
1675// HandleFlowClearFlag to handle flow clear flag during reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301676func (va *VoltApplication) HandleFlowClearFlag(cntx context.Context, deviceID string, serialNum, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301677 logger.Infow(ctx, "Clear All flags for Device", log.Fields{"Device": deviceID, "SerialNum": serialNum, "SBID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301678 dev, ok := va.DevicesDisc.Load(deviceID)
1679 if ok && dev != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301680 logger.Debugw(ctx, "Clear Flags for device", log.Fields{"voltDevice": dev.(*VoltDevice).Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301681 dev.(*VoltDevice).icmpv6GroupAdded = false
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301682 logger.Debugw(ctx, "Clearing DS Icmpv6 Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301683 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1684 dev.(*VoltDevice).ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301685 logger.Debugw(ctx, "Clearing DS IGMP Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301686 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1687 for k := range dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan {
1688 delete(dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan, k)
1689 }
vinokuma926cb3e2023-03-29 11:41:06 +05301690 // Delete group 1 - ICMPv6/ARP group
Naveen Sampath04696f72022-06-13 15:19:14 +05301691 if err := ProcessIcmpv6McGroup(deviceID, true); err != nil {
1692 logger.Errorw(ctx, "ProcessIcmpv6McGroup failed", log.Fields{"Device": deviceID, "Error": err})
1693 }
1694 } else {
1695 logger.Warnw(ctx, "VoltDevice not found for device ", log.Fields{"deviceID": deviceID})
1696 }
1697
1698 getVpvs := func(key interface{}, value interface{}) bool {
1699 vpvs := value.([]*VoltPortVnet)
1700 for _, vpv := range vpvs {
1701 if vpv.Device == deviceID {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301702 logger.Debugw(ctx, "Clear Flags for vpv",
Naveen Sampath04696f72022-06-13 15:19:14 +05301703 log.Fields{"device": vpv.Device, "port": vpv.Port,
1704 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301705 vpv.ClearAllServiceFlags(cntx)
1706 vpv.ClearAllVpvFlags(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301707
1708 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301709 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05301710 // Also clear service igmp stats
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301711 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301712 }
1713 }
1714 }
1715 return true
1716 }
1717 va.VnetsByPort.Range(getVpvs)
1718
vinokuma926cb3e2023-03-29 11:41:06 +05301719 // Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301720 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301721
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301722 logger.Infow(ctx, "All flags cleared for device", log.Fields{"Device": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301723
vinokuma926cb3e2023-03-29 11:41:06 +05301724 // Reset pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301725 va.RemovePendingGroups(cntx, deviceID, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301726
vinokuma926cb3e2023-03-29 11:41:06 +05301727 // Process all Migrate Service Request - force udpate all profiles since resources are already cleaned up
Naveen Sampath04696f72022-06-13 15:19:14 +05301728 if dev != nil {
1729 triggerForceUpdate := func(key, value interface{}) bool {
1730 msrList := value.(*util.ConcurrentMap)
1731 forceUpdateServices := func(key, value interface{}) bool {
1732 msr := value.(*MigrateServicesRequest)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301733 forceUpdateAllServices(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301734 return true
1735 }
1736 msrList.Range(forceUpdateServices)
1737 return true
1738 }
1739 dev.(*VoltDevice).MigratingServices.Range(triggerForceUpdate)
1740 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301741 va.FetchAndProcessAllMigrateServicesReq(cntx, deviceID, forceUpdateAllServices)
Naveen Sampath04696f72022-06-13 15:19:14 +05301742 }
1743}
1744
vinokuma926cb3e2023-03-29 11:41:06 +05301745// GetPonPortIDFromUNIPort to get pon port id from uni port
Naveen Sampath04696f72022-06-13 15:19:14 +05301746func GetPonPortIDFromUNIPort(uniPortID uint32) uint32 {
1747 ponPortID := (uniPortID & 0x0FF00000) >> 20
1748 return ponPortID
1749}
1750
vinokuma926cb3e2023-03-29 11:41:06 +05301751// ProcessFlowModResultIndication - Processes Flow mod operation indications from controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301752func (va *VoltApplication) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301753 logger.Debugw(ctx, "Received Flow Mod Result Indication.", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301754 d := va.GetDevice(flowStatus.Device)
1755 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301756 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 +05301757 return
1758 }
1759
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301760 cookieExists := ExecuteFlowEvent(cntx, d, flowStatus.Cookie, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +05301761
1762 if flowStatus.Flow != nil {
1763 flowAdd := (flowStatus.FlowModType == of.CommandAdd)
1764 if !cookieExists && !isFlowStatusSuccess(flowStatus.Status, flowAdd) {
1765 pushFlowFailureNotif(flowStatus)
1766 }
1767 }
1768}
1769
1770func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1771 subFlow := flowStatus.Flow
1772 cookie := subFlow.Cookie
1773 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301774 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301775}
1776
vinokuma926cb3e2023-03-29 11:41:06 +05301777// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301778func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301779 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301780 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1781 mvp := value.(*MvlanProfile)
1782 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301783 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301784 }
1785 return true
1786 }
1787 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1788}
1789
1790// TaskInfo structure that is used to store the task Info.
1791type TaskInfo struct {
1792 ID string
1793 Name string
1794 Timestamp string
1795}
1796
1797// GetTaskList to get task list information.
1798func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301799 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301800 taskList := cntlr.GetController().GetTaskList(device)
1801 taskMap := make(map[int]*TaskInfo)
1802 for i, task := range taskList {
1803 taskID := strconv.Itoa(int(task.TaskID()))
1804 name := task.Name()
1805 timestamp := task.Timestamp()
1806 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1807 taskMap[i] = taskInfo
1808 }
1809 return taskMap
1810}
1811
1812// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1813func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301814 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301815 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301816
1817 if voltDevice != nil {
1818 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301819 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 +05301820 } else {
1821 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301822 // Add Serial Number to Blocked Devices List.
1823 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1824 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1825
1826 updateSlNoForVnet := func(key, value interface{}) bool {
1827 vnet := value.(*VoltVnet)
1828 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1829 if deviceSlNo == oldOltSlNo {
1830 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1831 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1832 break
1833 }
1834 }
1835 return true
1836 }
1837
1838 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1839 mvProfile := value.(*MvlanProfile)
1840 for deviceSlNo := range mvProfile.DevicesList {
1841 if deviceSlNo == oldOltSlNo {
1842 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1843 delete(mvProfile.DevicesList, oldOltSlNo)
1844 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1845 break
1846 }
1847 }
1848 return true
1849 }
1850
1851 va.VnetsByName.Range(updateSlNoForVnet)
1852 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1853
1854 // Clear the serial number from Blocked Devices List
1855 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1856 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301857 }
1858}
1859
1860// GetVpvsForDsPkt to get vpv for downstream packets
1861func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1862 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301863 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301864 var matchVPVs []*VoltPortVnet
1865 findVpv := func(key, value interface{}) bool {
1866 vpvs := value.([]*VoltPortVnet)
1867 for _, vpv := range vpvs {
1868 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1869 var subMac net.HardwareAddr
1870 if NonZeroMacAddress(vpv.MacAddr) {
1871 subMac = vpv.MacAddr
1872 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
1873 subMac = vpv.LearntMacAddr
1874 } else {
1875 matchVPVs = append(matchVPVs, vpv)
1876 continue
1877 }
1878 if util.MacAddrsMatch(subMac, clientMAC) {
1879 matchVPVs = append([]*VoltPortVnet{}, vpv)
1880 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
1881 return false
1882 }
1883 }
1884 }
1885 return true
1886 }
1887 va.VnetsByPort.Range(findVpv)
1888
1889 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301890 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
1891 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301892 }
1893 return matchVPVs, nil
1894}
1895
1896// GetMacInPortMap to get PORT value based on MAC key
1897func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301898 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301899 if NonZeroMacAddress(macAddr) {
1900 va.macPortLock.Lock()
1901 defer va.macPortLock.Unlock()
1902 if port, ok := va.macPortMap[macAddr.String()]; ok {
1903 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1904 return port
1905 }
1906 }
1907 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
1908 return ""
1909}
1910
1911// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
1912func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301913 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301914 if NonZeroMacAddress(macAddr) {
1915 va.macPortLock.Lock()
1916 va.macPortMap[macAddr.String()] = port
1917 va.macPortLock.Unlock()
1918 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1919 }
1920}
1921
1922// DeleteMacInPortMap to remove MAC key from MacPortMap
1923func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301924 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301925 if NonZeroMacAddress(macAddr) {
1926 port := va.GetMacInPortMap(macAddr)
1927 va.macPortLock.Lock()
1928 delete(va.macPortMap, macAddr.String())
1929 va.macPortLock.Unlock()
1930 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1931 }
1932}
1933
vinokuma926cb3e2023-03-29 11:41:06 +05301934// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301935func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
1936 var grpMap map[*IgmpGroup]bool
1937 var ok bool
1938
1939 va.PendingPoolLock.Lock()
1940 defer va.PendingPoolLock.Unlock()
1941
1942 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
1943 // Do Not Reset any current profile info since group table entry tied to mvlan profile
1944 // The PonVlan is part of set field in group installed
1945 // Hence, Group created is always tied to the same mvlan profile until deleted
1946
1947 for device := range ig.Devices {
1948 key := getPendingPoolKey(ig.Mvlan, device)
1949
1950 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
1951 grpMap = make(map[*IgmpGroup]bool)
1952 }
1953 grpMap[ig] = true
1954
1955 //Add grpObj reference to all associated devices
1956 va.IgmpPendingPool[key] = grpMap
1957 }
1958}
1959
vinokuma926cb3e2023-03-29 11:41:06 +05301960// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301961func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
1962 GetApplication().PendingPoolLock.Lock()
1963 defer GetApplication().PendingPoolLock.Unlock()
1964
1965 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)})
1966
1967 key := getPendingPoolKey(ig.Mvlan, device)
1968 if _, ok := va.IgmpPendingPool[key]; ok {
1969 delete(va.IgmpPendingPool[key], ig)
1970 return true
1971 }
1972 return false
1973}
1974
vinokuma926cb3e2023-03-29 11:41:06 +05301975// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301976func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301977 GetApplication().PendingPoolLock.Lock()
1978 defer GetApplication().PendingPoolLock.Unlock()
1979
1980 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
1981
1982 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301983 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05301984}
1985
vinokuma926cb3e2023-03-29 11:41:06 +05301986// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05301987// 1. Deletes the group from device
1988// 2. Delete the IgmpGroup obj and release the group ID to pool
1989// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301990func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301991 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05301992 if grpMap, ok := va.IgmpPendingPool[key]; ok {
1993 delete(va.IgmpPendingPool, key)
1994 for ig := range grpMap {
1995 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301996 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301997 }
1998 }
1999 }
2000}
2001
vinokuma926cb3e2023-03-29 11:41:06 +05302002// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302003func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302004 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)})
2005 for device := range ig.PendingGroupForDevice {
2006 va.RemoveGroupFromPendingPool(device, ig)
2007 }
2008}
2009
vinokuma926cb3e2023-03-29 11:41:06 +05302010// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302011func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302012 var ig *IgmpGroup
2013
2014 va.PendingPoolLock.Lock()
2015 defer va.PendingPoolLock.Unlock()
2016
2017 key := getPendingPoolKey(mvlan, device)
2018 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2019
vinokuma926cb3e2023-03-29 11:41:06 +05302020 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302021 grpMap, ok := va.IgmpPendingPool[key]
2022 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302023 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 +05302024 return nil
2025 }
2026
vinokuma926cb3e2023-03-29 11:41:06 +05302027 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302028 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302029 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302030 for dev := range ig.Devices {
2031 key := getPendingPoolKey(mvlan, dev)
2032 delete(va.IgmpPendingPool[key], ig)
2033 }
2034
vinokuma926cb3e2023-03-29 11:41:06 +05302035 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302036 if ig.NumDevicesActive() == 0 {
2037 return ig
2038 }
2039
vinokuma926cb3e2023-03-29 11:41:06 +05302040 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302041 }
2042 return nil
2043}
2044
vinokuma926cb3e2023-03-29 11:41:06 +05302045// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302046// reference - mvlan/device ID
2047// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302048// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302049func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302050 va.PendingPoolLock.Lock()
2051 defer va.PendingPoolLock.Unlock()
2052
2053 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2054
vinokuma926cb3e2023-03-29 11:41:06 +05302055 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302056 paramPosition := 0
2057 if isRefDevice {
2058 paramPosition = 1
2059 }
2060
2061 // 1.Remove the Entry from pending pool
2062 // 2.Deletes the group from device
2063 // 3.Delete the IgmpGroup obj and release the group ID to pool
2064 for key := range va.IgmpPendingPool {
2065 keyParams := strings.Split(key, "_")
2066 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302067 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302068 }
2069 }
2070}
2071
2072func getPendingPoolKey(mvlan of.VlanType, device string) string {
2073 return mvlan.String() + "_" + device
2074}
2075
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302076func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302077 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302078 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2079 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302080 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302081 return true
2082 }
2083 va.IgmpGroups.Range(removeExpiredGroups)
2084}
2085
vinokuma926cb3e2023-03-29 11:41:06 +05302086// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302087func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302088 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302089 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302090 va.TriggerPendingServiceDeleteReq(cntx, device)
2091 va.TriggerPendingVpvDeleteReq(cntx, device)
2092 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302093 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302094}
2095
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302096// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2097func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
2098 logger.Infow(ctx, "Pending Services to be deactivated", log.Fields{"Count": len(va.ServicesToDeactivate)})
2099 for serviceName := range va.ServicesToDeactivate {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302100 logger.Debugw(ctx, "Trigger Service Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302101 if vs := va.GetService(serviceName); vs != nil {
2102 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302103 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302104 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2105 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302106 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302107 continue
2108 }
2109
2110 vpv.DelTrapFlows(cntx)
2111 vs.DelHsiaFlows(cntx)
2112 vs.WriteToDb(cntx)
2113 vpv.ClearServiceCounters(cntx)
2114 }
2115 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302116 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302117 }
2118 }
2119}
2120
vinokuma926cb3e2023-03-29 11:41:06 +05302121// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302122func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302123 logger.Infow(ctx, "Pending Services to be deleted", log.Fields{"Count": len(va.ServicesToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302124 for serviceName := range va.ServicesToDelete {
2125 logger.Debugw(ctx, "Trigger Service Delete", log.Fields{"Service": serviceName})
2126 if vs := va.GetService(serviceName); vs != nil {
2127 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302128 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302129 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302130 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302131 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302132 }
2133 }
2134 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302135 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302136 }
2137 }
2138}
2139
vinokuma926cb3e2023-03-29 11:41:06 +05302140// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302141func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302142 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302143 for vpv := range va.VoltPortVnetsToDelete {
2144 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302145 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 +05302146 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302147 }
2148 }
2149}
2150
vinokuma926cb3e2023-03-29 11:41:06 +05302151// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302152func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302153 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302154 for vnetName := range va.VnetsToDelete {
2155 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2156 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302157 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302158 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302159 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302160 va.deleteVnetConfig(vnet)
2161 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302162 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302163 }
2164 }
2165 }
2166}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302167
2168type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302169 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302170 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302171 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2172 EnableEapol bool `json:"enableEapol"`
2173 EnableDhcpV6 bool `json:"enableDhcpV6"`
2174 EnableDhcpV4 bool `json:"enableDhcpV4"`
2175 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302176}
2177
2178func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2179 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2180 va.OltFlowServiceConfig = oltFlowService
2181 b, err := json.Marshal(va.OltFlowServiceConfig)
2182 if err != nil {
2183 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2184 return
2185 }
2186 _ = db.PutOltFlowService(cntx, string(b))
2187}
Akash Sonia8246972023-01-03 10:37:08 +05302188
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302189// RestoreOltFlowService to read from the DB and restore olt flow service config
2190func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2191 oltflowService, err := db.GetOltFlowService(cntx)
2192 if err != nil {
2193 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2194 return
2195 }
2196 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2197 if err != nil {
2198 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2199 return
2200 }
2201 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2202}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302203
Akash Soni87a19072023-02-28 00:46:59 +05302204func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302205 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302206 var dc *DeviceConfig
2207 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2208 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2209 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302210 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302211 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302212 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302213 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302214 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302215 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302216 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302217 va.DevicesDisc.Store(id, device)
2218 }
2219}