blob: 371cd84791001b83db6bfdcbf8207c921f1f1b7a [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
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301770// IsFlowDelThresholdReached - check if the attempts for flow delete has reached threshold or not
1771func (va *VoltApplication) IsFlowDelThresholdReached(cntx context.Context, cookie string, device string) bool {
1772 logger.Debugw(ctx, "Check flow delete threshold", log.Fields{"Cookie": cookie, "Device": device})
1773 d := va.GetDevice(device)
1774 if d == nil {
1775 logger.Warnw(ctx, "Failed to get device during flow delete threshold check", log.Fields{"Cookie": cookie, "Device": device})
1776 return false
1777 }
1778
1779 flowEventMap, err := d.GetFlowEventRegister(of.CommandDel)
1780 if err != nil {
1781 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": of.CommandDel, "Error": err})
1782 return false
1783 }
1784 flowEventMap.MapLock.Lock()
1785 var event interface{}
1786 if event, _ = flowEventMap.Get(cookie); event == nil {
1787 logger.Warnw(ctx, "Event does not exist during flow delete threshold check", log.Fields{"Cookie": cookie})
1788 flowEventMap.MapLock.Unlock()
1789 return false
1790 }
1791 flowEventMap.MapLock.Unlock()
1792 flowEvent := event.(*FlowEvent)
1793 vs := flowEvent.eventData.(*VoltService)
1794 vs.ServiceLock.RLock()
1795 defer vs.ServiceLock.RUnlock()
1796 return vs.FlowPushCount[cookie] == controller.GetController().GetMaxFlowRetryAttempt()
1797}
1798
Naveen Sampath04696f72022-06-13 15:19:14 +05301799func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1800 subFlow := flowStatus.Flow
1801 cookie := subFlow.Cookie
1802 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301803 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301804}
1805
vinokuma926cb3e2023-03-29 11:41:06 +05301806// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301807func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301808 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301809 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1810 mvp := value.(*MvlanProfile)
1811 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301812 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301813 }
1814 return true
1815 }
1816 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1817}
1818
1819// TaskInfo structure that is used to store the task Info.
1820type TaskInfo struct {
1821 ID string
1822 Name string
1823 Timestamp string
1824}
1825
1826// GetTaskList to get task list information.
1827func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301828 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301829 taskList := cntlr.GetController().GetTaskList(device)
1830 taskMap := make(map[int]*TaskInfo)
1831 for i, task := range taskList {
1832 taskID := strconv.Itoa(int(task.TaskID()))
1833 name := task.Name()
1834 timestamp := task.Timestamp()
1835 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1836 taskMap[i] = taskInfo
1837 }
1838 return taskMap
1839}
1840
1841// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1842func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301843 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301844 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301845
1846 if voltDevice != nil {
1847 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301848 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 +05301849 } else {
1850 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301851 // Add Serial Number to Blocked Devices List.
1852 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1853 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1854
1855 updateSlNoForVnet := func(key, value interface{}) bool {
1856 vnet := value.(*VoltVnet)
1857 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1858 if deviceSlNo == oldOltSlNo {
1859 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1860 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1861 break
1862 }
1863 }
1864 return true
1865 }
1866
1867 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1868 mvProfile := value.(*MvlanProfile)
1869 for deviceSlNo := range mvProfile.DevicesList {
1870 if deviceSlNo == oldOltSlNo {
1871 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1872 delete(mvProfile.DevicesList, oldOltSlNo)
1873 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1874 break
1875 }
1876 }
1877 return true
1878 }
1879
1880 va.VnetsByName.Range(updateSlNoForVnet)
1881 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1882
1883 // Clear the serial number from Blocked Devices List
1884 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1885 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301886 }
1887}
1888
1889// GetVpvsForDsPkt to get vpv for downstream packets
1890func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1891 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301892 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301893 var matchVPVs []*VoltPortVnet
1894 findVpv := func(key, value interface{}) bool {
1895 vpvs := value.([]*VoltPortVnet)
1896 for _, vpv := range vpvs {
1897 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1898 var subMac net.HardwareAddr
1899 if NonZeroMacAddress(vpv.MacAddr) {
1900 subMac = vpv.MacAddr
1901 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
1902 subMac = vpv.LearntMacAddr
1903 } else {
1904 matchVPVs = append(matchVPVs, vpv)
1905 continue
1906 }
1907 if util.MacAddrsMatch(subMac, clientMAC) {
1908 matchVPVs = append([]*VoltPortVnet{}, vpv)
1909 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
1910 return false
1911 }
1912 }
1913 }
1914 return true
1915 }
1916 va.VnetsByPort.Range(findVpv)
1917
1918 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301919 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
1920 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301921 }
1922 return matchVPVs, nil
1923}
1924
1925// GetMacInPortMap to get PORT value based on MAC key
1926func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301927 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301928 if NonZeroMacAddress(macAddr) {
1929 va.macPortLock.Lock()
1930 defer va.macPortLock.Unlock()
1931 if port, ok := va.macPortMap[macAddr.String()]; ok {
1932 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1933 return port
1934 }
1935 }
1936 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
1937 return ""
1938}
1939
1940// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
1941func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301942 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301943 if NonZeroMacAddress(macAddr) {
1944 va.macPortLock.Lock()
1945 va.macPortMap[macAddr.String()] = port
1946 va.macPortLock.Unlock()
1947 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1948 }
1949}
1950
1951// DeleteMacInPortMap to remove MAC key from MacPortMap
1952func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301953 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301954 if NonZeroMacAddress(macAddr) {
1955 port := va.GetMacInPortMap(macAddr)
1956 va.macPortLock.Lock()
1957 delete(va.macPortMap, macAddr.String())
1958 va.macPortLock.Unlock()
1959 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1960 }
1961}
1962
vinokuma926cb3e2023-03-29 11:41:06 +05301963// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301964func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
1965 var grpMap map[*IgmpGroup]bool
1966 var ok bool
1967
1968 va.PendingPoolLock.Lock()
1969 defer va.PendingPoolLock.Unlock()
1970
1971 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
1972 // Do Not Reset any current profile info since group table entry tied to mvlan profile
1973 // The PonVlan is part of set field in group installed
1974 // Hence, Group created is always tied to the same mvlan profile until deleted
1975
1976 for device := range ig.Devices {
1977 key := getPendingPoolKey(ig.Mvlan, device)
1978
1979 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
1980 grpMap = make(map[*IgmpGroup]bool)
1981 }
1982 grpMap[ig] = true
1983
1984 //Add grpObj reference to all associated devices
1985 va.IgmpPendingPool[key] = grpMap
1986 }
1987}
1988
vinokuma926cb3e2023-03-29 11:41:06 +05301989// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301990func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
1991 GetApplication().PendingPoolLock.Lock()
1992 defer GetApplication().PendingPoolLock.Unlock()
1993
1994 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)})
1995
1996 key := getPendingPoolKey(ig.Mvlan, device)
1997 if _, ok := va.IgmpPendingPool[key]; ok {
1998 delete(va.IgmpPendingPool[key], ig)
1999 return true
2000 }
2001 return false
2002}
2003
vinokuma926cb3e2023-03-29 11:41:06 +05302004// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302005func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302006 GetApplication().PendingPoolLock.Lock()
2007 defer GetApplication().PendingPoolLock.Unlock()
2008
2009 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
2010
2011 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302012 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302013}
2014
vinokuma926cb3e2023-03-29 11:41:06 +05302015// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05302016// 1. Deletes the group from device
2017// 2. Delete the IgmpGroup obj and release the group ID to pool
2018// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302019func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302020 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05302021 if grpMap, ok := va.IgmpPendingPool[key]; ok {
2022 delete(va.IgmpPendingPool, key)
2023 for ig := range grpMap {
2024 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302025 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302026 }
2027 }
2028 }
2029}
2030
vinokuma926cb3e2023-03-29 11:41:06 +05302031// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302032func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302033 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)})
2034 for device := range ig.PendingGroupForDevice {
2035 va.RemoveGroupFromPendingPool(device, ig)
2036 }
2037}
2038
vinokuma926cb3e2023-03-29 11:41:06 +05302039// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302040func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302041 var ig *IgmpGroup
2042
2043 va.PendingPoolLock.Lock()
2044 defer va.PendingPoolLock.Unlock()
2045
2046 key := getPendingPoolKey(mvlan, device)
2047 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2048
vinokuma926cb3e2023-03-29 11:41:06 +05302049 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302050 grpMap, ok := va.IgmpPendingPool[key]
2051 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302052 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 +05302053 return nil
2054 }
2055
vinokuma926cb3e2023-03-29 11:41:06 +05302056 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302057 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302058 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302059 for dev := range ig.Devices {
2060 key := getPendingPoolKey(mvlan, dev)
2061 delete(va.IgmpPendingPool[key], ig)
2062 }
2063
vinokuma926cb3e2023-03-29 11:41:06 +05302064 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302065 if ig.NumDevicesActive() == 0 {
2066 return ig
2067 }
2068
vinokuma926cb3e2023-03-29 11:41:06 +05302069 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302070 }
2071 return nil
2072}
2073
vinokuma926cb3e2023-03-29 11:41:06 +05302074// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302075// reference - mvlan/device ID
2076// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302077// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302078func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302079 va.PendingPoolLock.Lock()
2080 defer va.PendingPoolLock.Unlock()
2081
2082 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2083
vinokuma926cb3e2023-03-29 11:41:06 +05302084 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302085 paramPosition := 0
2086 if isRefDevice {
2087 paramPosition = 1
2088 }
2089
2090 // 1.Remove the Entry from pending pool
2091 // 2.Deletes the group from device
2092 // 3.Delete the IgmpGroup obj and release the group ID to pool
2093 for key := range va.IgmpPendingPool {
2094 keyParams := strings.Split(key, "_")
2095 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302096 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302097 }
2098 }
2099}
2100
2101func getPendingPoolKey(mvlan of.VlanType, device string) string {
2102 return mvlan.String() + "_" + device
2103}
2104
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302105func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302106 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302107 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2108 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302109 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302110 return true
2111 }
2112 va.IgmpGroups.Range(removeExpiredGroups)
2113}
2114
vinokuma926cb3e2023-03-29 11:41:06 +05302115// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302116func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302117 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302118 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302119 va.TriggerPendingServiceDeleteReq(cntx, device)
2120 va.TriggerPendingVpvDeleteReq(cntx, device)
2121 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302122 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302123}
2124
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302125// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2126func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
2127 logger.Infow(ctx, "Pending Services to be deactivated", log.Fields{"Count": len(va.ServicesToDeactivate)})
2128 for serviceName := range va.ServicesToDeactivate {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302129 logger.Debugw(ctx, "Trigger Service Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302130 if vs := va.GetService(serviceName); vs != nil {
2131 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302132 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302133 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2134 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302135 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 +05302136 continue
2137 }
2138
2139 vpv.DelTrapFlows(cntx)
2140 vs.DelHsiaFlows(cntx)
2141 vs.WriteToDb(cntx)
2142 vpv.ClearServiceCounters(cntx)
2143 }
2144 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302145 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302146 }
2147 }
2148}
2149
vinokuma926cb3e2023-03-29 11:41:06 +05302150// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302151func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302152 logger.Infow(ctx, "Pending Services to be deleted", log.Fields{"Count": len(va.ServicesToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302153 for serviceName := range va.ServicesToDelete {
2154 logger.Debugw(ctx, "Trigger Service Delete", log.Fields{"Service": serviceName})
2155 if vs := va.GetService(serviceName); vs != nil {
2156 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302157 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302158 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302159 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302160 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302161 }
2162 }
2163 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302164 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302165 }
2166 }
2167}
2168
vinokuma926cb3e2023-03-29 11:41:06 +05302169// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302170func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302171 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302172 for vpv := range va.VoltPortVnetsToDelete {
2173 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302174 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 +05302175 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302176 }
2177 }
2178}
2179
vinokuma926cb3e2023-03-29 11:41:06 +05302180// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302181func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302182 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302183 for vnetName := range va.VnetsToDelete {
2184 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2185 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302186 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302187 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302188 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302189 va.deleteVnetConfig(vnet)
2190 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302191 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302192 }
2193 }
2194 }
2195}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302196
2197type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302198 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302199 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302200 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2201 EnableEapol bool `json:"enableEapol"`
2202 EnableDhcpV6 bool `json:"enableDhcpV6"`
2203 EnableDhcpV4 bool `json:"enableDhcpV4"`
2204 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302205}
2206
2207func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2208 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2209 va.OltFlowServiceConfig = oltFlowService
2210 b, err := json.Marshal(va.OltFlowServiceConfig)
2211 if err != nil {
2212 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2213 return
2214 }
2215 _ = db.PutOltFlowService(cntx, string(b))
2216}
Akash Sonia8246972023-01-03 10:37:08 +05302217
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302218// RestoreOltFlowService to read from the DB and restore olt flow service config
2219func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2220 oltflowService, err := db.GetOltFlowService(cntx)
2221 if err != nil {
2222 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2223 return
2224 }
2225 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2226 if err != nil {
2227 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2228 return
2229 }
2230 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2231}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302232
Akash Soni87a19072023-02-28 00:46:59 +05302233func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302234 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302235 var dc *DeviceConfig
2236 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2237 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2238 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302239 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302240 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302241 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302242 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302243 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302244 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302245 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302246 va.DevicesDisc.Store(id, device)
2247 }
2248}