blob: c87e419df7ce221f38293e06999b3d5442600318 [file] [log] [blame]
Joey Armstrongaca03cf2024-04-23 09:29:52 -04001/* -----------------------------------------------------------------------
2 * Copyright 2022-2024 Open Networking Foundation Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * -----------------------------------------------------------------------
16 * SPDX-FileCopyrightText: 2022-2024 Open Networking Foundation Contributors
17 * SPDX-License-Identifier: Apache-2.0
18 * -----------------------------------------------------------------------
Naveen Sampath04696f72022-06-13 15:19:14 +053019 */
20
21package application
22
23import (
24 "context"
25 "encoding/hex"
26 "encoding/json"
27 "errors"
28 "fmt"
29 "net"
30 "strconv"
31 "strings"
32 "sync"
33 "time"
34
35 "github.com/google/gopacket"
36 "github.com/google/gopacket/layers"
37
Akash Sonia8246972023-01-03 10:37:08 +053038 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053039 "voltha-go-controller/internal/pkg/controller"
40 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053041 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053042 "voltha-go-controller/internal/pkg/intf"
43 "voltha-go-controller/internal/pkg/of"
44 "voltha-go-controller/internal/pkg/tasks"
Akash Soni6f369452023-09-19 11:18:28 +053045 common "voltha-go-controller/internal/pkg/types"
Naveen Sampath04696f72022-06-13 15:19:14 +053046 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053047 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053048)
49
50var logger log.CLogger
51var ctx = context.TODO()
52
53func init() {
54 // Setup this package so that it's log level can be modified at run time
55 var err error
Tinoj Joseph1d108322022-07-13 10:07:39 +053056 logger, err = log.AddPackageWithDefaultParam()
Naveen Sampath04696f72022-06-13 15:19:14 +053057 if err != nil {
58 panic(err)
59 }
60}
61
62const (
63 // TODO - Need to identify a right place for this
64
65 // PriorityNone constant.
66 PriorityNone uint8 = 8
67 // AnyVlan constant.
68 AnyVlan uint16 = 0xFFFF
69)
70
71// List of Mac Learning Type
72const (
Tinoj Joseph1d108322022-07-13 10:07:39 +053073 MacLearningNone MacLearningType = iota
74 Learn
75 ReLearn
Naveen Sampath04696f72022-06-13 15:19:14 +053076)
77
78// MacLearningType represents Mac Learning Type
79type MacLearningType int
80
81var (
82 tickCount uint16
83 vgcRebooted bool
84 isUpgradeComplete bool
85)
86
87var db database.DBIntf
88
89// PacketHandlers : packet handler for different protocols
90var PacketHandlers map[string]CallBack
91
92// CallBack : registered call back function for different protocol packets
Tinoj Joseph07cc5372022-07-18 22:53:51 +053093type CallBack func(cntx context.Context, device string, port string, pkt gopacket.Packet)
Naveen Sampath04696f72022-06-13 15:19:14 +053094
95const (
96 // ARP packet
97 ARP string = "ARP"
98 // DHCPv4 packet
99 DHCPv4 string = "DHCPv4"
100 // DHCPv6 packet
101 DHCPv6 string = "DHCPv6"
102 // IGMP packet
103 IGMP string = "IGMP"
104 // PPPOE packet
105 PPPOE string = "PPPOE"
106 // US packet side
107 US string = "US"
108 // DS packet side
109 DS string = "DS"
110 // NNI port name
111 NNI string = "nni"
112)
113
114// RegisterPacketHandler : API to register callback function for every protocol
115func RegisterPacketHandler(protocol string, callback CallBack) {
116 if PacketHandlers == nil {
117 PacketHandlers = make(map[string]CallBack)
118 }
119 PacketHandlers[protocol] = callback
120}
121
122// ---------------------------------------------------------------------
123// VOLT Ports
124// ---------------------------------------------------------------------
125// VOLT Ports are ports associated with VOLT devices. Each port is classified into
126// Access/NNI. Each port is identified by Name (Identity known to the NB) and
127// Id (Identity used on the SB). Both identities are presented when a port is
128// discovered in the SB.
129
130// VoltPortType type for Port Type
131type VoltPortType uint8
132
133const (
134 // VoltPortTypeAccess constant.
135 VoltPortTypeAccess VoltPortType = 0
136 // VoltPortTypeNni constant.
137 VoltPortTypeNni VoltPortType = 1
138)
139
140// PortState type for Port State.
141type PortState uint8
142
143const (
144 // PortStateDown constant.
145 PortStateDown PortState = 0
146 // PortStateUp constant.
147 PortStateUp PortState = 1
148)
149
150// VoltPort structure that is used to store the ports. The name is the
151// the main identity used by the application. The SB and NB both present name
152// as the identity. The SB is abstracted by VPAgent and the VPAgent transacts
153// using name as identity
154type VoltPort struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530155 Name string
156 Device string
157 PonPort uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530158 ActiveChannels uint32
159 ID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530160 Type VoltPortType
161 State PortState
Naveen Sampath04696f72022-06-13 15:19:14 +0530162 ChannelPerSubAlarmRaised bool
163}
164
165// NewVoltPort : Constructor for the port.
166func NewVoltPort(device string, name string, id uint32) *VoltPort {
167 var vp VoltPort
168 vp.Device = device
169 vp.Name = name
170 vp.ID = id
171 if util.IsNniPort(id) {
172 vp.Type = VoltPortTypeNni
173 } else {
174 vp.PonPort = GetPonPortIDFromUNIPort(id)
175 }
176 vp.State = PortStateDown
177 vp.ChannelPerSubAlarmRaised = false
178 return &vp
179}
180
181// SetPortID : The ID is used when constructing flows as the flows require ID.
182func (vp *VoltPort) SetPortID(id uint32) {
183 vp.ID = id
184 if util.IsNniPort(id) {
185 vp.Type = VoltPortTypeNni
186 }
187}
188
189// ---------------------------------------------------------------------
190// VOLT Device
191// ---------------------------------------------------------------------
192//
193// VoltDevice is an OLT which contains ports of type access and NNI. Each OLT
194// can only have one NNI port in the current release. The NNI port always uses
195// identity 65536 and all the access ports use identities less than 65535. The
196// identification of NNI is done by comparing the port identity with 65535
197
198// VoltDevice fields :
199// Name: This is the name presented by the device/VOLTHA. This doesn't
vinokuma926cb3e2023-03-29 11:41:06 +0530200// have any relation to the physical device
Naveen Sampath04696f72022-06-13 15:19:14 +0530201// SerialNum: This is the serial number of the device and can be used to
vinokuma926cb3e2023-03-29 11:41:06 +0530202// correlate the devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530203// NniPort: The identity of the NNI port
204// Ports: List of all ports added to the device
205type VoltDevice struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530206 FlowAddEventMap *util.ConcurrentMap //map[string]*FlowEvent
207 FlowDelEventMap *util.ConcurrentMap //map[string]*FlowEvent
208 MigratingServices *util.ConcurrentMap //<vnetID,<RequestID, MigrateServicesRequest>>
vinokuma926cb3e2023-03-29 11:41:06 +0530209 VpvsBySvlan *util.ConcurrentMap // map[svlan]map[vnet_port]*VoltPortVnet
210 ConfiguredVlanForDeviceFlows *util.ConcurrentMap //map[string]map[string]bool
211 IgmpDsFlowAppliedForMvlan map[uint16]bool
212 State controller.DeviceState
213 SouthBoundID string
214 NniPort string
215 Name string
216 SerialNum string
217 Ports sync.Map
218 VlanPortStatus sync.Map
219 ActiveChannelsPerPon sync.Map // [PonPortID]*PonPortCfg
220 PonPortList sync.Map // [PonPortID]map[string]string
221 ActiveChannelCountLock sync.Mutex // This lock is used to update ActiveIGMPChannels
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530222 NniDhcpTrapVid of.VlanType
vinokuma926cb3e2023-03-29 11:41:06 +0530223 GlobalDhcpFlowAdded bool
224 icmpv6GroupAdded bool
Akash Soni6f369452023-09-19 11:18:28 +0530225 VoltDeviceIntr VoltDevInterface
226}
227
228type VoltDevInterface interface {
229 GetPortNameFromPortID(portID uint32) string
Naveen Sampath04696f72022-06-13 15:19:14 +0530230}
231
232// NewVoltDevice : Constructor for the device
233func NewVoltDevice(name string, slno, southBoundID string) *VoltDevice {
234 var d VoltDevice
235 d.Name = name
236 d.SouthBoundID = southBoundID
237 d.State = controller.DeviceStateDOWN
238 d.NniPort = ""
239 d.SouthBoundID = southBoundID
240 d.SerialNum = slno
241 d.icmpv6GroupAdded = false
242 d.IgmpDsFlowAppliedForMvlan = make(map[uint16]bool)
243 d.ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
244 d.MigratingServices = util.NewConcurrentMap()
245 d.VpvsBySvlan = util.NewConcurrentMap()
246 d.FlowAddEventMap = util.NewConcurrentMap()
247 d.FlowDelEventMap = util.NewConcurrentMap()
248 d.GlobalDhcpFlowAdded = false
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530249 if config, ok := GetApplication().DevicesConfig.Load(slno); ok {
250 //Update nni dhcp vid
Akash Soni53da2852023-03-15 00:31:31 +0530251 deviceConfig := config.(*DeviceConfig)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530252 d.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
253 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530254 return &d
255}
256
vinokuma926cb3e2023-03-29 11:41:06 +0530257// GetAssociatedVpvsForDevice - return the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530258func (va *VoltApplication) GetAssociatedVpvsForDevice(device string, svlan of.VlanType) *util.ConcurrentMap {
259 if d := va.GetDevice(device); d != nil {
260 return d.GetAssociatedVpvs(svlan)
261 }
262 return nil
263}
264
vinokuma926cb3e2023-03-29 11:41:06 +0530265// AssociateVpvsToDevice - updates the associated VPVs for given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530266func (va *VoltApplication) AssociateVpvsToDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530267 logger.Debugw(ctx, "AssociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530268 if d := va.GetDevice(device); d != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530269 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
270 vpvMap.Set(vpv, true)
271 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530272 logger.Debugw(ctx, "VPVMap: SET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530273 return
274 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530275 logger.Warnw(ctx, "Set VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530276}
277
vinokuma926cb3e2023-03-29 11:41:06 +0530278// DisassociateVpvsFromDevice - disassociated VPVs from given device & svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530279func (va *VoltApplication) DisassociateVpvsFromDevice(device string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530280 logger.Debugw(ctx, "DisassociateVpvsToDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530281 if d := va.GetDevice(device); d != nil {
282 vpvMap := d.GetAssociatedVpvs(vpv.SVlan)
283 vpvMap.Remove(vpv)
284 d.VpvsBySvlan.Set(vpv.SVlan, vpvMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530285 logger.Debugw(ctx, "VPVMap: Remove", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530286 return
287 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530288 logger.Warnw(ctx, "Remove VPVMap failed: Device Not Found", log.Fields{"Svlan": vpv.SVlan, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530289}
290
vinokuma926cb3e2023-03-29 11:41:06 +0530291// GetAssociatedVpvs - returns the associated VPVs for the given Svlan
Naveen Sampath04696f72022-06-13 15:19:14 +0530292func (d *VoltDevice) GetAssociatedVpvs(svlan of.VlanType) *util.ConcurrentMap {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530293 logger.Debugw(ctx, "Received Get Associated Vpvs", log.Fields{"svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530294 var vpvMap *util.ConcurrentMap
295 var mapIntf interface{}
296 var ok bool
297
298 if mapIntf, ok = d.VpvsBySvlan.Get(svlan); ok {
299 vpvMap = mapIntf.(*util.ConcurrentMap)
300 } else {
301 vpvMap = util.NewConcurrentMap()
302 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530303 logger.Debugw(ctx, "VPVMap: GET", log.Fields{"Map": vpvMap.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530304 return vpvMap
305}
306
307// AddPort add port to the device.
308func (d *VoltDevice) AddPort(port string, id uint32) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530309 logger.Debugw(ctx, "Add Port", log.Fields{"Port": port, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530310 addPonPortFromUniPort := func(vPort *VoltPort) {
311 if vPort.Type == VoltPortTypeAccess {
312 ponPortID := GetPonPortIDFromUNIPort(vPort.ID)
313
314 if ponPortUniList, ok := d.PonPortList.Load(ponPortID); !ok {
315 uniList := make(map[string]uint32)
316 uniList[port] = vPort.ID
317 d.PonPortList.Store(ponPortID, uniList)
318 } else {
319 ponPortUniList.(map[string]uint32)[port] = vPort.ID
320 d.PonPortList.Store(ponPortID, ponPortUniList)
321 }
322 }
323 }
324 va := GetApplication()
325 if pIntf, ok := d.Ports.Load(port); ok {
326 voltPort := pIntf.(*VoltPort)
327 addPonPortFromUniPort(voltPort)
328 va.AggActiveChannelsCountPerSub(d.Name, port, voltPort)
329 d.Ports.Store(port, voltPort)
330 return voltPort
331 }
332 p := NewVoltPort(d.Name, port, id)
333 va.AggActiveChannelsCountPerSub(d.Name, port, p)
334 d.Ports.Store(port, p)
335 if util.IsNniPort(id) {
336 d.NniPort = port
337 }
338 addPonPortFromUniPort(p)
339 return p
340}
341
342// GetPort to get port information from the device.
343func (d *VoltDevice) GetPort(port string) *VoltPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530344 logger.Debugw(ctx, "Get Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530345 if pIntf, ok := d.Ports.Load(port); ok {
346 return pIntf.(*VoltPort)
347 }
348 return nil
349}
350
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530351// GetPortByPortID to get port information from the device.
352func (d *VoltDevice) GetPortNameFromPortID(portID uint32) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530353 logger.Debugw(ctx, "Get Port Name from the device", log.Fields{"PortID": portID})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530354 portName := ""
355 d.Ports.Range(func(key, value interface{}) bool {
356 vp := value.(*VoltPort)
357 if vp.ID == portID {
358 portName = vp.Name
359 }
360 return true
361 })
362 return portName
363}
364
Naveen Sampath04696f72022-06-13 15:19:14 +0530365// DelPort to delete port from the device
366func (d *VoltDevice) DelPort(port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530367 logger.Debugw(ctx, "Delete Port from the device", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530368 if _, ok := d.Ports.Load(port); ok {
369 d.Ports.Delete(port)
370 } else {
371 logger.Warnw(ctx, "Port doesn't exist", log.Fields{"Device": d.Name, "Port": port})
372 }
373}
374
375// pushFlowsForUnis to send port-up-indication for uni ports.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530376func (d *VoltDevice) pushFlowsForUnis(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530377 logger.Info(ctx, "NNI Discovered, Sending Port UP Ind for UNIs")
378 d.Ports.Range(func(key, value interface{}) bool {
379 port := key.(string)
380 vp := value.(*VoltPort)
381
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530382 logger.Debugw(ctx, "NNI Discovered. Sending Port UP Ind for UNI", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530383 //Ignore if UNI port is not UP
384 if vp.State != PortStateUp {
385 return true
386 }
387
388 //Obtain all VPVs associated with the port
389 vnets, ok := GetApplication().VnetsByPort.Load(port)
390 if !ok {
391 return true
392 }
393
394 for _, vpv := range vnets.([]*VoltPortVnet) {
395 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530396 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530397 vpv.VpvLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +0530398 }
399 return true
400 })
401}
402
403// ----------------------------------------------------------
404// VOLT Application - hosts all other objects
405// ----------------------------------------------------------
406//
407// The VOLT application is a singleton implementation where
408// there is just one instance in the system and is the gateway
409// to all other components within the controller
410// The declaration of the singleton object
411var vapplication *VoltApplication
412
Akash Soni6f369452023-09-19 11:18:28 +0530413type VoltAppInterface interface {
414 AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error
415 AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error
416 AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error
417 GetFlowProvisionStatus(portNo string) FlowProvisionStatus
418 DelServiceWithPrefix(cntx context.Context, prefix string) error
419 GetDevice(device string) *VoltDevice
420 GetTaskList(device string) map[int]*TaskInfo
421 AddMeterProf(cntx context.Context, cfg VoltMeter)
422 AddMvlanProfile(cntx context.Context, name string, mvlan of.VlanType, ponVlan of.VlanType, groups map[string][]string, isChannelBasedGroup bool, OLTSerialNum []string, activeChannelsPerPon int, proxy map[string]common.MulticastGroupProxy) error
423 DelMvlanProfile(cntx context.Context, name string) error
424 GetMvlanProfileByTag(vlan of.VlanType) *MvlanProfile
425 AddMcastConfig(cntx context.Context, MvlanProfileID string, IgmpProfileID string, IgmpProxyIP string, OltSerialNum string) error
426 DelMeterProf(cntx context.Context, name string) error
427 GetMeterByName(name string) (*VoltMeter, bool)
428 UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig)
429 GetDeviceConfig(serNum string) *DeviceConfig
430 GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error)
431 GetAllMacLearnerInfo() ([]MacLearnerInfo, error)
432 GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error)
433 ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
434 DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error
435 GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error)
436 UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService)
437 GetIgnoredPorts() (map[string][]string, error)
438}
439
Naveen Sampath04696f72022-06-13 15:19:14 +0530440// VoltApplication fields :
441// ServiceByName - Stores the services by the name as key
vinokuma926cb3e2023-03-29 11:41:06 +0530442// A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530443// VnetsByPort - Stores the VNETs by the ports configured
vinokuma926cb3e2023-03-29 11:41:06 +0530444// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530445// VnetsByTag - Stores the VNETs by the VLANS configured
vinokuma926cb3e2023-03-29 11:41:06 +0530446// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530447// VnetsByName - Stores the VNETs by the name configured
vinokuma926cb3e2023-03-29 11:41:06 +0530448// from NB. A record of NB configuration.
Naveen Sampath04696f72022-06-13 15:19:14 +0530449// DevicesDisc - Stores the devices discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530450// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530451// PortsDisc - Stores the ports discovered from SB.
vinokuma926cb3e2023-03-29 11:41:06 +0530452// Should be updated only by events from SB
Naveen Sampath04696f72022-06-13 15:19:14 +0530453type VoltApplication struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530454 MeterMgr
vinokuma926cb3e2023-03-29 11:41:06 +0530455 DataMigrationInfo DataMigration
456 VnetsBySvlan *util.ConcurrentMap
457 IgmpGroupIds []*IgmpGroup
458 VoltPortVnetsToDelete map[*VoltPortVnet]bool
Akash Sonia8246972023-01-03 10:37:08 +0530459 IgmpPendingPool map[string]map[*IgmpGroup]bool //[grpkey, map[groupObj]bool] //mvlan_grpName/IP
vinokuma926cb3e2023-03-29 11:41:06 +0530460 macPortMap map[string]string
Akash Sonia8246972023-01-03 10:37:08 +0530461 VnetsToDelete map[string]bool
462 ServicesToDelete map[string]bool
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530463 ServicesToDeactivate map[string]bool
Akash Sonia8246972023-01-03 10:37:08 +0530464 PortAlarmProfileCache map[string]map[string]int // [portAlarmID][ThresholdLevelString]ThresholdLevel
465 vendorID string
vinokuma926cb3e2023-03-29 11:41:06 +0530466 ServiceByName sync.Map // [serName]*VoltService
467 VnetsByPort sync.Map // [portName][]*VoltPortVnet
468 VnetsByTag sync.Map // [svlan-cvlan-uvlan]*VoltVnet
469 VnetsByName sync.Map // [vnetName]*VoltVnet
470 DevicesDisc sync.Map
471 PortsDisc sync.Map
472 IgmpGroups sync.Map // [grpKey]*IgmpGroup
473 MvlanProfilesByTag sync.Map
474 MvlanProfilesByName sync.Map
475 Icmpv6Receivers sync.Map
476 DeviceCounters sync.Map //[logicalDeviceId]*DeviceCounters
477 ServiceCounters sync.Map //[serviceName]*ServiceCounters
478 NbDevice sync.Map // [OLTSouthBoundID]*NbDevice
479 OltIgmpInfoBySerial sync.Map
480 McastConfigMap sync.Map //[OltSerialNo_MvlanProfileID]*McastConfig
Akash Sonia8246972023-01-03 10:37:08 +0530481 DevicesConfig sync.Map //[serialNumber]*DeviceConfig
vinokuma926cb3e2023-03-29 11:41:06 +0530482 IgmpProfilesByName sync.Map
483 IgmpTasks tasks.Tasks
484 IndicationsTasks tasks.Tasks
485 MulticastAlarmTasks tasks.Tasks
486 IgmpKPIsTasks tasks.Tasks
487 pppoeTasks tasks.Tasks
488 OltFlowServiceConfig OltFlowService
489 PendingPoolLock sync.RWMutex
490 // MacAddress-Port MAP to avoid swap of mac across ports.
491 macPortLock sync.RWMutex
492 portLock sync.Mutex
Akash Sonia8246972023-01-03 10:37:08 +0530493}
Naveen Sampath04696f72022-06-13 15:19:14 +0530494
Akash Sonia8246972023-01-03 10:37:08 +0530495type DeviceConfig struct {
496 SerialNumber string `json:"id"`
497 HardwareIdentifier string `json:"hardwareIdentifier"`
Akash Soni87a19072023-02-28 00:46:59 +0530498 IPAddress string `json:"ipAddress"`
Akash Soni53da2852023-03-15 00:31:31 +0530499 UplinkPort string `json:"uplinkPort"`
Akash Sonia8246972023-01-03 10:37:08 +0530500 NasID string `json:"nasId"`
501 NniDhcpTrapVid int `json:"nniDhcpTrapVid"`
Naveen Sampath04696f72022-06-13 15:19:14 +0530502}
503
504// PonPortCfg contains NB port config and activeIGMPChannels count
505type PonPortCfg struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530506 PortAlarmProfileID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530507 PortID uint32
508 MaxActiveChannels uint32
509 ActiveIGMPChannels uint32
510 EnableMulticastKPI bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530511}
512
513// NbDevice OLT Device info
514type NbDevice struct {
515 SouthBoundID string
516 PonPorts sync.Map // [PortID]*PonPortCfg
517}
518
519// RestoreNbDeviceFromDb restores the NB Device in case of VGC pod restart.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530520func (va *VoltApplication) RestoreNbDeviceFromDb(cntx context.Context, deviceID string) *NbDevice {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530521 logger.Debugw(ctx, "Received Restore Nb Device From Db", log.Fields{"deviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530522 nbDevice := NewNbDevice()
523 nbDevice.SouthBoundID = deviceID
524
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530525 nbPorts, _ := db.GetAllNbPorts(cntx, deviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530526
527 for key, p := range nbPorts {
528 b, ok := p.Value.([]byte)
529 if !ok {
530 logger.Warn(ctx, "The value type is not []byte")
531 continue
532 }
533 var port PonPortCfg
534 err := json.Unmarshal(b, &port)
535 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530536 logger.Warnw(ctx, "Unmarshal of PonPortCfg failed", log.Fields{"deviceID": deviceID, "port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530537 continue
538 }
539 logger.Debugw(ctx, "Port recovered", log.Fields{"port": port})
540 ponPortID, _ := strconv.Atoi(key)
541 nbDevice.PonPorts.Store(uint32(ponPortID), &port)
542 }
543 va.NbDevice.Store(deviceID, nbDevice)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530544 logger.Debugw(ctx, "Recovered NbDevice From Db", log.Fields{"deviceID": deviceID, "nbDevice": nbDevice})
Naveen Sampath04696f72022-06-13 15:19:14 +0530545 return nbDevice
546}
547
548// NewNbDevice Constructor for NbDevice
549func NewNbDevice() *NbDevice {
550 var nbDevice NbDevice
551 return &nbDevice
552}
553
554// WriteToDb writes nb device port config to kv store
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530555func (nbd *NbDevice) WriteToDb(cntx context.Context, portID uint32, ponPort *PonPortCfg) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530556 b, err := json.Marshal(ponPort)
557 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530558 logger.Errorw(ctx, "PonPortConfig-marshal-failed", log.Fields{"err": err, "ponPort": ponPort})
Naveen Sampath04696f72022-06-13 15:19:14 +0530559 return
560 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530561 db.PutNbDevicePort(cntx, nbd.SouthBoundID, portID, string(b))
Naveen Sampath04696f72022-06-13 15:19:14 +0530562}
563
564// AddPortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530565func (nbd *NbDevice) AddPortToNbDevice(cntx context.Context, portID, allowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +0530566 enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530567 logger.Debugw(ctx, "AddPortToNbDevice", log.Fields{"PortID": portID, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530568 ponPort := &PonPortCfg{
569 PortID: portID,
570 MaxActiveChannels: allowedChannels,
571 EnableMulticastKPI: enableMulticastKPI,
572 PortAlarmProfileID: portAlarmProfileID,
573 }
574 nbd.PonPorts.Store(portID, ponPort)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530575 nbd.WriteToDb(cntx, portID, ponPort)
Naveen Sampath04696f72022-06-13 15:19:14 +0530576 return ponPort
577}
578
Akash Sonia8246972023-01-03 10:37:08 +0530579// RestoreDeviceConfigFromDb to restore vnet from port
580func (va *VoltApplication) RestoreDeviceConfigFromDb(cntx context.Context) {
581 // VNETS must be learnt first
582 dConfig, _ := db.GetDeviceConfig(cntx)
583 for _, device := range dConfig {
584 b, ok := device.Value.([]byte)
585 if !ok {
586 logger.Warn(ctx, "The value type is not []byte")
587 continue
588 }
589 devConfig := DeviceConfig{}
590 err := json.Unmarshal(b, &devConfig)
591 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530592 logger.Warnw(ctx, "Unmarshal of device configuration failed", log.Fields{"Device Config": devConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530593 continue
594 }
595 logger.Debugw(ctx, "Retrieved device config", log.Fields{"Device Config": devConfig})
596 if err := va.AddDeviceConfig(cntx, devConfig.SerialNumber, devConfig.HardwareIdentifier, devConfig.NasID, devConfig.IPAddress, devConfig.UplinkPort, devConfig.NniDhcpTrapVid); err != nil {
597 logger.Warnw(ctx, "Add device config failed", log.Fields{"DeviceConfig": devConfig, "Error": err})
598 }
Akash Sonia8246972023-01-03 10:37:08 +0530599 }
600}
601
602// WriteDeviceConfigToDb writes sb device config to kv store
603func (dc *DeviceConfig) WriteDeviceConfigToDb(cntx context.Context, serialNum string, deviceConfig *DeviceConfig) error {
604 b, err := json.Marshal(deviceConfig)
605 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530606 return fmt.Errorf("deviceConfig-marshal-failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530607 }
608 dberr := db.PutDeviceConfig(cntx, serialNum, string(b))
609 if dberr != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530610 return fmt.Errorf("update device config failed - %w ", err)
Akash Sonia8246972023-01-03 10:37:08 +0530611 }
612 return nil
613}
614
vinokuma926cb3e2023-03-29 11:41:06 +0530615func (va *VoltApplication) AddDeviceConfig(cntx context.Context, serialNum, hardwareIdentifier, nasID, ipAddress, uplinkPort string, nniDhcpTrapID int) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530616 logger.Debugw(ctx, "Received Add device config", log.Fields{"SerialNumber": serialNum, "HardwareIdentifier": hardwareIdentifier, "NasID": nasID, "IPAddress": ipAddress, "UplinkPort": uplinkPort, "NniDhcpTrapID": nniDhcpTrapID})
Akash Sonia8246972023-01-03 10:37:08 +0530617 var dc *DeviceConfig
618
Akash Soni87a19072023-02-28 00:46:59 +0530619 deviceConfig := &DeviceConfig{
620 SerialNumber: serialNum,
621 HardwareIdentifier: hardwareIdentifier,
622 NasID: nasID,
623 UplinkPort: uplinkPort,
624 IPAddress: ipAddress,
vinokuma926cb3e2023-03-29 11:41:06 +0530625 NniDhcpTrapVid: nniDhcpTrapID,
Akash Sonia8246972023-01-03 10:37:08 +0530626 }
Akash Soni87a19072023-02-28 00:46:59 +0530627 va.DevicesConfig.Store(serialNum, deviceConfig)
628 err := dc.WriteDeviceConfigToDb(cntx, serialNum, deviceConfig)
629 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530630 return fmt.Errorf("DB update for device config failed - %w ", err)
Akash Soni87a19072023-02-28 00:46:59 +0530631 }
632
633 // If device is already discovered update the VoltDevice structure
634 device, id := va.GetDeviceBySerialNo(serialNum)
635 if device != nil {
vinokuma926cb3e2023-03-29 11:41:06 +0530636 device.NniDhcpTrapVid = of.VlanType(nniDhcpTrapID)
Akash Soni87a19072023-02-28 00:46:59 +0530637 va.DevicesDisc.Store(id, device)
638 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530639 logger.Debugw(ctx, "Added device config", log.Fields{"Device Config": deviceConfig})
Akash Sonia8246972023-01-03 10:37:08 +0530640 return nil
641}
642
643// GetDeviceConfig to get a device config.
644func (va *VoltApplication) GetDeviceConfig(serNum string) *DeviceConfig {
645 if d, ok := va.DevicesConfig.Load(serNum); ok {
646 return d.(*DeviceConfig)
647 }
648 return nil
649}
650
Naveen Sampath04696f72022-06-13 15:19:14 +0530651// UpdatePortToNbDevice Adds pon port to NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530652func (nbd *NbDevice) UpdatePortToNbDevice(cntx context.Context, portID, allowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) *PonPortCfg {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530653 logger.Debugw(ctx, "Received Update Port To NbDevice", log.Fields{"portID": portID, "AllowedChannels": allowedChannels, "EnableMulticastKPI": enableMulticastKPI, "PortAlarmProfileID": portAlarmProfileID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530654 p, exists := nbd.PonPorts.Load(portID)
655 if !exists {
656 logger.Errorw(ctx, "PON port not exists in nb-device", log.Fields{"portID": portID})
657 return nil
658 }
659 port := p.(*PonPortCfg)
660 if allowedChannels != 0 {
661 port.MaxActiveChannels = allowedChannels
662 port.EnableMulticastKPI = enableMulticastKPI
663 port.PortAlarmProfileID = portAlarmProfileID
664 }
665
666 nbd.PonPorts.Store(portID, port)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530667 nbd.WriteToDb(cntx, portID, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530668 return port
669}
670
671// DeletePortFromNbDevice Deletes pon port from NB Device and DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530672func (nbd *NbDevice) DeletePortFromNbDevice(cntx context.Context, portID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530673 logger.Debugw(ctx, "Received Delete Port from NbDevice", log.Fields{"portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530674 if _, ok := nbd.PonPorts.Load(portID); ok {
675 nbd.PonPorts.Delete(portID)
676 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530677 db.DelNbDevicePort(cntx, nbd.SouthBoundID, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530678}
679
680// GetApplication : Interface to access the singleton object
681func GetApplication() *VoltApplication {
682 if vapplication == nil {
683 vapplication = newVoltApplication()
684 }
685 return vapplication
686}
687
688// newVoltApplication : Constructor for the singleton object. Hence this is not
689// an exported function
690func newVoltApplication() *VoltApplication {
691 var va VoltApplication
692 va.IgmpTasks.Initialize(context.TODO())
693 va.MulticastAlarmTasks.Initialize(context.TODO())
694 va.IgmpKPIsTasks.Initialize(context.TODO())
695 va.pppoeTasks.Initialize(context.TODO())
696 va.storeIgmpProfileMap(DefaultIgmpProfID, newDefaultIgmpProfile())
697 va.MeterMgr.Init()
698 va.AddIgmpGroups(5000)
699 va.macPortMap = make(map[string]string)
700 va.IgmpPendingPool = make(map[string]map[*IgmpGroup]bool)
701 va.VnetsBySvlan = util.NewConcurrentMap()
702 va.VnetsToDelete = make(map[string]bool)
703 va.ServicesToDelete = make(map[string]bool)
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530704 va.ServicesToDeactivate = make(map[string]bool)
Naveen Sampath04696f72022-06-13 15:19:14 +0530705 va.VoltPortVnetsToDelete = make(map[*VoltPortVnet]bool)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530706 go va.Start(context.Background(), TimerCfg{tick: 100 * time.Millisecond}, tickTimer)
707 go va.Start(context.Background(), TimerCfg{tick: time.Duration(GroupExpiryTime) * time.Minute}, pendingPoolTimer)
Naveen Sampath04696f72022-06-13 15:19:14 +0530708 InitEventFuncMapper()
709 db = database.GetDatabase()
Akash Soni6f369452023-09-19 11:18:28 +0530710
Naveen Sampath04696f72022-06-13 15:19:14 +0530711 return &va
712}
713
vinokuma926cb3e2023-03-29 11:41:06 +0530714// GetFlowEventRegister - returs the register based on flow mod type
Naveen Sampath04696f72022-06-13 15:19:14 +0530715func (d *VoltDevice) GetFlowEventRegister(flowModType of.Command) (*util.ConcurrentMap, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530716 switch flowModType {
717 case of.CommandDel:
718 return d.FlowDelEventMap, nil
719 case of.CommandAdd:
720 return d.FlowAddEventMap, nil
721 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530722 logger.Warnw(ctx, "Unknown Flow Mod received", log.Fields{"flowModtype": flowModType})
Naveen Sampath04696f72022-06-13 15:19:14 +0530723 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530724 return util.NewConcurrentMap(), errors.New("unknown flow mod")
Naveen Sampath04696f72022-06-13 15:19:14 +0530725}
726
727// RegisterFlowAddEvent to register a flow event.
728func (d *VoltDevice) RegisterFlowAddEvent(cookie string, event *FlowEvent) {
729 logger.Debugw(ctx, "Registered Flow Add Event", log.Fields{"Cookie": cookie, "Event": event})
730 d.FlowAddEventMap.MapLock.Lock()
731 defer d.FlowAddEventMap.MapLock.Unlock()
732 d.FlowAddEventMap.Set(cookie, event)
733}
734
735// RegisterFlowDelEvent to register a flow event.
736func (d *VoltDevice) RegisterFlowDelEvent(cookie string, event *FlowEvent) {
737 logger.Debugw(ctx, "Registered Flow Del Event", log.Fields{"Cookie": cookie, "Event": event})
738 d.FlowDelEventMap.MapLock.Lock()
739 defer d.FlowDelEventMap.MapLock.Unlock()
740 d.FlowDelEventMap.Set(cookie, event)
741}
742
743// UnRegisterFlowEvent to unregister a flow event.
744func (d *VoltDevice) UnRegisterFlowEvent(cookie string, flowModType of.Command) {
745 logger.Debugw(ctx, "UnRegistered Flow Add Event", log.Fields{"Cookie": cookie, "Type": flowModType})
746 flowEventMap, err := d.GetFlowEventRegister(flowModType)
747 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530748 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": flowModType, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530749 return
750 }
751 flowEventMap.MapLock.Lock()
752 defer flowEventMap.MapLock.Unlock()
753 flowEventMap.Remove(cookie)
754}
755
756// AddIgmpGroups to add Igmp groups.
757func (va *VoltApplication) AddIgmpGroups(numOfGroups uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530758 logger.Debugw(ctx, "AddIgmpGroups", log.Fields{"NumOfGroups": numOfGroups})
Naveen Sampath04696f72022-06-13 15:19:14 +0530759 //TODO: Temp change to resolve group id issue in pOLT
760 //for i := 1; uint32(i) <= numOfGroups; i++ {
761 for i := 2; uint32(i) <= (numOfGroups + 1); i++ {
762 ig := IgmpGroup{}
763 ig.GroupID = uint32(i)
764 va.IgmpGroupIds = append(va.IgmpGroupIds, &ig)
765 }
766}
767
768// GetAvailIgmpGroupID to get id of available igmp group.
769func (va *VoltApplication) GetAvailIgmpGroupID() *IgmpGroup {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530770 logger.Info(ctx, "GetAvailIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530771 var ig *IgmpGroup
772 if len(va.IgmpGroupIds) > 0 {
773 ig, va.IgmpGroupIds = va.IgmpGroupIds[0], va.IgmpGroupIds[1:]
774 return ig
775 }
776 return nil
777}
778
779// GetIgmpGroupID to get id of igmp group.
780func (va *VoltApplication) GetIgmpGroupID(gid uint32) (*IgmpGroup, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530781 logger.Info(ctx, "GetIgmpGroupID")
Naveen Sampath04696f72022-06-13 15:19:14 +0530782 for id, ig := range va.IgmpGroupIds {
783 if ig.GroupID == gid {
784 va.IgmpGroupIds = append(va.IgmpGroupIds[0:id], va.IgmpGroupIds[id+1:]...)
785 return ig, nil
786 }
787 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530788 return nil, errors.New("group id missing")
Naveen Sampath04696f72022-06-13 15:19:14 +0530789}
790
791// PutIgmpGroupID to add id of igmp group.
792func (va *VoltApplication) PutIgmpGroupID(ig *IgmpGroup) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530793 logger.Debugw(ctx, "GetIgmpGroupID", log.Fields{"GroupID": ig.GroupID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530794 va.IgmpGroupIds = append([]*IgmpGroup{ig}, va.IgmpGroupIds[0:]...)
795}
796
vinokuma926cb3e2023-03-29 11:41:06 +0530797// RestoreUpgradeStatus - gets upgrade/migration status from DB and updates local flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530798func (va *VoltApplication) RestoreUpgradeStatus(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530799 logger.Info(ctx, "Received Restore Upgrade Status")
Naveen Sampath04696f72022-06-13 15:19:14 +0530800 Migrate := new(DataMigration)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530801 if err := GetMigrationInfo(cntx, Migrate); err == nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530802 if Migrate.Status == MigrationInProgress {
803 isUpgradeComplete = false
804 return
805 }
806 }
807 isUpgradeComplete = true
808
809 logger.Infow(ctx, "Upgrade Status Restored", log.Fields{"Upgrade Completed": isUpgradeComplete})
810}
811
812// ReadAllFromDb : If we are restarted, learn from the database the current execution
813// stage
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530814func (va *VoltApplication) ReadAllFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530815 logger.Info(ctx, "Reading the meters from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530816 va.RestoreMetersFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530817 logger.Info(ctx, "Reading the VNETs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530818 va.RestoreVnetsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530819 logger.Info(ctx, "Reading the VPVs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530820 va.RestoreVpvsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530821 logger.Info(ctx, "Reading the Services from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530822 va.RestoreSvcsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530823 logger.Info(ctx, "Reading the MVLANs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530824 va.RestoreMvlansFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530825 logger.Info(ctx, "Reading the IGMP profiles from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826 va.RestoreIGMPProfilesFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530827 logger.Info(ctx, "Reading the Mcast configs from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530828 va.RestoreMcastConfigsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530829 logger.Info(ctx, "Reading the IGMP groups for DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530830 va.RestoreIgmpGroupsFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530831 logger.Info(ctx, "Reading Upgrade status from DB")
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530832 va.RestoreUpgradeStatus(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530833 logger.Info(ctx, "Reading OltFlowService from DB")
834 va.RestoreOltFlowService(cntx)
Akash Sonia8246972023-01-03 10:37:08 +0530835 logger.Info(ctx, "Reading device config from DB")
836 va.RestoreDeviceConfigFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530837 logger.Info(ctx, "Reconciled from DB")
838}
839
vinokuma926cb3e2023-03-29 11:41:06 +0530840// InitStaticConfig to initialize static config.
Naveen Sampath04696f72022-06-13 15:19:14 +0530841func (va *VoltApplication) InitStaticConfig() {
842 va.InitIgmpSrcMac()
843}
844
845// SetVendorID to set vendor id
846func (va *VoltApplication) SetVendorID(vendorID string) {
847 va.vendorID = vendorID
848}
849
850// GetVendorID to get vendor id
851func (va *VoltApplication) GetVendorID() string {
852 return va.vendorID
853}
854
855// SetRebootFlag to set reboot flag
856func (va *VoltApplication) SetRebootFlag(flag bool) {
857 vgcRebooted = flag
858}
859
860// GetUpgradeFlag to get reboot status
861func (va *VoltApplication) GetUpgradeFlag() bool {
862 return isUpgradeComplete
863}
864
865// SetUpgradeFlag to set reboot status
866func (va *VoltApplication) SetUpgradeFlag(flag bool) {
867 isUpgradeComplete = flag
868}
869
870// ------------------------------------------------------------
871// Device related functions
872
873// AddDevice : Add a device and typically the device stores the NNI port on the device
874// The NNI port is used when the packets are emitted towards the network.
875// The outport is selected as the NNI port of the device. Today, we support
876// a single NNI port per OLT. This is true whether the network uses any
877// protection mechanism (LAG, ERPS, etc.). The aggregate of the such protection
878// is represented by a single NNI port
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530879func (va *VoltApplication) AddDevice(cntx context.Context, device string, slno, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530880 logger.Debugw(ctx, "Received Device Ind: Add", log.Fields{"Device": device, "SrNo": slno, "southBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530881 if _, ok := va.DevicesDisc.Load(device); ok {
882 logger.Warnw(ctx, "Device Exists", log.Fields{"Device": device})
883 }
884 d := NewVoltDevice(device, slno, southBoundID)
885
886 addPort := func(key, value interface{}) bool {
887 portID := key.(uint32)
888 port := value.(*PonPortCfg)
889 va.AggActiveChannelsCountForPonPort(device, portID, port)
890 d.ActiveChannelsPerPon.Store(portID, port)
891 return true
892 }
893 if nbDevice, exists := va.NbDevice.Load(southBoundID); exists {
894 // Pon Ports added before OLT activate.
895 nbDevice.(*NbDevice).PonPorts.Range(addPort)
896 } else {
897 // Check if NbPort exists in DB. VGC restart case.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530898 nbd := va.RestoreNbDeviceFromDb(cntx, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530899 nbd.PonPorts.Range(addPort)
900 }
901 va.DevicesDisc.Store(device, d)
902}
903
904// GetDevice to get a device.
905func (va *VoltApplication) GetDevice(device string) *VoltDevice {
906 if d, ok := va.DevicesDisc.Load(device); ok {
907 return d.(*VoltDevice)
908 }
909 return nil
910}
911
912// DelDevice to delete a device.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530913func (va *VoltApplication) DelDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530914 logger.Debugw(ctx, "Received Device Ind: Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530915 if vdIntf, ok := va.DevicesDisc.Load(device); ok {
916 vd := vdIntf.(*VoltDevice)
917 va.DevicesDisc.Delete(device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530918 _ = db.DelAllRoutesForDevice(cntx, device)
919 va.HandleFlowClearFlag(cntx, device, vd.SerialNum, vd.SouthBoundID)
920 _ = db.DelAllGroup(cntx, device)
921 _ = db.DelAllMeter(cntx, device)
922 _ = db.DelAllPorts(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +0530923 logger.Debugw(ctx, "Device deleted", log.Fields{"Device": device})
924 } else {
925 logger.Warnw(ctx, "Device Doesn't Exist", log.Fields{"Device": device})
926 }
927}
928
929// GetDeviceBySerialNo to get a device by serial number.
930// TODO - Transform this into a MAP instead
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530931func (va *VoltApplication) GetDeviceBySerialNo(slno string) (*VoltDevice, string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530932 logger.Debugw(ctx, "Received Device Ind: Get", log.Fields{"Serial Num": slno})
Naveen Sampath04696f72022-06-13 15:19:14 +0530933 var device *VoltDevice
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530934 var deviceID string
Naveen Sampath04696f72022-06-13 15:19:14 +0530935 getserial := func(key interface{}, value interface{}) bool {
936 device = value.(*VoltDevice)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530937 deviceID = key.(string)
Naveen Sampath04696f72022-06-13 15:19:14 +0530938 return device.SerialNum != slno
939 }
940 va.DevicesDisc.Range(getserial)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530941 return device, deviceID
Naveen Sampath04696f72022-06-13 15:19:14 +0530942}
943
944// PortAddInd : This is a PORT add indication coming from the VPAgent, which is essentially
945// a request coming from VOLTHA. The device and identity of the port is provided
946// in this request. Add them to the application for further use
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530947func (va *VoltApplication) PortAddInd(cntx context.Context, device string, id uint32, portName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530948 logger.Debugw(ctx, "Received Port Ind: Add", log.Fields{"Device": device, "ID": id, "Port": portName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530949 va.portLock.Lock()
950 if d := va.GetDevice(device); d != nil {
951 p := d.AddPort(portName, id)
952 va.PortsDisc.Store(portName, p)
953 va.portLock.Unlock()
954 nni, _ := va.GetNniPort(device)
955 if nni == portName {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530956 d.pushFlowsForUnis(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530957 }
958 } else {
959 va.portLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530960 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 +0530961 }
962}
963
964// PortDelInd : Only the NNI ports are recorded in the device for now. When port delete
965// arrives, only the NNI ports need adjustments.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530966func (va *VoltApplication) PortDelInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530967 logger.Debugw(ctx, "Received Port Ind: Delete", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530968 if d := va.GetDevice(device); d != nil {
969 p := d.GetPort(port)
970 if p != nil && p.State == PortStateUp {
971 logger.Infow(ctx, "Port state is UP. Trigerring Port Down Ind before deleting", log.Fields{"Port": p})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530972 va.PortDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530973 }
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530974 // if RemoveFlowsOnDisable is flase, then flows will be existing till port delete. Remove the flows now
975 if !va.OltFlowServiceConfig.RemoveFlowsOnDisable {
Akash Sonia8246972023-01-03 10:37:08 +0530976 vpvs, ok := va.VnetsByPort.Load(port)
977 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530978 logger.Infow(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
979 } else {
980 for _, vpv := range vpvs.([]*VoltPortVnet) {
981 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530982 // Set delFlowsInDevice to true to delete flows only in DB/device during Port Delete.
983 vpv.PortDownInd(cntx, device, port, true, true)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530984 vpv.VpvLock.Unlock()
985 }
986 }
987 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530988 va.portLock.Lock()
989 defer va.portLock.Unlock()
990 d.DelPort(port)
991 if _, ok := va.PortsDisc.Load(port); ok {
992 va.PortsDisc.Delete(port)
993 }
994 } else {
995 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: Delete", log.Fields{"Device": device, "Port": port})
996 }
997}
998
vinokuma926cb3e2023-03-29 11:41:06 +0530999// PortUpdateInd Updates port Id incase of ONU movement
Naveen Sampath04696f72022-06-13 15:19:14 +05301000func (va *VoltApplication) PortUpdateInd(device string, portName string, id uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301001 logger.Debugw(ctx, "Received Port Ind: Update", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301002 va.portLock.Lock()
1003 defer va.portLock.Unlock()
1004 if d := va.GetDevice(device); d != nil {
1005 vp := d.GetPort(portName)
1006 vp.ID = id
1007 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301008 logger.Warnw(ctx, "Device Not Found", log.Fields{"Device": device, "Port": portName, "ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +05301009 }
1010}
1011
1012// AddNbPonPort Add pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301013func (va *VoltApplication) AddNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32,
Naveen Sampath04696f72022-06-13 15:19:14 +05301014 enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301015 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 +05301016 var nbd *NbDevice
1017 nbDevice, ok := va.NbDevice.Load(oltSbID)
1018
1019 if !ok {
1020 nbd = NewNbDevice()
1021 nbd.SouthBoundID = oltSbID
1022 } else {
1023 nbd = nbDevice.(*NbDevice)
1024 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301025 port := nbd.AddPortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301026 logger.Debugw(ctx, "Added Port To NbDevice", log.Fields{"port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301027 // Add this port to voltDevice
1028 addPort := func(key, value interface{}) bool {
1029 voltDevice := value.(*VoltDevice)
1030 if oltSbID == voltDevice.SouthBoundID {
1031 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); !exists {
1032 voltDevice.ActiveChannelsPerPon.Store(portID, port)
1033 }
1034 return false
1035 }
1036 return true
1037 }
1038 va.DevicesDisc.Range(addPort)
1039 va.NbDevice.Store(oltSbID, nbd)
1040
1041 return nil
1042}
1043
1044// UpdateNbPonPort update pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301045func (va *VoltApplication) UpdateNbPonPort(cntx context.Context, oltSbID string, portID, maxAllowedChannels uint32, enableMulticastKPI bool, portAlarmProfileID string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301046 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 +05301047 var nbd *NbDevice
1048 nbDevice, ok := va.NbDevice.Load(oltSbID)
1049
1050 if !ok {
1051 logger.Errorw(ctx, "Device-doesn't-exists", log.Fields{"deviceID": oltSbID})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301052 return fmt.Errorf("device-doesn't-exists - %s", oltSbID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301053 }
1054 nbd = nbDevice.(*NbDevice)
1055
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301056 port := nbd.UpdatePortToNbDevice(cntx, portID, maxAllowedChannels, enableMulticastKPI, portAlarmProfileID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301057 if port == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301058 return fmt.Errorf("port-doesn't-exists-%d", portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301059 }
1060 va.NbDevice.Store(oltSbID, nbd)
1061
1062 // Add this port to voltDevice
1063 updPort := func(key, value interface{}) bool {
1064 voltDevice := value.(*VoltDevice)
1065 if oltSbID == voltDevice.SouthBoundID {
1066 voltDevice.ActiveChannelCountLock.Lock()
1067 if p, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1068 oldPort := p.(*PonPortCfg)
1069 if port.MaxActiveChannels != 0 {
1070 oldPort.MaxActiveChannels = port.MaxActiveChannels
1071 oldPort.EnableMulticastKPI = port.EnableMulticastKPI
1072 voltDevice.ActiveChannelsPerPon.Store(portID, oldPort)
1073 }
1074 }
1075 voltDevice.ActiveChannelCountLock.Unlock()
1076 return false
1077 }
1078 return true
1079 }
1080 va.DevicesDisc.Range(updPort)
1081
1082 return nil
1083}
1084
1085// DeleteNbPonPort Delete pon port to nbDevice
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301086func (va *VoltApplication) DeleteNbPonPort(cntx context.Context, oltSbID string, portID uint32) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301087 logger.Debugw(ctx, "Received NbPonPort Ind: Delete", log.Fields{"oltSbID": oltSbID, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301088 nbDevice, ok := va.NbDevice.Load(oltSbID)
1089 if ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301090 nbDevice.(*NbDevice).DeletePortFromNbDevice(cntx, portID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301091 va.NbDevice.Store(oltSbID, nbDevice.(*NbDevice))
1092 } else {
1093 logger.Warnw(ctx, "Delete pon received for unknown device", log.Fields{"oltSbID": oltSbID})
1094 return nil
1095 }
1096 // Delete this port from voltDevice
1097 delPort := func(key, value interface{}) bool {
1098 voltDevice := value.(*VoltDevice)
1099 if oltSbID == voltDevice.SouthBoundID {
1100 if _, exists := voltDevice.ActiveChannelsPerPon.Load(portID); exists {
1101 voltDevice.ActiveChannelsPerPon.Delete(portID)
1102 }
1103 return false
1104 }
1105 return true
1106 }
1107 va.DevicesDisc.Range(delPort)
1108 return nil
1109}
1110
1111// GetNniPort : Get the NNI port for a device. Called from different other applications
1112// as a port to match or destination for a packet out. The VOLT application
1113// is written with the assumption that there is a single NNI port. The OLT
1114// device is responsible for translating the combination of VLAN and the
1115// NNI port ID to identify possibly a single physical port or a logical
1116// port which is a result of protection methods applied.
1117func (va *VoltApplication) GetNniPort(device string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301118 logger.Debugw(ctx, "NNI Get Ind", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301119 va.portLock.Lock()
1120 defer va.portLock.Unlock()
1121 d, ok := va.DevicesDisc.Load(device)
1122 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301123 return "", errors.New("device doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301124 }
1125 return d.(*VoltDevice).NniPort, nil
1126}
1127
1128// NniDownInd process for Nni down indication.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129func (va *VoltApplication) NniDownInd(cntx context.Context, deviceID string, devSrNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301130 logger.Debugw(ctx, "NNI Down Ind", log.Fields{"DeviceID": deviceID, "Device SrNo": devSrNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301131
1132 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1133 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301134 mvProfile.removeIgmpMcastFlows(cntx, devSrNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301135 return true
1136 }
1137 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1138
1139 //Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301140 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301141}
1142
1143// DeviceUpInd changes device state to up.
1144func (va *VoltApplication) DeviceUpInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301145 logger.Infow(ctx, "Received Device Ind: UP", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301146 if d := va.GetDevice(device); d != nil {
1147 d.State = controller.DeviceStateUP
1148 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301149 logger.Warnw(ctx, "Ignoring Device indication: UP. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301150 }
1151}
1152
1153// DeviceDownInd changes device state to down.
1154func (va *VoltApplication) DeviceDownInd(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301155 logger.Infow(ctx, "Received Device Ind: DOWN", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301156 if d := va.GetDevice(device); d != nil {
1157 d.State = controller.DeviceStateDOWN
1158 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301159 logger.Warnw(ctx, "Ignoring Device indication: DOWN. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301160 }
1161}
1162
1163// DeviceRebootInd process for handling flow clear flag for device reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301164func (va *VoltApplication) DeviceRebootInd(cntx context.Context, device string, serialNum string, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301165 logger.Infow(ctx, "Received Device Ind: Reboot", log.Fields{"Device": device, "SerialNumber": serialNum, "SouthBoundID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301166
1167 if d := va.GetDevice(device); d != nil {
1168 if d.State == controller.DeviceStateREBOOTED {
1169 logger.Warnw(ctx, "Ignoring Device Ind: Reboot, Device already in Reboot state", log.Fields{"Device": device, "SerialNumber": serialNum, "State": d.State})
1170 return
1171 }
1172 d.State = controller.DeviceStateREBOOTED
1173 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301174 va.HandleFlowClearFlag(cntx, device, serialNum, southBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301175}
1176
1177// DeviceDisableInd handles device deactivation process
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301178func (va *VoltApplication) DeviceDisableInd(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301179 logger.Infow(ctx, "Received Device Ind: Disable", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301180
1181 d := va.GetDevice(device)
1182 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301183 logger.Warnw(ctx, "Ignoring Device indication: DISABLED. Device Missing", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301184 return
1185 }
1186
1187 d.State = controller.DeviceStateDISABLED
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301188 va.HandleFlowClearFlag(cntx, device, d.SerialNum, d.SouthBoundID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301189}
1190
1191// ProcessIgmpDSFlowForMvlan for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301192func (va *VoltApplication) ProcessIgmpDSFlowForMvlan(cntx context.Context, d *VoltDevice, mvp *MvlanProfile, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301193 logger.Debugw(ctx, "Process IGMP DS Flows for MVlan", log.Fields{"device": d.Name, "Mvlan": mvp.Mvlan, "addFlow": addFlow})
1194 portState := false
1195 p := d.GetPort(d.NniPort)
1196 if p != nil && p.State == PortStateUp {
1197 portState = true
1198 }
1199
1200 if addFlow {
1201 if portState {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301202 mvp.pushIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301203 }
1204 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301205 mvp.removeIgmpMcastFlows(cntx, d.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301206 }
1207}
1208
1209// ProcessIgmpDSFlowForDevice for processing Igmp DS flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301210func (va *VoltApplication) ProcessIgmpDSFlowForDevice(cntx context.Context, d *VoltDevice, addFlow bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301211 logger.Debugw(ctx, "Process IGMP DS Flows for device", log.Fields{"device": d.Name, "addFlow": addFlow})
1212
1213 handleIgmpDsFlows := func(key interface{}, value interface{}) bool {
1214 mvProfile := value.(*MvlanProfile)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301215 va.ProcessIgmpDSFlowForMvlan(cntx, d, mvProfile, addFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301216 return true
1217 }
1218 va.MvlanProfilesByName.Range(handleIgmpDsFlows)
1219}
1220
1221// GetDeviceFromPort : This is suitable only for access ports as their naming convention
1222// makes them unique across all the OLTs. This must be called with
1223// port name that is an access port. Currently called from VNETs, attached
1224// only to access ports, and the services which are also attached only
1225// to access ports
1226func (va *VoltApplication) GetDeviceFromPort(port string) (*VoltDevice, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301227 logger.Debugw(ctx, "Received Get Device From Port", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301228 va.portLock.Lock()
1229 defer va.portLock.Unlock()
1230 var err error
1231 err = nil
1232 p, ok := va.PortsDisc.Load(port)
1233 if !ok {
1234 return nil, errorCodes.ErrPortNotFound
1235 }
1236 d := va.GetDevice(p.(*VoltPort).Device)
1237 if d == nil {
1238 err = errorCodes.ErrDeviceNotFound
1239 }
1240 return d, err
1241}
1242
1243// GetPortID : This too applies only to access ports. The ports can be indexed
1244// purely by their names without the device forming part of the key
1245func (va *VoltApplication) GetPortID(port string) (uint32, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301246 logger.Debugw(ctx, "Received Get Port ID", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301247 va.portLock.Lock()
1248 defer va.portLock.Unlock()
1249 p, ok := va.PortsDisc.Load(port)
1250 if !ok {
1251 return 0, errorCodes.ErrPortNotFound
1252 }
1253 return p.(*VoltPort).ID, nil
1254}
1255
1256// GetPortName : This too applies only to access ports. The ports can be indexed
1257// purely by their names without the device forming part of the key
1258func (va *VoltApplication) GetPortName(port uint32) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301259 logger.Debugw(ctx, "Received Get Port Name", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301260 va.portLock.Lock()
1261 defer va.portLock.Unlock()
1262 var portName string
1263 va.PortsDisc.Range(func(key interface{}, value interface{}) bool {
1264 portInfo := value.(*VoltPort)
1265 if portInfo.ID == port {
1266 portName = portInfo.Name
1267 return false
1268 }
1269 return true
1270 })
1271 return portName, nil
1272}
1273
1274// GetPonFromUniPort to get Pon info from UniPort
1275func (va *VoltApplication) GetPonFromUniPort(port string) (string, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301276 logger.Debugw(ctx, "Received Get Pon From UniPort", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301277 uniPortID, err := va.GetPortID(port)
1278 if err == nil {
1279 ponPortID := (uniPortID & 0x0FF00000) >> 20 //pon(8) + onu(8) + uni(12)
1280 return strconv.FormatUint(uint64(ponPortID), 10), nil
1281 }
1282 return "", err
1283}
1284
1285// GetPortState : This too applies only to access ports. The ports can be indexed
1286// purely by their names without the device forming part of the key
1287func (va *VoltApplication) GetPortState(port string) (PortState, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301288 logger.Debugw(ctx, "Received Get Port State", log.Fields{"Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301289 va.portLock.Lock()
1290 defer va.portLock.Unlock()
1291 p, ok := va.PortsDisc.Load(port)
1292 if !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301293 return 0, errors.New("port not configured")
Naveen Sampath04696f72022-06-13 15:19:14 +05301294 }
1295 return p.(*VoltPort).State, nil
1296}
1297
1298// GetIcmpv6Receivers to get Icmp v6 receivers
1299func (va *VoltApplication) GetIcmpv6Receivers(device string) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301300 logger.Debugw(ctx, "Get Icmpv6 Receivers", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301301 var receiverList []uint32
1302 receivers, _ := va.Icmpv6Receivers.Load(device)
1303 if receivers != nil {
1304 receiverList = receivers.([]uint32)
1305 }
1306 return receiverList
1307}
1308
1309// AddIcmpv6Receivers to add Icmp v6 receivers
1310func (va *VoltApplication) AddIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301311 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 var receiverList []uint32
1313 receivers, _ := va.Icmpv6Receivers.Load(device)
1314 if receivers != nil {
1315 receiverList = receivers.([]uint32)
1316 }
1317 receiverList = append(receiverList, portID)
1318 va.Icmpv6Receivers.Store(device, receiverList)
1319 logger.Debugw(ctx, "Receivers after addition", log.Fields{"Receivers": receiverList})
1320 return receiverList
1321}
1322
1323// DelIcmpv6Receivers to delete Icmp v6 receievers
1324func (va *VoltApplication) DelIcmpv6Receivers(device string, portID uint32) []uint32 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301325 logger.Debugw(ctx, "Received Add Icmpv6 Receivers", log.Fields{"device": device, "portID": portID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301326 var receiverList []uint32
1327 receivers, _ := va.Icmpv6Receivers.Load(device)
1328 if receivers != nil {
1329 receiverList = receivers.([]uint32)
1330 }
1331 for i, port := range receiverList {
1332 if port == portID {
1333 receiverList = append(receiverList[0:i], receiverList[i+1:]...)
1334 va.Icmpv6Receivers.Store(device, receiverList)
1335 break
1336 }
1337 }
1338 logger.Debugw(ctx, "Receivers After deletion", log.Fields{"Receivers": receiverList})
1339 return receiverList
1340}
1341
1342// ProcessDevFlowForDevice - Process DS ICMPv6 & ARP flow for provided device and vnet profile
1343// device - Device Obj
1344// vnet - vnet profile name
1345// enabled - vlan enabled/disabled - based on the status, the flow shall be added/removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301346func (va *VoltApplication) ProcessDevFlowForDevice(cntx context.Context, device *VoltDevice, vnet *VoltVnet, enabled bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301347 logger.Debugw(ctx, "Process Dev Flow For Device", log.Fields{"Device": device, "VnetName": vnet.Name, "Enabled": enabled})
Naveen Sampath04696f72022-06-13 15:19:14 +05301348 _, applied := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0))
1349 if enabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301350 va.PushDevFlowForVlan(cntx, vnet)
Naveen Sampath04696f72022-06-13 15:19:14 +05301351 } else if !enabled && applied {
1352 //va.DeleteDevFlowForVlan(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301353 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, device.SerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301354 }
1355}
1356
vinokuma926cb3e2023-03-29 11:41:06 +05301357// NniVlanIndToIgmp - Trigger receiver up indication to all ports with igmp enabled
1358// and has the provided mvlan
Naveen Sampath04696f72022-06-13 15:19:14 +05301359func (va *VoltApplication) NniVlanIndToIgmp(device *VoltDevice, mvp *MvlanProfile) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301360 logger.Infow(ctx, "Received Nni Vlan Ind To Igmp", log.Fields{"Vlan": mvp.Mvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301361
vinokuma926cb3e2023-03-29 11:41:06 +05301362 // Trigger nni indication for receiver only for first time
Naveen Sampath04696f72022-06-13 15:19:14 +05301363 if device.IgmpDsFlowAppliedForMvlan[uint16(mvp.Mvlan)] {
1364 return
1365 }
1366 device.Ports.Range(func(key, value interface{}) bool {
1367 port := key.(string)
1368
1369 if state, _ := va.GetPortState(port); state == PortStateUp {
1370 vpvs, _ := va.VnetsByPort.Load(port)
1371 if vpvs == nil {
1372 return true
1373 }
1374 for _, vpv := range vpvs.([]*VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05301375 // Send indication only for subscribers with the received mvlan profile
Naveen Sampath04696f72022-06-13 15:19:14 +05301376 if vpv.IgmpEnabled && vpv.MvlanProfileName == mvp.Name {
1377 vpv.services.Range(ReceiverUpInd)
1378 }
1379 }
1380 }
1381 return true
1382 })
1383}
1384
1385// PortUpInd :
1386// -----------------------------------------------------------------------
1387// Port status change handling
1388// ----------------------------------------------------------------------
1389// Port UP indication is passed to all services associated with the port
1390// so that the services can configure flows applicable when the port goes
1391// up from down state
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301392func (va *VoltApplication) PortUpInd(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301393 logger.Infow(ctx, "Received Southbound Port Ind: UP", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301394 d := va.GetDevice(device)
1395
1396 if d == nil {
1397 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: UP", log.Fields{"Device": device, "Port": port})
1398 return
1399 }
1400
vinokuma926cb3e2023-03-29 11:41:06 +05301401 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301402 va.portLock.Lock()
1403 // Do not defer the port mutex unlock here
1404 // Some of the following func calls needs the port lock, so defering the lock here
1405 // may lead to dead-lock
1406 p := d.GetPort(port)
1407
1408 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301409 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 +05301410 va.portLock.Unlock()
1411 return
1412 }
1413 p.State = PortStateUp
1414 va.portLock.Unlock()
1415
Naveen Sampath04696f72022-06-13 15:19:14 +05301416 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301417 logger.Debugw(ctx, "Received NNI Port Ind: UP", log.Fields{"Device": device, "PortName": port, "PortId": p.ID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301418 //va.PushDevFlowForDevice(d)
1419 //Build Igmp TrapFlowRule
1420 //va.ProcessIgmpDSFlowForDevice(d, true)
1421 }
1422 vpvs, ok := va.VnetsByPort.Load(port)
1423 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301424 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301425 //msgbus.ProcessPortInd(msgbus.PortUp, d.SerialNum, p.Name, false, getServiceList(port))
1426 return
1427 }
1428
vinokuma926cb3e2023-03-29 11:41:06 +05301429 // If NNI port is not UP, do not push Flows
Naveen Sampath04696f72022-06-13 15:19:14 +05301430 if d.NniPort == "" {
1431 logger.Warnw(ctx, "NNI port not UP. Not sending Port UP Ind for VPVs", log.Fields{"NNI": d.NniPort})
1432 return
1433 }
1434
Naveen Sampath04696f72022-06-13 15:19:14 +05301435 for _, vpv := range vpvs.([]*VoltPortVnet) {
1436 vpv.VpvLock.Lock()
vinokuma926cb3e2023-03-29 11:41:06 +05301437 // If no service is activated drop the portUpInd
Tinoj Josephec742f62022-09-29 19:11:10 +05301438 if vpv.IsServiceActivated(cntx) {
vinokuma926cb3e2023-03-29 11:41:06 +05301439 // Do not trigger indication for the vpv which is already removed from vpv list as
Tinoj Josephec742f62022-09-29 19:11:10 +05301440 // part of service delete (during the lock wait duration)
1441 // In that case, the services associated wil be zero
1442 if vpv.servicesCount.Load() != 0 {
1443 vpv.PortUpInd(cntx, d, port)
1444 }
1445 } else {
1446 // Service not activated, still attach device to service
1447 vpv.setDevice(d.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301448 }
1449 vpv.VpvLock.Unlock()
1450 }
1451 // At the end of processing inform the other entities that
1452 // are interested in the events
1453}
1454
1455/*
1456func getServiceList(port string) map[string]bool {
1457 serviceList := make(map[string]bool)
1458
1459 getServiceNames := func(key interface{}, value interface{}) bool {
1460 serviceList[key.(string)] = value.(*VoltService).DsHSIAFlowsApplied
1461 return true
1462 }
1463
1464 if vpvs, _ := GetApplication().VnetsByPort.Load(port); vpvs != nil {
1465 vpvList := vpvs.([]*VoltPortVnet)
1466 for _, vpv := range vpvList {
1467 vpv.services.Range(getServiceNames)
1468 }
1469 }
1470 return serviceList
1471
1472}*/
1473
vinokuma926cb3e2023-03-29 11:41:06 +05301474// ReceiverUpInd - Send receiver up indication for service with Igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301475func ReceiverUpInd(key, value interface{}) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301476 logger.Info(ctx, "Receiver Indication: UP")
Naveen Sampath04696f72022-06-13 15:19:14 +05301477 svc := value.(*VoltService)
1478 var vlan of.VlanType
1479
1480 if !svc.IPAssigned() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301481 logger.Warnw(ctx, "IP Not assigned, skipping general query", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +05301482 return false
1483 }
1484
vinokuma926cb3e2023-03-29 11:41:06 +05301485 // Send port up indication to igmp only for service with igmp enabled
Naveen Sampath04696f72022-06-13 15:19:14 +05301486 if svc.IgmpEnabled {
1487 if svc.VlanControl == ONUCVlan || svc.VlanControl == ONUCVlanOLTSVlan {
1488 vlan = svc.CVlan
1489 } else {
1490 vlan = svc.UniVlan
1491 }
1492 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
1493 GetApplication().ReceiverUpInd(device.Name, svc.Port, svc.MvlanProfileName, vlan, svc.Pbits)
1494 }
1495 return false
1496 }
1497 return true
1498}
1499
1500// PortDownInd : Port down indication is passed on to the services so that the services
1501// can make changes at this transition.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301502func (va *VoltApplication) PortDownInd(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301503 logger.Infow(ctx, "Received SouthBound Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1504 d := va.GetDevice(device)
1505
1506 if d == nil {
1507 logger.Warnw(ctx, "Device Not Found - Dropping Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
1508 return
1509 }
vinokuma926cb3e2023-03-29 11:41:06 +05301510 // Fixme: If Port Update Comes in large numbers, this will result in slow update per device
Naveen Sampath04696f72022-06-13 15:19:14 +05301511 va.portLock.Lock()
1512 // Do not defer the port mutex unlock here
1513 // Some of the following func calls needs the port lock, so defering the lock here
1514 // may lead to dead-lock
1515 p := d.GetPort(port)
1516 if p == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301517 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 +05301518 va.portLock.Unlock()
1519 return
1520 }
1521 p.State = PortStateDown
1522 va.portLock.Unlock()
1523
1524 if d.State == controller.DeviceStateREBOOTED {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301525 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 +05301526 return
1527 }
1528
1529 if p.Type == VoltPortTypeNni {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301530 logger.Debugw(ctx, "Received NNI Port Ind: DOWN", log.Fields{"Device": device, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301531 va.DeleteDevFlowForDevice(cntx, d)
1532 va.NniDownInd(cntx, device, d.SerialNum)
1533 va.RemovePendingGroups(cntx, device, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301534 }
1535 vpvs, ok := va.VnetsByPort.Load(port)
1536 if !ok || nil == vpvs || len(vpvs.([]*VoltPortVnet)) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301537 logger.Warnw(ctx, "No VNETs on port", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301538 //msgbus.ProcessPortInd(msgbus.PortDown, d.SerialNum, p.Name, false, getServiceList(port))
1539 return
1540 }
Akash Sonia8246972023-01-03 10:37:08 +05301541
Naveen Sampath04696f72022-06-13 15:19:14 +05301542 for _, vpv := range vpvs.([]*VoltPortVnet) {
1543 vpv.VpvLock.Lock()
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301544 vpv.PortDownInd(cntx, device, port, false, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301545 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301546 va.ReceiverDownInd(cntx, device, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301547 }
1548 vpv.VpvLock.Unlock()
1549 }
1550}
1551
1552// PacketInInd :
1553// -----------------------------------------------------------------------
1554// PacketIn Processing
1555// Packet In Indication processing. It arrives with the identities of
1556// the device and port on which the packet is received. At first, the
1557// packet is decoded and the right processor is called. Currently, we
1558// plan to support only DHCP and IGMP. In future, we can add more
1559// capabilities as needed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301560func (va *VoltApplication) PacketInInd(cntx context.Context, device string, port string, pkt []byte) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301561 logger.Infow(ctx, "Received a Packet-In Indication", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301562 // Decode the incoming packet
1563 packetSide := US
1564 if strings.Contains(port, NNI) {
1565 packetSide = DS
1566 }
1567
Naveen Sampath04696f72022-06-13 15:19:14 +05301568 gopkt := gopacket.NewPacket(pkt, layers.LayerTypeEthernet, gopacket.Default)
1569
1570 var dot1qFound = false
1571 for _, l := range gopkt.Layers() {
1572 if l.LayerType() == layers.LayerTypeDot1Q {
1573 dot1qFound = true
1574 break
1575 }
1576 }
1577
1578 if !dot1qFound {
1579 logger.Debugw(ctx, "Ignoring Received Packet-In Indication without Dot1Q Header",
1580 log.Fields{"Device": device, "Port": port})
1581 return
1582 }
1583
1584 logger.Debugw(ctx, "Received Southbound Packet In", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1585
1586 // Classify the packet into packet types that we support
1587 // The supported types are DHCP and IGMP. The DHCP packet is
1588 // identified by matching the L4 protocol to UDP. The IGMP packet
1589 // is identified by matching L3 protocol to IGMP
1590 arpl := gopkt.Layer(layers.LayerTypeARP)
1591 if arpl != nil {
1592 if callBack, ok := PacketHandlers[ARP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301593 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301594 } else {
1595 logger.Debugw(ctx, "ARP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1596 }
1597 return
1598 }
1599 ipv4l := gopkt.Layer(layers.LayerTypeIPv4)
1600 if ipv4l != nil {
1601 ip := ipv4l.(*layers.IPv4)
1602
1603 if ip.Protocol == layers.IPProtocolUDP {
1604 logger.Debugw(ctx, "Received Southbound UDP ipv4 packet in", log.Fields{"StreamSide": packetSide})
1605 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv4)
1606 if dhcpl != nil {
1607 if callBack, ok := PacketHandlers[DHCPv4]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301608 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301609 } else {
1610 logger.Debugw(ctx, "DHCPv4 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1611 }
1612 }
1613 } else if ip.Protocol == layers.IPProtocolIGMP {
1614 logger.Debugw(ctx, "Received Southbound IGMP packet in", log.Fields{"StreamSide": packetSide})
1615 if callBack, ok := PacketHandlers[IGMP]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301616 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301617 } else {
1618 logger.Debugw(ctx, "IGMP handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1619 }
1620 }
1621 return
1622 }
1623 ipv6l := gopkt.Layer(layers.LayerTypeIPv6)
1624 if ipv6l != nil {
1625 ip := ipv6l.(*layers.IPv6)
1626 if ip.NextHeader == layers.IPProtocolUDP {
1627 logger.Debug(ctx, "Received Southbound UDP ipv6 packet in")
1628 dhcpl := gopkt.Layer(layers.LayerTypeDHCPv6)
1629 if dhcpl != nil {
1630 if callBack, ok := PacketHandlers[DHCPv6]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301631 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301632 } else {
1633 logger.Debugw(ctx, "DHCPv6 handler is not registered, dropping the packet", log.Fields{"Pkt": hex.EncodeToString(gopkt.Data())})
1634 }
1635 }
1636 }
1637 return
1638 }
1639
1640 pppoel := gopkt.Layer(layers.LayerTypePPPoE)
1641 if pppoel != nil {
1642 logger.Debugw(ctx, "Received Southbound PPPoE packet in", log.Fields{"StreamSide": packetSide})
1643 if callBack, ok := PacketHandlers[PPPOE]; ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301644 callBack(cntx, device, port, gopkt)
Naveen Sampath04696f72022-06-13 15:19:14 +05301645 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301646 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 +05301647 }
1648 }
1649}
1650
1651// GetVlans : This utility gets the VLANs from the packet. The VLANs are
1652// used to identify the right service that must process the incoming
1653// packet
1654func GetVlans(pkt gopacket.Packet) []of.VlanType {
1655 var vlans []of.VlanType
1656 for _, l := range pkt.Layers() {
1657 if l.LayerType() == layers.LayerTypeDot1Q {
1658 q, ok := l.(*layers.Dot1Q)
1659 if ok {
1660 vlans = append(vlans, of.VlanType(q.VLANIdentifier))
1661 }
1662 }
1663 }
1664 return vlans
1665}
1666
1667// GetPriority to get priority
1668func GetPriority(pkt gopacket.Packet) uint8 {
1669 for _, l := range pkt.Layers() {
1670 if l.LayerType() == layers.LayerTypeDot1Q {
1671 q, ok := l.(*layers.Dot1Q)
1672 if ok {
1673 return q.Priority
1674 }
1675 }
1676 }
1677 return PriorityNone
1678}
1679
1680// HandleFlowClearFlag to handle flow clear flag during reboot
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301681func (va *VoltApplication) HandleFlowClearFlag(cntx context.Context, deviceID string, serialNum, southBoundID string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301682 logger.Infow(ctx, "Clear All flags for Device", log.Fields{"Device": deviceID, "SerialNum": serialNum, "SBID": southBoundID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301683 dev, ok := va.DevicesDisc.Load(deviceID)
1684 if ok && dev != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301685 logger.Debugw(ctx, "Clear Flags for device", log.Fields{"voltDevice": dev.(*VoltDevice).Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301686 dev.(*VoltDevice).icmpv6GroupAdded = false
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301687 logger.Debugw(ctx, "Clearing DS Icmpv6 Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301688 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1689 dev.(*VoltDevice).ConfiguredVlanForDeviceFlows = util.NewConcurrentMap()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301690 logger.Debugw(ctx, "Clearing DS IGMP Map",
Naveen Sampath04696f72022-06-13 15:19:14 +05301691 log.Fields{"voltDevice": dev.(*VoltDevice).Name})
1692 for k := range dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan {
1693 delete(dev.(*VoltDevice).IgmpDsFlowAppliedForMvlan, k)
1694 }
vinokuma926cb3e2023-03-29 11:41:06 +05301695 // Delete group 1 - ICMPv6/ARP group
Naveen Sampath04696f72022-06-13 15:19:14 +05301696 if err := ProcessIcmpv6McGroup(deviceID, true); err != nil {
1697 logger.Errorw(ctx, "ProcessIcmpv6McGroup failed", log.Fields{"Device": deviceID, "Error": err})
1698 }
1699 } else {
1700 logger.Warnw(ctx, "VoltDevice not found for device ", log.Fields{"deviceID": deviceID})
1701 }
1702
1703 getVpvs := func(key interface{}, value interface{}) bool {
1704 vpvs := value.([]*VoltPortVnet)
1705 for _, vpv := range vpvs {
1706 if vpv.Device == deviceID {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301707 logger.Debugw(ctx, "Clear Flags for vpv",
Naveen Sampath04696f72022-06-13 15:19:14 +05301708 log.Fields{"device": vpv.Device, "port": vpv.Port,
1709 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301710 vpv.ClearAllServiceFlags(cntx)
1711 vpv.ClearAllVpvFlags(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301712
1713 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301714 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05301715 // Also clear service igmp stats
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301716 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301717 }
1718 }
1719 }
1720 return true
1721 }
1722 va.VnetsByPort.Range(getVpvs)
1723
vinokuma926cb3e2023-03-29 11:41:06 +05301724 // Clear Static Group
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301725 va.ReceiverDownInd(cntx, deviceID, StaticPort)
Naveen Sampath04696f72022-06-13 15:19:14 +05301726
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301727 logger.Infow(ctx, "All flags cleared for device", log.Fields{"Device": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301728
vinokuma926cb3e2023-03-29 11:41:06 +05301729 // Reset pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301730 va.RemovePendingGroups(cntx, deviceID, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301731
vinokuma926cb3e2023-03-29 11:41:06 +05301732 // Process all Migrate Service Request - force udpate all profiles since resources are already cleaned up
Naveen Sampath04696f72022-06-13 15:19:14 +05301733 if dev != nil {
1734 triggerForceUpdate := func(key, value interface{}) bool {
1735 msrList := value.(*util.ConcurrentMap)
1736 forceUpdateServices := func(key, value interface{}) bool {
1737 msr := value.(*MigrateServicesRequest)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301738 forceUpdateAllServices(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301739 return true
1740 }
1741 msrList.Range(forceUpdateServices)
1742 return true
1743 }
1744 dev.(*VoltDevice).MigratingServices.Range(triggerForceUpdate)
1745 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301746 va.FetchAndProcessAllMigrateServicesReq(cntx, deviceID, forceUpdateAllServices)
Naveen Sampath04696f72022-06-13 15:19:14 +05301747 }
1748}
1749
vinokuma926cb3e2023-03-29 11:41:06 +05301750// GetPonPortIDFromUNIPort to get pon port id from uni port
Naveen Sampath04696f72022-06-13 15:19:14 +05301751func GetPonPortIDFromUNIPort(uniPortID uint32) uint32 {
1752 ponPortID := (uniPortID & 0x0FF00000) >> 20
1753 return ponPortID
1754}
1755
vinokuma926cb3e2023-03-29 11:41:06 +05301756// ProcessFlowModResultIndication - Processes Flow mod operation indications from controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301757func (va *VoltApplication) ProcessFlowModResultIndication(cntx context.Context, flowStatus intf.FlowStatus) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301758 logger.Debugw(ctx, "Received Flow Mod Result Indication.", log.Fields{"Cookie": flowStatus.Cookie, "Device": flowStatus.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301759 d := va.GetDevice(flowStatus.Device)
1760 if d == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301761 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 +05301762 return
1763 }
1764
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301765 cookieExists := ExecuteFlowEvent(cntx, d, flowStatus.Cookie, flowStatus)
Naveen Sampath04696f72022-06-13 15:19:14 +05301766
1767 if flowStatus.Flow != nil {
1768 flowAdd := (flowStatus.FlowModType == of.CommandAdd)
1769 if !cookieExists && !isFlowStatusSuccess(flowStatus.Status, flowAdd) {
1770 pushFlowFailureNotif(flowStatus)
1771 }
1772 }
1773}
1774
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301775// IsFlowDelThresholdReached - check if the attempts for flow delete has reached threshold or not
1776func (va *VoltApplication) IsFlowDelThresholdReached(cntx context.Context, cookie string, device string) bool {
1777 logger.Debugw(ctx, "Check flow delete threshold", log.Fields{"Cookie": cookie, "Device": device})
1778 d := va.GetDevice(device)
1779 if d == nil {
1780 logger.Warnw(ctx, "Failed to get device during flow delete threshold check", log.Fields{"Cookie": cookie, "Device": device})
1781 return false
1782 }
1783
1784 flowEventMap, err := d.GetFlowEventRegister(of.CommandDel)
1785 if err != nil {
1786 logger.Warnw(ctx, "Flow event map does not exists", log.Fields{"flowMod": of.CommandDel, "Error": err})
1787 return false
1788 }
1789 flowEventMap.MapLock.Lock()
1790 var event interface{}
1791 if event, _ = flowEventMap.Get(cookie); event == nil {
1792 logger.Warnw(ctx, "Event does not exist during flow delete threshold check", log.Fields{"Cookie": cookie})
1793 flowEventMap.MapLock.Unlock()
1794 return false
1795 }
1796 flowEventMap.MapLock.Unlock()
1797 flowEvent := event.(*FlowEvent)
Sridhar Ravindra45589a72024-01-04 17:57:35 +05301798 if vs, ok := flowEvent.eventData.(*VoltService); ok {
1799 vs.ServiceLock.RLock()
1800 defer vs.ServiceLock.RUnlock()
1801 return vs.FlowPushCount[cookie] == controller.GetController().GetMaxFlowRetryAttempt()
1802 }
1803 return false
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301804}
1805
Naveen Sampath04696f72022-06-13 15:19:14 +05301806func pushFlowFailureNotif(flowStatus intf.FlowStatus) {
1807 subFlow := flowStatus.Flow
1808 cookie := subFlow.Cookie
1809 uniPort := cookie >> 16 & 0xFFFFFFFF
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301810 logger.Warnw(ctx, "Flow Failure Notification", log.Fields{"uniPort": uniPort, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301811}
1812
vinokuma926cb3e2023-03-29 11:41:06 +05301813// UpdateMvlanProfilesForDevice to update mvlan profile for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301814func (va *VoltApplication) UpdateMvlanProfilesForDevice(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301815 logger.Debugw(ctx, "Received Update Mvlan Profiles For Device", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301816 checkAndAddMvlanUpdateTask := func(key, value interface{}) bool {
1817 mvp := value.(*MvlanProfile)
1818 if mvp.IsUpdateInProgressForDevice(device) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301819 mvp.UpdateProfile(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301820 }
1821 return true
1822 }
1823 va.MvlanProfilesByName.Range(checkAndAddMvlanUpdateTask)
1824}
1825
1826// TaskInfo structure that is used to store the task Info.
1827type TaskInfo struct {
1828 ID string
1829 Name string
1830 Timestamp string
1831}
1832
1833// GetTaskList to get task list information.
1834func (va *VoltApplication) GetTaskList(device string) map[int]*TaskInfo {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301835 logger.Debugw(ctx, "Received Get Task List", log.Fields{"device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301836 taskList := cntlr.GetController().GetTaskList(device)
1837 taskMap := make(map[int]*TaskInfo)
1838 for i, task := range taskList {
1839 taskID := strconv.Itoa(int(task.TaskID()))
1840 name := task.Name()
1841 timestamp := task.Timestamp()
1842 taskInfo := &TaskInfo{ID: taskID, Name: name, Timestamp: timestamp}
1843 taskMap[i] = taskInfo
1844 }
1845 return taskMap
1846}
1847
1848// UpdateDeviceSerialNumberList to update the device serial number list after device serial number is updated for vnet and mvlan
1849func (va *VoltApplication) UpdateDeviceSerialNumberList(oldOltSlNo string, newOltSlNo string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301850 logger.Debugw(ctx, "Update Device Serial Number List", log.Fields{"oldOltSlNo": oldOltSlNo, "newOltSlNo": newOltSlNo})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301851 voltDevice, _ := va.GetDeviceBySerialNo(oldOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301852
1853 if voltDevice != nil {
1854 // Device is present with old serial number ID
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301855 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 +05301856 } else {
1857 logger.Infow(ctx, "No device present with old serial number", log.Fields{"Serial Number": oldOltSlNo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301858 // Add Serial Number to Blocked Devices List.
1859 cntlr.GetController().AddBlockedDevices(oldOltSlNo)
1860 cntlr.GetController().AddBlockedDevices(newOltSlNo)
1861
1862 updateSlNoForVnet := func(key, value interface{}) bool {
1863 vnet := value.(*VoltVnet)
1864 for i, deviceSlNo := range vnet.VnetConfig.DevicesList {
1865 if deviceSlNo == oldOltSlNo {
1866 vnet.VnetConfig.DevicesList[i] = newOltSlNo
1867 logger.Infow(ctx, "device serial number updated for vnet profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1868 break
1869 }
1870 }
1871 return true
1872 }
1873
1874 updateSlNoforMvlan := func(key interface{}, value interface{}) bool {
1875 mvProfile := value.(*MvlanProfile)
1876 for deviceSlNo := range mvProfile.DevicesList {
1877 if deviceSlNo == oldOltSlNo {
1878 mvProfile.DevicesList[newOltSlNo] = mvProfile.DevicesList[oldOltSlNo]
1879 delete(mvProfile.DevicesList, oldOltSlNo)
1880 logger.Infow(ctx, "device serial number updated for mvlan profile", log.Fields{"Updated Serial Number": deviceSlNo, "Previous Serial Number": oldOltSlNo})
1881 break
1882 }
1883 }
1884 return true
1885 }
1886
1887 va.VnetsByName.Range(updateSlNoForVnet)
1888 va.MvlanProfilesByName.Range(updateSlNoforMvlan)
1889
1890 // Clear the serial number from Blocked Devices List
1891 cntlr.GetController().DelBlockedDevices(oldOltSlNo)
1892 cntlr.GetController().DelBlockedDevices(newOltSlNo)
Naveen Sampath04696f72022-06-13 15:19:14 +05301893 }
1894}
1895
1896// GetVpvsForDsPkt to get vpv for downstream packets
1897func (va *VoltApplication) GetVpvsForDsPkt(cvlan of.VlanType, svlan of.VlanType, clientMAC net.HardwareAddr,
1898 pbit uint8) ([]*VoltPortVnet, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301899 logger.Debugw(ctx, "Received Get Vpvs For Ds Pkt", log.Fields{"Cvlan": cvlan, "Svlan": svlan, "Mac": clientMAC})
Naveen Sampath04696f72022-06-13 15:19:14 +05301900 var matchVPVs []*VoltPortVnet
1901 findVpv := func(key, value interface{}) bool {
1902 vpvs := value.([]*VoltPortVnet)
1903 for _, vpv := range vpvs {
1904 if vpv.isVlanMatching(cvlan, svlan) && vpv.MatchesPriority(pbit) != nil {
1905 var subMac net.HardwareAddr
1906 if NonZeroMacAddress(vpv.MacAddr) {
1907 subMac = vpv.MacAddr
1908 } else if vpv.LearntMacAddr != nil && NonZeroMacAddress(vpv.LearntMacAddr) {
1909 subMac = vpv.LearntMacAddr
1910 } else {
1911 matchVPVs = append(matchVPVs, vpv)
1912 continue
1913 }
1914 if util.MacAddrsMatch(subMac, clientMAC) {
1915 matchVPVs = append([]*VoltPortVnet{}, vpv)
1916 logger.Infow(ctx, "Matching VPV found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "MAC": clientMAC})
1917 return false
1918 }
1919 }
1920 }
1921 return true
1922 }
1923 va.VnetsByPort.Range(findVpv)
1924
1925 if len(matchVPVs) != 1 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301926 logger.Errorw(ctx, "No matching VPV found or multiple vpvs found", log.Fields{"Match VPVs": matchVPVs, "MAC": clientMAC})
1927 return nil, errors.New("no matching VPV found or multiple vpvs found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301928 }
1929 return matchVPVs, nil
1930}
1931
1932// GetMacInPortMap to get PORT value based on MAC key
1933func (va *VoltApplication) GetMacInPortMap(macAddr net.HardwareAddr) string {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301934 logger.Debugw(ctx, "Received Get PORT value based on MAC key", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301935 if NonZeroMacAddress(macAddr) {
1936 va.macPortLock.Lock()
1937 defer va.macPortLock.Unlock()
1938 if port, ok := va.macPortMap[macAddr.String()]; ok {
1939 logger.Debugw(ctx, "found-entry-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1940 return port
1941 }
1942 }
1943 logger.Infow(ctx, "entry-not-found-macportmap", log.Fields{"MacAddr": macAddr.String()})
1944 return ""
1945}
1946
1947// UpdateMacInPortMap to update MAC PORT (key value) information in MacPortMap
1948func (va *VoltApplication) UpdateMacInPortMap(macAddr net.HardwareAddr, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301949 logger.Debugw(ctx, "Update Macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301950 if NonZeroMacAddress(macAddr) {
1951 va.macPortLock.Lock()
1952 va.macPortMap[macAddr.String()] = port
1953 va.macPortLock.Unlock()
1954 logger.Debugw(ctx, "updated-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1955 }
1956}
1957
1958// DeleteMacInPortMap to remove MAC key from MacPortMap
1959func (va *VoltApplication) DeleteMacInPortMap(macAddr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301960 logger.Debugw(ctx, "Delete Mac from Macportmap", log.Fields{"MacAddr": macAddr.String()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301961 if NonZeroMacAddress(macAddr) {
1962 port := va.GetMacInPortMap(macAddr)
1963 va.macPortLock.Lock()
1964 delete(va.macPortMap, macAddr.String())
1965 va.macPortLock.Unlock()
1966 logger.Debugw(ctx, "deleted-from-macportmap", log.Fields{"MacAddr": macAddr.String(), "Port": port})
1967 }
1968}
1969
vinokuma926cb3e2023-03-29 11:41:06 +05301970// AddGroupToPendingPool - adds the IgmpGroup with active group table entry to global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301971func (va *VoltApplication) AddGroupToPendingPool(ig *IgmpGroup) {
1972 var grpMap map[*IgmpGroup]bool
1973 var ok bool
1974
1975 va.PendingPoolLock.Lock()
1976 defer va.PendingPoolLock.Unlock()
1977
1978 logger.Infow(ctx, "Adding IgmpGroup to Global Pending Pool", log.Fields{"GroupID": ig.GroupID, "GroupName": ig.GroupName, "GroupAddr": ig.GroupAddr, "PendingDevices": len(ig.Devices)})
1979 // Do Not Reset any current profile info since group table entry tied to mvlan profile
1980 // The PonVlan is part of set field in group installed
1981 // Hence, Group created is always tied to the same mvlan profile until deleted
1982
1983 for device := range ig.Devices {
1984 key := getPendingPoolKey(ig.Mvlan, device)
1985
1986 if grpMap, ok = va.IgmpPendingPool[key]; !ok {
1987 grpMap = make(map[*IgmpGroup]bool)
1988 }
1989 grpMap[ig] = true
1990
1991 //Add grpObj reference to all associated devices
1992 va.IgmpPendingPool[key] = grpMap
1993 }
1994}
1995
vinokuma926cb3e2023-03-29 11:41:06 +05301996// RemoveGroupFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05301997func (va *VoltApplication) RemoveGroupFromPendingPool(device string, ig *IgmpGroup) bool {
1998 GetApplication().PendingPoolLock.Lock()
1999 defer GetApplication().PendingPoolLock.Unlock()
2000
2001 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)})
2002
2003 key := getPendingPoolKey(ig.Mvlan, device)
2004 if _, ok := va.IgmpPendingPool[key]; ok {
2005 delete(va.IgmpPendingPool[key], ig)
2006 return true
2007 }
2008 return false
2009}
2010
vinokuma926cb3e2023-03-29 11:41:06 +05302011// RemoveGroupsFromPendingPool - removes the group from global pending group pool
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302012func (va *VoltApplication) RemoveGroupsFromPendingPool(cntx context.Context, device string, mvlan of.VlanType) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302013 GetApplication().PendingPoolLock.Lock()
2014 defer GetApplication().PendingPoolLock.Unlock()
2015
2016 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool for given Deivce & Mvlan", log.Fields{"Device": device, "Mvlan": mvlan.String()})
2017
2018 key := getPendingPoolKey(mvlan, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302019 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302020}
2021
vinokuma926cb3e2023-03-29 11:41:06 +05302022// RemoveGroupListFromPendingPool - removes the groups for provided key
Naveen Sampath04696f72022-06-13 15:19:14 +05302023// 1. Deletes the group from device
2024// 2. Delete the IgmpGroup obj and release the group ID to pool
2025// Note: Make sure to obtain PendingPoolLock lock before calling this func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302026func (va *VoltApplication) RemoveGroupListFromPendingPool(cntx context.Context, key string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302027 logger.Infow(ctx, "Remove GroupList from Pending Pool for ", log.Fields{"key": key})
Naveen Sampath04696f72022-06-13 15:19:14 +05302028 if grpMap, ok := va.IgmpPendingPool[key]; ok {
2029 delete(va.IgmpPendingPool, key)
2030 for ig := range grpMap {
2031 for device := range ig.Devices {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302032 ig.DeleteIgmpGroupDevice(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302033 }
2034 }
2035 }
2036}
2037
vinokuma926cb3e2023-03-29 11:41:06 +05302038// RemoveGroupDevicesFromPendingPool - removes the group from global pending group pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302039func (va *VoltApplication) RemoveGroupDevicesFromPendingPool(ig *IgmpGroup) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302040 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)})
2041 for device := range ig.PendingGroupForDevice {
2042 va.RemoveGroupFromPendingPool(device, ig)
2043 }
2044}
2045
vinokuma926cb3e2023-03-29 11:41:06 +05302046// GetGroupFromPendingPool - Returns IgmpGroup obj from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302047func (va *VoltApplication) GetGroupFromPendingPool(mvlan of.VlanType, device string) *IgmpGroup {
Naveen Sampath04696f72022-06-13 15:19:14 +05302048 var ig *IgmpGroup
2049
2050 va.PendingPoolLock.Lock()
2051 defer va.PendingPoolLock.Unlock()
2052
2053 key := getPendingPoolKey(mvlan, device)
2054 logger.Infow(ctx, "Getting IgmpGroup from Global Pending Pool", log.Fields{"Device": device, "Mvlan": mvlan.String(), "Key": key})
2055
vinokuma926cb3e2023-03-29 11:41:06 +05302056 // Gets all IgmpGrp Obj for the device
Naveen Sampath04696f72022-06-13 15:19:14 +05302057 grpMap, ok := va.IgmpPendingPool[key]
2058 if !ok || len(grpMap) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302059 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 +05302060 return nil
2061 }
2062
vinokuma926cb3e2023-03-29 11:41:06 +05302063 // Gets a random obj from available grps
Naveen Sampath04696f72022-06-13 15:19:14 +05302064 for ig = range grpMap {
vinokuma926cb3e2023-03-29 11:41:06 +05302065 // Remove grp obj reference from all devices associated in pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302066 for dev := range ig.Devices {
2067 key := getPendingPoolKey(mvlan, dev)
2068 delete(va.IgmpPendingPool[key], ig)
2069 }
2070
vinokuma926cb3e2023-03-29 11:41:06 +05302071 // Safety check to avoid re-allocating group already in use
Naveen Sampath04696f72022-06-13 15:19:14 +05302072 if ig.NumDevicesActive() == 0 {
2073 return ig
2074 }
2075
vinokuma926cb3e2023-03-29 11:41:06 +05302076 // Iteration will continue only if IG is not allocated
Naveen Sampath04696f72022-06-13 15:19:14 +05302077 }
2078 return nil
2079}
2080
vinokuma926cb3e2023-03-29 11:41:06 +05302081// RemovePendingGroups - removes all pending groups for provided reference from global pending pool
Naveen Sampath04696f72022-06-13 15:19:14 +05302082// reference - mvlan/device ID
2083// isRefDevice - true - Device as reference
vinokuma926cb3e2023-03-29 11:41:06 +05302084// false - Mvlan as reference
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302085func (va *VoltApplication) RemovePendingGroups(cntx context.Context, reference string, isRefDevice bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302086 va.PendingPoolLock.Lock()
2087 defer va.PendingPoolLock.Unlock()
2088
2089 logger.Infow(ctx, "Removing IgmpGroups from Global Pending Pool", log.Fields{"Reference": reference, "isRefDevice": isRefDevice})
2090
vinokuma926cb3e2023-03-29 11:41:06 +05302091 // Pending Pool key: "<mvlan>_<DeviceID>""
Naveen Sampath04696f72022-06-13 15:19:14 +05302092 paramPosition := 0
2093 if isRefDevice {
2094 paramPosition = 1
2095 }
2096
2097 // 1.Remove the Entry from pending pool
2098 // 2.Deletes the group from device
2099 // 3.Delete the IgmpGroup obj and release the group ID to pool
2100 for key := range va.IgmpPendingPool {
2101 keyParams := strings.Split(key, "_")
2102 if keyParams[paramPosition] == reference {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302103 va.RemoveGroupListFromPendingPool(cntx, key)
Naveen Sampath04696f72022-06-13 15:19:14 +05302104 }
2105 }
2106}
2107
2108func getPendingPoolKey(mvlan of.VlanType, device string) string {
2109 return mvlan.String() + "_" + device
2110}
2111
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302112func (va *VoltApplication) removeExpiredGroups(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302113 logger.Info(ctx, "Remove expired Igmp Groups")
Naveen Sampath04696f72022-06-13 15:19:14 +05302114 removeExpiredGroups := func(key interface{}, value interface{}) bool {
2115 ig := value.(*IgmpGroup)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302116 ig.removeExpiredGroupFromDevice(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302117 return true
2118 }
2119 va.IgmpGroups.Range(removeExpiredGroups)
2120}
2121
vinokuma926cb3e2023-03-29 11:41:06 +05302122// TriggerPendingProfileDeleteReq - trigger pending profile delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302123func (va *VoltApplication) TriggerPendingProfileDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302124 logger.Infow(ctx, "Trigger Pending Profile Delete for device", log.Fields{"Device": device})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302125 va.TriggerPendingServiceDeactivateReq(cntx, device)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302126 va.TriggerPendingServiceDeleteReq(cntx, device)
2127 va.TriggerPendingVpvDeleteReq(cntx, device)
2128 va.TriggerPendingVnetDeleteReq(cntx, device)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302129 logger.Infow(ctx, "All Pending Profile Delete triggered for device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302130}
2131
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302132// TriggerPendingServiceDeactivateReq - trigger pending service deactivate request
2133func (va *VoltApplication) TriggerPendingServiceDeactivateReq(cntx context.Context, device string) {
2134 logger.Infow(ctx, "Pending Services to be deactivated", log.Fields{"Count": len(va.ServicesToDeactivate)})
2135 for serviceName := range va.ServicesToDeactivate {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302136 logger.Debugw(ctx, "Trigger Service Deactivate", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302137 if vs := va.GetService(serviceName); vs != nil {
2138 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302139 logger.Infow(ctx, "Triggering Pending Service Deactivate", log.Fields{"Service": vs.Name})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302140 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
2141 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302142 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 +05302143 continue
2144 }
2145
2146 vpv.DelTrapFlows(cntx)
2147 vs.DelHsiaFlows(cntx)
2148 vs.WriteToDb(cntx)
2149 vpv.ClearServiceCounters(cntx)
2150 }
2151 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302152 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302153 }
2154 }
2155}
2156
vinokuma926cb3e2023-03-29 11:41:06 +05302157// TriggerPendingServiceDeleteReq - trigger pending service delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302158func (va *VoltApplication) TriggerPendingServiceDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302159 logger.Infow(ctx, "Pending Services to be deleted", log.Fields{"Count": len(va.ServicesToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302160 for serviceName := range va.ServicesToDelete {
2161 logger.Debugw(ctx, "Trigger Service Delete", log.Fields{"Service": serviceName})
2162 if vs := va.GetService(serviceName); vs != nil {
2163 if vs.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302164 logger.Infow(ctx, "Triggering Pending Service delete", log.Fields{"Service": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302165 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302166 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302167 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302168 }
2169 }
2170 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302171 logger.Warnw(ctx, "Pending Service Not found", log.Fields{"Service": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302172 }
2173 }
2174}
2175
vinokuma926cb3e2023-03-29 11:41:06 +05302176// TriggerPendingVpvDeleteReq - trigger pending VPV delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302177func (va *VoltApplication) TriggerPendingVpvDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302178 logger.Infow(ctx, "Pending VPVs to be deleted", log.Fields{"Count": len(va.VoltPortVnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302179 for vpv := range va.VoltPortVnetsToDelete {
2180 if vpv.Device == device {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302181 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 +05302182 va.DelVnetFromPort(cntx, vpv.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05302183 }
2184 }
2185}
2186
vinokuma926cb3e2023-03-29 11:41:06 +05302187// TriggerPendingVnetDeleteReq - trigger pending vnet delete request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302188func (va *VoltApplication) TriggerPendingVnetDeleteReq(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302189 logger.Infow(ctx, "Pending Vnets to be deleted", log.Fields{"Count": len(va.VnetsToDelete)})
Naveen Sampath04696f72022-06-13 15:19:14 +05302190 for vnetName := range va.VnetsToDelete {
2191 if vnetIntf, _ := va.VnetsByName.Load(vnetName); vnetIntf != nil {
2192 vnet := vnetIntf.(*VoltVnet)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302193 if d, _ := va.GetDeviceBySerialNo(vnet.PendingDeviceToDelete); d != nil && d.SerialNum == vnet.PendingDeviceToDelete {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302194 logger.Infow(ctx, "Triggering Pending Vnet flows delete", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302195 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, vnet.PendingDeviceToDelete)
Naveen Sampath04696f72022-06-13 15:19:14 +05302196 va.deleteVnetConfig(vnet)
2197 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302198 logger.Warnw(ctx, "Vnet Delete Failed : Device Not Found", log.Fields{"Vnet": vnet.Name, "Device": vnet.PendingDeviceToDelete})
Naveen Sampath04696f72022-06-13 15:19:14 +05302199 }
2200 }
2201 }
2202}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302203
2204type OltFlowService struct {
vinokuma926cb3e2023-03-29 11:41:06 +05302205 DefaultTechProfileID int `json:"defaultTechProfileId"`
Akash Sonia8246972023-01-03 10:37:08 +05302206 EnableDhcpOnNni bool `json:"enableDhcpOnNni"`
Akash Sonia8246972023-01-03 10:37:08 +05302207 EnableIgmpOnNni bool `json:"enableIgmpOnNni"`
2208 EnableEapol bool `json:"enableEapol"`
2209 EnableDhcpV6 bool `json:"enableDhcpV6"`
2210 EnableDhcpV4 bool `json:"enableDhcpV4"`
2211 RemoveFlowsOnDisable bool `json:"removeFlowsOnDisable"`
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302212}
2213
2214func (va *VoltApplication) UpdateOltFlowService(cntx context.Context, oltFlowService OltFlowService) {
2215 logger.Infow(ctx, "UpdateOltFlowService", log.Fields{"oldValue": va.OltFlowServiceConfig, "newValue": oltFlowService})
2216 va.OltFlowServiceConfig = oltFlowService
2217 b, err := json.Marshal(va.OltFlowServiceConfig)
2218 if err != nil {
2219 logger.Warnw(ctx, "Failed to Marshal OltFlowServiceConfig", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2220 return
2221 }
2222 _ = db.PutOltFlowService(cntx, string(b))
2223}
Akash Sonia8246972023-01-03 10:37:08 +05302224
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302225// RestoreOltFlowService to read from the DB and restore olt flow service config
2226func (va *VoltApplication) RestoreOltFlowService(cntx context.Context) {
2227 oltflowService, err := db.GetOltFlowService(cntx)
2228 if err != nil {
2229 logger.Warnw(ctx, "Failed to Get OltFlowServiceConfig from DB", log.Fields{"Error": err})
2230 return
2231 }
2232 err = json.Unmarshal([]byte(oltflowService), &va.OltFlowServiceConfig)
2233 if err != nil {
2234 logger.Warn(ctx, "Unmarshal of oltflowService failed")
2235 return
2236 }
2237 logger.Infow(ctx, "updated OltFlowServiceConfig from DB", log.Fields{"OltFlowServiceConfig": va.OltFlowServiceConfig})
2238}
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302239
Akash Soni87a19072023-02-28 00:46:59 +05302240func (va *VoltApplication) UpdateDeviceConfig(cntx context.Context, deviceConfig *DeviceConfig) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302241 logger.Infow(ctx, "Received UpdateDeviceConfig", log.Fields{"DeviceInfo": deviceConfig})
Akash Soni87a19072023-02-28 00:46:59 +05302242 var dc *DeviceConfig
2243 va.DevicesConfig.Store(deviceConfig.SerialNumber, deviceConfig)
2244 err := dc.WriteDeviceConfigToDb(cntx, deviceConfig.SerialNumber, deviceConfig)
2245 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302246 logger.Warnw(ctx, "DB update for device config failed", log.Fields{"err": err})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302247 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302248 logger.Debugw(ctx, "Added OLT configurations", log.Fields{"DeviceInfo": deviceConfig})
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302249 // If device is already discovered update the VoltDevice structure
Akash Soni87a19072023-02-28 00:46:59 +05302250 device, id := va.GetDeviceBySerialNo(deviceConfig.SerialNumber)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302251 if device != nil {
Akash Soni87a19072023-02-28 00:46:59 +05302252 device.NniDhcpTrapVid = of.VlanType(deviceConfig.NniDhcpTrapVid)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302253 va.DevicesDisc.Store(id, device)
2254 }
2255}