blob: 80e82128226377b7cc2bdcedf1605ed6b362c8d7 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14 */
15
16package application
17
18import (
Akash Sonia8246972023-01-03 10:37:08 +053019 "context"
Naveen Sampath04696f72022-06-13 15:19:14 +053020 "encoding/json"
21 "errors"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +053022 "fmt"
Naveen Sampath04696f72022-06-13 15:19:14 +053023 "net"
vinokuma04dc9f82023-07-31 15:47:49 +053024 "reflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053025 "strconv"
26 "sync"
27 "time"
28
Akash Sonia8246972023-01-03 10:37:08 +053029 //errorCodes "voltha-go-controller/internal/pkg/errorcodes"
30
Naveen Sampath04696f72022-06-13 15:19:14 +053031 "github.com/google/gopacket"
32 "github.com/google/gopacket/layers"
33 "go.uber.org/atomic"
34
Akash Sonia8246972023-01-03 10:37:08 +053035 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053036 "voltha-go-controller/internal/pkg/controller"
37 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053038
39 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053040 "voltha-go-controller/internal/pkg/of"
41 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053042 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053043)
44
45const (
46 // ICMPv6ArpGroupID constant
47 ICMPv6ArpGroupID uint32 = 1
48
49 // Radisys vendor id constant
50 Radisys string = "Radisys"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053051
52 // DPU_MGMT_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053053 DpuMgmtTraffic string = "DPU_MGMT_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053054
55 // DPU_ANCP_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053056 DpuAncpTraffic string = "DPU_ANCP_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053057
58 // FTTB_SUBSCRIBER_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053059 FttbSubscriberTraffic string = "FTTB_SUBSCRIBER_TRAFFIC"
Naveen Sampath04696f72022-06-13 15:19:14 +053060)
61
62var (
63 //BroadcastMAC - Broadcast MAC Address
64 BroadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
65)
66
67// NonZeroMacAddress utility to identify if the MAC address is non-zero.
68// We use zero MAC address as an unset MAC address
69func NonZeroMacAddress(h net.HardwareAddr) bool {
70 for i := 0; i < 6; i++ {
71 if h[i] != 0 {
72 return true
73 }
74 }
75 return false
76}
77
78// VNET package manages the different virtual networks that are part of the
79// the network. In the case of VOLT, the networks can be single tagged or
80// double tagged networks. In addition, the networks may be used for unicast
81// and multicast traffic. The unicast traffic further has two models, the
82// 1:1 and N:1 model. In case of a 1:1 model, the outer tag is same for many
83// subscribers and the inner tag is unique to each subscriber for the same
84// outer tag. The N:1 uses the same inner and outer tags, or for that matter
85// a single tag that can also be shared by subscribers. The VNET implementation
86// manages all these possibilities and the associated configuration.
87
88const (
89 // PbitMatchNone constant
90 PbitMatchNone of.PbitType = 8
91 // PbitMatchAll constant
92 PbitMatchAll of.PbitType = 0xFF
93)
94
95// SVlan - Value of the outer tag if double tagged or the only tag if single
96// tagged
97// SVlanTpid - SVlan Tag Protocol Identifier
98// CVlan - Value of the inner tag. Set to VlanNone if single tagged
99// DhcpRelay - Set to true if the DHCP relay is enabled on the virtual network
100// MacLearning - Set to true if the flows should include MAC address
101// UsDhcpPbit - The pbit used for US DHCP packets
102// DsDhcpPbit - The pbit used for DS DHCP packets
103
104// VnetConfig structure
105type VnetConfig struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530106 CtrlPktPbitRemark map[of.PbitType]of.PbitType
Naveen Sampath04696f72022-06-13 15:19:14 +0530107 Name string
vinokuma926cb3e2023-03-29 11:41:06 +0530108 VnetType string
Naveen Sampath04696f72022-06-13 15:19:14 +0530109 Encapsulation string
vinokuma926cb3e2023-03-29 11:41:06 +0530110 DevicesList []string //List of serial number of devices on which this vnet is applied
Naveen Sampath04696f72022-06-13 15:19:14 +0530111 UsDhcpPbit []of.PbitType
112 DsDhcpPbit []of.PbitType
113 UsIGMPPbit []of.PbitType
114 DsIGMPPbit []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530115 ONTEtherTypeClassification int
116 MacLearning MacLearningType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530117 UsPonCTagPriority of.PbitType
118 UsPonSTagPriority of.PbitType
119 DsPonCTagPriority of.PbitType
120 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530121 SVlan of.VlanType
122 CVlan of.VlanType
123 UniVlan of.VlanType
124 SVlanTpid layers.EthernetType
125 VlanControl VlanControl
126 DhcpRelay bool
127 ArpLearning bool
128 AllowTransparent bool
129 PppoeIa bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530130}
131
132// VnetOper structure
133type VnetOper struct {
134 PendingDeleteFlow map[string]map[string]bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530135 AssociatedPorts map[string]bool `json:"-"`
vinokuma926cb3e2023-03-29 11:41:06 +0530136 PendingDeviceToDelete string
137 VnetLock sync.RWMutex `json:"-"`
138 VnetPortLock sync.RWMutex `json:"-"`
139 DeleteInProgress bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530140}
141
142// VoltVnet sructure
143type VoltVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530144 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530145 VnetConfig
146 VnetOper
Naveen Sampath04696f72022-06-13 15:19:14 +0530147}
148
149const (
150 // EncapsulationPPPoEIA constant
151 EncapsulationPPPoEIA string = "PPPoE-IA"
152 // EncapsulationPPPoE constant
153 EncapsulationPPPoE string = "PPPoE"
154 // EncapsulationIPoE constant
155 EncapsulationIPoE string = "IPoE"
156)
157
158// NewVoltVnet is constructor for the VNET structure
159func NewVoltVnet(cfg VnetConfig) *VoltVnet {
160 var vv VoltVnet
161 vv.VnetConfig = cfg
162 if vv.PendingDeleteFlow == nil {
163 vv.PendingDeleteFlow = make(map[string]map[string]bool)
164 }
165 vv.DeleteInProgress = false
166 if cfg.Encapsulation == EncapsulationPPPoEIA {
167 vv.PppoeIa = true
168 }
169 vv.AssociatedPorts = make(map[string]bool)
170 return &vv
171}
172
vinokuma926cb3e2023-03-29 11:41:06 +0530173// associatePortToVnet - associate a port to Vnet
Naveen Sampath04696f72022-06-13 15:19:14 +0530174func (vv *VoltVnet) associatePortToVnet(port string) {
175 vv.VnetPortLock.Lock()
176 if vv.AssociatedPorts == nil {
177 vv.AssociatedPorts = make(map[string]bool)
178 }
179 vv.AssociatedPorts[port] = true
180 vv.VnetPortLock.Unlock()
181}
182
vinokuma926cb3e2023-03-29 11:41:06 +0530183// disassociatePortFromVnet - disassociate a port from Vnet and return true if the association map is empty
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530184func (vv *VoltVnet) disassociatePortFromVnet(cntx context.Context, device string, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530185 logger.Infow(ctx, "Disassociate Port from Vnet", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530186 vv.VnetPortLock.Lock()
187 delete(vv.AssociatedPorts, port)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530188 logger.Debugw(ctx, "Disassociated Port from Vnet", log.Fields{"Device": device, "Port": port, "Vnet": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow, "AssociatedPorts": vv.AssociatedPorts, "DeleteFlag": vv.DeleteInProgress})
Naveen Sampath04696f72022-06-13 15:19:14 +0530189 vv.VnetPortLock.Unlock()
190
191 if vv.DeleteInProgress {
192 if !vv.isAssociatedPortsPresent() {
193 if len(vv.PendingDeleteFlow[device]) == 0 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530194 logger.Debugw(ctx, "Deleting Vnet", log.Fields{"Name": vv.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530195 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530196 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530197 } else {
198 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow})
199 }
200 } else {
201 vv.VnetPortLock.RLock()
202 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts})
203 vv.VnetPortLock.RUnlock()
204 }
205 }
206}
207
208func (vv *VoltVnet) isAssociatedPortsPresent() bool {
209 vv.VnetPortLock.RLock()
210 defer vv.VnetPortLock.RUnlock()
211 return len(vv.AssociatedPorts) != 0
212}
213
214// WriteToDb commit the VNET to the database
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530215func (vv *VoltVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530216 if vv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530217 logger.Warnw(ctx, "Skipping Redis Update for Vnet, Vnet delete in progress", log.Fields{"Vnet": vv.Name, "SVlan": vv.SVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530218 return
219 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530220 vv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530221}
222
vinokuma926cb3e2023-03-29 11:41:06 +0530223// ForceWriteToDb force commit a vnet to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530224func (vv *VoltVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530225 vv.VnetPortLock.RLock()
226 defer vv.VnetPortLock.RUnlock()
227 vv.Version = database.PresentVersionMap[database.VnetPath]
228 logger.Debugw(ctx, "Updating VNET....", log.Fields{"vnet": vv})
229 if b, err := json.Marshal(vv); err == nil {
Akash Sonia8246972023-01-03 10:37:08 +0530230 if err := db.PutVnet(cntx, vv.Name, string(b)); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530231 logger.Warnw(ctx, "Add Vnet to DB failed", log.Fields{"Vnet": vv.Name, "SVlan": vv.SVlan, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530232 }
233 }
234}
235
236// VnetKey creates the key using the two VLAN tags
237// We append the two VLAN tags to create a single key
238func VnetKey(otag of.VlanType, itag of.VlanType, utag of.VlanType) string {
239 return strconv.Itoa(int(otag)) + "-" + strconv.Itoa(int(itag)) + "-" + strconv.Itoa(int(utag))
240}
241
242// GetVnet get VNET configuration related functionality associated with VOLT application
243func (va *VoltApplication) GetVnet(otag of.VlanType, itag of.VlanType, utag of.VlanType) *VoltVnet {
244 // When matching VNET, it is expected to match first just the outer
245 // tag, and then the combination to make sure there is no conflict
246 // for the new configuration.
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530247 logger.Debugw(ctx, "Get Vnet configuration", log.Fields{"SVlan": otag, "CVlan": itag, "UniVlan": utag})
Naveen Sampath04696f72022-06-13 15:19:14 +0530248 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, of.VlanNone, utag)); ok {
249 return vnet.(*VoltVnet)
250 }
251 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, itag, utag)); ok {
252 return vnet.(*VoltVnet)
253 }
254 return nil
255}
256
257// The VNET may also be assigned name for easier references. For now,
258// the VNET is mainly identified by the two VLANs.
259
260// GetVnetByName to get vnet by name
261func (va *VoltApplication) GetVnetByName(name string) *VoltVnet {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530262 logger.Debugw(ctx, "Get Vnet by Name", log.Fields{"Name": name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530263 if vnet, ok := va.VnetsByName.Load(name); ok {
264 return vnet.(*VoltVnet)
265 }
266 return nil
267}
268
269// storeVnetConfig to store vnet config
270func (va *VoltApplication) storeVnetConfig(cfg VnetConfig, vv *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530271 logger.Debugw(ctx, "Store Vnet config", log.Fields{"Name": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530272 var vnetMap *util.ConcurrentMap
273
274 va.VnetsByTag.Store(VnetKey(cfg.SVlan, cfg.CVlan, cfg.UniVlan), vv)
275 va.VnetsByName.Store(cfg.Name, vv)
276
277 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vv.SVlan); !ok {
278 vnetMap = util.NewConcurrentMap()
279 } else {
280 vnetMap = vnetMapIntf.(*util.ConcurrentMap)
281 }
282 vnetMap.Set(vv, true)
283 va.VnetsBySvlan.Set(vv.SVlan, vnetMap)
284}
285
286// deleteVnetConfig to delete vnet config
287func (va *VoltApplication) deleteVnetConfig(vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530288 logger.Debugw(ctx, "Delete Vnet config", log.Fields{"Name": vnet.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530289 va.VnetsByTag.Delete(VnetKey(vnet.SVlan, vnet.CVlan, vnet.UniVlan))
290 va.VnetsByName.Delete(vnet.Name)
291
292 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vnet.SVlan); ok {
293 vnetMap := vnetMapIntf.(*util.ConcurrentMap)
294 vnetMap.Remove(vnet)
295 va.VnetsBySvlan.Set(vnet.SVlan, vnetMap)
296 }
297}
298
299// AddVnet to add a VNET to the list of VNETs configured.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530300func (va *VoltApplication) AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530301 logger.Debugw(ctx, "Add Vnet config", log.Fields{"Name": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530302 AppMutex.VnetMutex.Lock()
303 var vv *VoltVnet
304 devicesToHandle := []string{}
305 vv = va.GetVnetByName(cfg.Name)
306 if vv != nil {
307 //Could be for another OLT or could be case of backup-restore
308 for _, serialNum := range cfg.DevicesList {
309 if isDeviceInList(serialNum, vv.DevicesList) {
310 //This is backup restore scenario, just update the profile
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530311 logger.Infow(ctx, "Add Vnet : Profile Name already exists with OLT, update-the-profile", log.Fields{"SerialNum": serialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +0530312 continue
313 }
314 devicesToHandle = append(devicesToHandle, serialNum)
315 }
316 if len(devicesToHandle) == 0 {
Akash Sonief452f12024-12-12 18:20:28 +0530317 logger.Warnw(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530318 AppMutex.VnetMutex.Unlock()
319 return nil
320 }
321 }
322
323 if vv == nil {
324 vv = NewVoltVnet(cfg)
325 if oper != nil {
326 vv.PendingDeleteFlow = oper.PendingDeleteFlow
327 vv.DeleteInProgress = oper.DeleteInProgress
328 vv.AssociatedPorts = oper.AssociatedPorts
329 vv.PendingDeviceToDelete = oper.PendingDeviceToDelete
330 }
331 devicesToHandle = append(devicesToHandle, cfg.DevicesList...)
332 } else {
333 vv.DevicesList = append(vv.DevicesList, devicesToHandle...)
334 }
335
336 va.storeVnetConfig(cfg, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530337 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530338
339 logger.Infow(ctx, "Added VNET TO DB", log.Fields{"cfg": cfg, "devicesToHandle": devicesToHandle})
340
341 //va.PushDevFlowForVlan(vv)
342 AppMutex.VnetMutex.Unlock()
343 return nil
344}
345
346// DelVnet to delete a VNET from the list of VNETs configured
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530347func (va *VoltApplication) DelVnet(cntx context.Context, name, deviceSerialNum string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530348 logger.Infow(ctx, "Deleting Vnet", log.Fields{"Vnet": name})
349 AppMutex.VnetMutex.Lock()
350 if vnetIntf, ok := va.VnetsByName.Load(name); ok {
351 vnet := vnetIntf.(*VoltVnet)
vinokuma926cb3e2023-03-29 11:41:06 +0530352 // Delete from mvp list
Naveen Sampath04696f72022-06-13 15:19:14 +0530353 vnet.DevicesList = util.RemoveFromSlice(vnet.DevicesList, deviceSerialNum)
354
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530355 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, deviceSerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +0530356 if len(vnet.DevicesList) == 0 {
357 vnet.DeleteInProgress = true
358 vnet.PendingDeviceToDelete = deviceSerialNum
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530359 vnet.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530360 vnet.VnetPortLock.RLock()
361 if len(vnet.PendingDeleteFlow) == 0 && !vnet.isAssociatedPortsPresent() {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530362 logger.Debugw(ctx, "Deleting Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
Naveen Sampath04696f72022-06-13 15:19:14 +0530363 va.deleteVnetConfig(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530364 _ = db.DelVnet(cntx, vnet.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530365 } else {
366 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
367 }
368 vnet.VnetPortLock.RUnlock()
369 } else {
vinokuma926cb3e2023-03-29 11:41:06 +0530370 // Update the devicelist in db
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530371 vnet.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530372 }
373 }
vinokuma926cb3e2023-03-29 11:41:06 +0530374 // TODO: if no vnets are present on device remove icmpv6 group from device
Naveen Sampath04696f72022-06-13 15:19:14 +0530375 AppMutex.VnetMutex.Unlock()
376 return nil
377}
378
379// UpdateVnet to update the VNET with associated service count
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530380func (va *VoltApplication) UpdateVnet(cntx context.Context, vv *VoltVnet) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530381 va.storeVnetConfig(vv.VnetConfig, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530382 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530383 logger.Infow(ctx, "Updated VNET TO DB", log.Fields{"vv": vv.VnetConfig})
384 return nil
385}
386
387// ------------------------------------------------------------
388// Manifestation of a VNET on a port is handled below
389// ------------------------------------------------------------
390//
391// The VNET on a port handles everything that is done for a VNET
392// such as DHCP relay state machine, MAC addresses, IP addresses
393// learnt, so on.
394
395// DhcpStatus type
396type DhcpStatus uint8
397
398const (
399 // DhcpStatusNone constant
400 DhcpStatusNone DhcpStatus = 0
401 // DhcpStatusAcked constant
402 DhcpStatusAcked DhcpStatus = 1
403 // DhcpStatusNacked constant
404 DhcpStatusNacked DhcpStatus = 2
405 // EthTypeNone constant
406 EthTypeNone int = 0
407 // EthTypeIPoE constant
408 EthTypeIPoE int = 1
409 // EthTypePPPoE constant
410 EthTypePPPoE int = 2
411)
412
413// VoltPortVnet structure
414type VoltPortVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530415 PendingDeleteFlow map[string]bool
416 servicesCount *atomic.Uint64
417 services sync.Map
Naveen Sampath04696f72022-06-13 15:19:14 +0530418 Device string
419 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +0530420 VnetName string
vinokuma926cb3e2023-03-29 11:41:06 +0530421 VnetType string
422 MvlanProfileName string
423 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530424 DhcpExpiryTime time.Time
425 Dhcp6ExpiryTime time.Time
Naveen Sampath04696f72022-06-13 15:19:14 +0530426 Ipv4Addr net.IP
427 Ipv6Addr net.IP
428 MacAddr net.HardwareAddr
429 LearntMacAddr net.HardwareAddr
vinokuma926cb3e2023-03-29 11:41:06 +0530430 CircuitID []byte //Will not be used
431 RemoteID []byte //Will not be used
432 VpvLock sync.Mutex `json:"-"`
433 PendingFlowLock sync.RWMutex `json:"-"`
434 SchedID int
Naveen Sampath04696f72022-06-13 15:19:14 +0530435 ONTEtherTypeClassification int
vinokuma926cb3e2023-03-29 11:41:06 +0530436 MacLearning MacLearningType
437 PonPort uint32
438 McastUsMeterID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530439 McastTechProfileID uint16
440 McastPbit of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530441 SVlanTpid layers.EthernetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530442 DhcpPbit of.PbitType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530443 UsPonCTagPriority of.PbitType
444 UsPonSTagPriority of.PbitType
445 DsPonCTagPriority of.PbitType
446 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530447 SVlan of.VlanType
448 CVlan of.VlanType
449 UniVlan of.VlanType
450 VlanControl VlanControl
451 RelayState DhcpRelayState
452 DhcpStatus DhcpStatus
453 PPPoeState PppoeIaState
454 RelayStatev6 Dhcpv6RelayState
455 DHCPv6DUID [MaxLenDhcpv6DUID]byte
456 DhcpRelay bool
457 ArpRelay bool
458 PppoeIa bool
459 DeleteInProgress bool
460 Blocked bool
461 AllowTransparent bool
462 IgmpEnabled bool
463 IgmpFlowsApplied bool
464 McastService bool
465 FlowsApplied bool
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530466 IsOption82Enabled bool //Will not be used
Naveen Sampath04696f72022-06-13 15:19:14 +0530467}
468
vinokuma926cb3e2023-03-29 11:41:06 +0530469// VlanControl vlan control type
Naveen Sampath04696f72022-06-13 15:19:14 +0530470type VlanControl uint8
471
472const (
473 // None constant
474 // ONU and OLT will passthrough UNIVLAN as is to BNG
475 None VlanControl = iota
476
477 // ONUCVlanOLTSVlan constant
478 // Tagged traffic, ONU will replace UNIVLAN with CVLAN and OLT will add SVLAN
479 // Untagged traffic, ONU will add CVLAN and OLT will add SVLAN
480 ONUCVlanOLTSVlan
481
482 // OLTCVlanOLTSVlan constant
483 // Tagged traffic, ONU will passthrough UNIVLAN as is to OLT and
484 // OLT will replace UNIVLAN with CVLAN and add SVLAN
485 OLTCVlanOLTSVlan
486
487 // ONUCVlan constant
488 // Tagged traffic, ONU will replace UNIVLAN with CVLAN
489 // Untagged traffic, ONU will add CVLAN
490 ONUCVlan
491
492 // OLTSVlan constant
493 // UnTagged traffic, OLT will add the SVLAN
494 OLTSVlan
495)
496
497// NewVoltPortVnet is constructor for VoltPortVnet
498func NewVoltPortVnet(vnet *VoltVnet) *VoltPortVnet {
499 var vpv VoltPortVnet
500
501 vpv.VnetName = vnet.Name
502 vpv.SVlan = vnet.SVlan
503 vpv.CVlan = vnet.CVlan
504 vpv.UniVlan = vnet.UniVlan
505 vpv.SVlanTpid = vnet.SVlanTpid
506 vpv.DhcpRelay = vnet.DhcpRelay
507 vpv.DhcpStatus = DhcpStatusNone
508 vpv.PPPoeState = PppoeIaStateNone
509 vpv.ArpRelay = vnet.ArpLearning
510 vpv.PppoeIa = vnet.PppoeIa
511 vpv.VlanControl = vnet.VlanControl
512 vpv.ONTEtherTypeClassification = vnet.ONTEtherTypeClassification
513 vpv.AllowTransparent = vnet.AllowTransparent
514 vpv.FlowsApplied = false
515 vpv.IgmpEnabled = false
516 vpv.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
517 vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Naveen Sampath04696f72022-06-13 15:19:14 +0530518 vpv.servicesCount = atomic.NewUint64(0)
519 vpv.SchedID = 0
520 vpv.PendingDeleteFlow = make(map[string]bool)
521 vpv.DhcpPbit = vnet.UsDhcpPbit[0]
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530522 vpv.UsPonCTagPriority = vnet.UsPonCTagPriority
523 vpv.UsPonSTagPriority = vnet.UsPonSTagPriority
524 vpv.DsPonCTagPriority = vnet.UsPonCTagPriority
525 vpv.DsPonSTagPriority = vnet.UsPonSTagPriority
526
527 vpv.VnetType = vnet.VnetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530528 return &vpv
529}
530
531func (vpv *VoltPortVnet) setDevice(device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530532 logger.Debugw(ctx, "Set Device", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530533 if vpv.Device != device && vpv.Device != "" {
534 GetApplication().DisassociateVpvsFromDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530535 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530536 vpv.printAssociatedVPVs(false)
537 }
538
Tinoj Josephec742f62022-09-29 19:11:10 +0530539 logger.Infow(ctx, "Associating VPV and Device", log.Fields{"Device": device, "Port": vpv.Port, "SVlan": vpv.SVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530540
541 vpv.Device = device
542 GetApplication().AssociateVpvsToDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530543 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530544 vpv.printAssociatedVPVs(true)
545}
546
vinokuma926cb3e2023-03-29 11:41:06 +0530547// TODO - Nav - Temp
Naveen Sampath04696f72022-06-13 15:19:14 +0530548func (vpv *VoltPortVnet) printAssociatedVPVs(add bool) {
549 logger.Infow(ctx, "Start----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
550 if vMap := GetApplication().GetAssociatedVpvsForDevice(vpv.Device, vpv.SVlan); vMap != nil {
551 vMap.Range(func(key, value interface{}) bool {
552 vpvEntry := key.(*VoltPortVnet)
553 logger.Infow(ctx, "Associated VPVs", log.Fields{"SVlan": vpvEntry.SVlan, "CVlan": vpvEntry.CVlan, "UniVlan": vpvEntry.UniVlan})
554 return true
555 })
556 }
557 logger.Infow(ctx, "End----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
Naveen Sampath04696f72022-06-13 15:19:14 +0530558}
559
560// GetCircuitID : The interface to be satisfied by the VoltPortVnet to be a DHCP relay
561// session is implemented below. The main functions still remain in
562// the service.go file.
563func (vpv *VoltPortVnet) GetCircuitID() []byte {
564 return []byte(vpv.CircuitID)
565}
566
567// GetRemoteID to get remote id
568func (vpv *VoltPortVnet) GetRemoteID() []byte {
569 return []byte(vpv.RemoteID)
570}
571
572// GetDhcpState to get dhcp state
573func (vpv *VoltPortVnet) GetDhcpState() DhcpRelayState {
574 return vpv.RelayState
575}
576
577// SetDhcpState to set the dhcp state
578func (vpv *VoltPortVnet) SetDhcpState(state DhcpRelayState) {
579 vpv.RelayState = state
580}
581
582// GetPppoeIaState to get pppoeia state
583func (vpv *VoltPortVnet) GetPppoeIaState() PppoeIaState {
584 return vpv.PPPoeState
585}
586
587// SetPppoeIaState to set pppoeia state
588func (vpv *VoltPortVnet) SetPppoeIaState(state PppoeIaState) {
589 vpv.PPPoeState = state
590}
591
592// GetDhcpv6State to get dhcpv6 state
593func (vpv *VoltPortVnet) GetDhcpv6State() Dhcpv6RelayState {
594 return vpv.RelayStatev6
595}
596
597// SetDhcpv6State to set dhcpv6 state
598func (vpv *VoltPortVnet) SetDhcpv6State(state Dhcpv6RelayState) {
599 vpv.RelayStatev6 = state
600}
601
602// DhcpResultInd for dhcp result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530603func (vpv *VoltPortVnet) DhcpResultInd(cntx context.Context, res *layers.DHCPv4) {
604 vpv.ProcessDhcpResult(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530605}
606
607// Dhcpv6ResultInd for dhcpv6 result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530608func (vpv *VoltPortVnet) Dhcpv6ResultInd(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
609 vpv.ProcessDhcpv6Result(cntx, ipv6Addr, leaseTime)
Naveen Sampath04696f72022-06-13 15:19:14 +0530610}
611
612// GetNniVlans to get nni vlans
613func (vpv *VoltPortVnet) GetNniVlans() (uint16, uint16) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530614 logger.Debugw(ctx, "Get Nni Vlans", log.Fields{"vpv.VlanControl": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530615 switch vpv.VlanControl {
616 case ONUCVlanOLTSVlan,
617 OLTCVlanOLTSVlan:
618 return uint16(vpv.SVlan), uint16(vpv.CVlan)
619 case ONUCVlan,
620 None:
621 return uint16(vpv.SVlan), uint16(of.VlanNone)
622 case OLTSVlan:
623 return uint16(vpv.SVlan), uint16(of.VlanNone)
624 }
625 return uint16(of.VlanNone), uint16(of.VlanNone)
626}
627
628// GetService to get service
629func (vpv *VoltPortVnet) GetService(name string) (*VoltService, bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530630 logger.Debugw(ctx, "Get Service", log.Fields{"name": name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530631 service, ok := vpv.services.Load(name)
632 if ok {
633 return service.(*VoltService), ok
634 }
635 return nil, ok
636}
637
638// AddService to add service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530639func (vpv *VoltPortVnet) AddService(cntx context.Context, service *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530640 logger.Debugw(ctx, "Add Service", log.Fields{"ServiceName": service.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530641 vpv.services.Store(service.Name, service)
642 vpv.servicesCount.Inc()
643 logger.Infow(ctx, "Service added/updated to VPV", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "Service": service.Name, "Count": vpv.servicesCount.Load()})
644}
645
646// DelService to delete service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530647func (vpv *VoltPortVnet) DelService(cntx context.Context, service *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530648 logger.Debugw(ctx, "Delete Service", log.Fields{"ServiceName": service.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530649 vpv.services.Delete(service.Name)
650 vpv.servicesCount.Dec()
651
652 // If the only Igmp Enabled service is removed, remove the Igmp trap flow along with it
653 if service.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530654 if err := vpv.DelIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530655 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530656 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
657 }
658
659 vpv.IgmpEnabled = false
660 }
661 logger.Infow(ctx, "Service deleted from VPV", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "Service": service.Name, "Count": vpv.servicesCount.Load()})
662}
663
664// ProcessDhcpResult to process dhcp results
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530665func (vpv *VoltPortVnet) ProcessDhcpResult(cntx context.Context, res *layers.DHCPv4) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530666 logger.Debug(ctx, "Process Dhcp Result")
Naveen Sampath04696f72022-06-13 15:19:14 +0530667 msgType := DhcpMsgType(res)
668 if msgType == layers.DHCPMsgTypeAck {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530669 vpv.ProcessDhcpSuccess(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530670 } else if msgType == layers.DHCPMsgTypeNak {
671 vpv.DhcpStatus = DhcpStatusNacked
672 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530673 vpv.WriteToDb(cntx)
674}
675
676// RangeOnServices to call a function on all services on the vpv
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530677func (vpv *VoltPortVnet) RangeOnServices(cntx context.Context, callback func(cntx context.Context, key, value interface{}, flag bool) bool, delFlowsInDevice bool) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530678 vpv.services.Range(func(key, value interface{}) bool {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530679 return callback(cntx, key, value, delFlowsInDevice)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530680 })
Naveen Sampath04696f72022-06-13 15:19:14 +0530681}
682
683// ProcessDhcpSuccess : Learn the IPv4 address allocated to the services and update the
684// the services with the same. This also calls for adding flows
685// for the services as the DHCP procedure is completed
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530686func (vpv *VoltPortVnet) ProcessDhcpSuccess(cntx context.Context, res *layers.DHCPv4) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530687 logger.Info(ctx, "Process Dhcp Success")
Naveen Sampath04696f72022-06-13 15:19:14 +0530688 vpv.DhcpStatus = DhcpStatusAcked
689 vpv.Ipv4Addr, _ = GetIpv4Addr(res)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530690 logger.Debugw(ctx, "Received IPv4 Address and Services Configured", log.Fields{"IP Address": vpv.Ipv4Addr.String(), "Count": vpv.servicesCount.Load()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530691
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530692 vpv.RangeOnServices(cntx, vpv.updateIPv4AndProvisionFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530693 vpv.ProcessDhcpv4Options(res)
694}
695
696// ProcessDhcpv4Options : Currently we process lease time and store the validity of the
697// IP address allocated.
698func (vpv *VoltPortVnet) ProcessDhcpv4Options(res *layers.DHCPv4) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530699 logger.Debug(ctx, "Process Dhcp v4 Options")
Naveen Sampath04696f72022-06-13 15:19:14 +0530700 for _, o := range res.Options {
701 switch o.Type {
702 case layers.DHCPOptLeaseTime:
703 leasetime := GetIPv4LeaseTime(o)
704 vpv.DhcpExpiryTime = time.Now().Add((time.Duration(leasetime) * time.Second))
705 logger.Infow(ctx, "Lease Expiry Set", log.Fields{"Time": vpv.DhcpExpiryTime})
706 }
707 }
708}
709
710// ProcessDhcpv6Result : Read the IPv6 address allocated to the device and store it on the
711// VNET. The same IPv6 address is also passed to the services. When a
712// service is fetched all the associated information such as MAC address,
713// IPv4 address and IPv6 addresses can be provided.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530714func (vpv *VoltPortVnet) ProcessDhcpv6Result(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530715 logger.Debugw(ctx, "Process Dhcp v6 Result", log.Fields{"ipv6Addr": ipv6Addr, "leaseTime": leaseTime})
Naveen Sampath04696f72022-06-13 15:19:14 +0530716 // TODO: Status based hanlding of flows
717 vpv.Dhcp6ExpiryTime = time.Now().Add((time.Duration(leaseTime) * time.Second))
718 vpv.Ipv6Addr = ipv6Addr
719
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530720 vpv.RangeOnServices(cntx, vpv.updateIPv6AndProvisionFlows, false)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530721 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530722}
723
724// AddSvcUsMeterToDevice to add service upstream meter info to device
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530725func AddSvcUsMeterToDevice(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +0530726 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +0530727 logger.Infow(ctx, "Adding upstream meter profile to device", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530728 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
729 GetApplication().AddMeterToDevice(svc.Port, device.Name, svc.UsMeterID, 0)
730 return true
731 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530732 logger.Warnw(ctx, "Dropping US Meter request: Device not found", log.Fields{"Service": svc})
Naveen Sampath04696f72022-06-13 15:19:14 +0530733 return false
734}
735
736// PushFlowsForPortVnet - triggers flow construction and push for provided VPV
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530737func (vpv *VoltPortVnet) PushFlowsForPortVnet(cntx context.Context, d *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530738 logger.Debugw(ctx, "Push Flows For Port Vnet", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530739 vp := d.GetPort(vpv.Port)
740
741 //Ignore if UNI port is not found or not UP
742 if vp == nil || vp.State != PortStateUp {
743 logger.Warnw(ctx, "Ignoring Vlan UP Ind for VPV: Port Not Found/Ready", log.Fields{"Port": vp})
744 return
745 }
746
Naveen Sampath04696f72022-06-13 15:19:14 +0530747 //Disable the flag so that flows can be pushed again
748 // vpv.IgmpFlowsApplied = false
749 // vpv.DsFlowsApplied = false
750 // vpv.UsFlowsApplied = false
751 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530752 vpv.PortUpInd(cntx, d, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530753 vpv.VpvLock.Unlock()
754}
755
756// PortUpInd : When a port transistions to UP state, the indication is passed
757// on to this module via the application. We read the VNET configuration
758// again here to apply the latest configuration if the configuration
759// changed. Thus, a reboot of ONT forces the new configuration to get
760// applied.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530761func (vpv *VoltPortVnet) PortUpInd(cntx context.Context, device *VoltDevice, port string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530762 logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
Naveen Sampath04696f72022-06-13 15:19:14 +0530763 if vpv.DeleteInProgress {
Akash Sonief452f12024-12-12 18:20:28 +0530764 logger.Warnw(ctx, "Ignoring VPV Port UP Ind, VPV deletion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530765 return
766 }
767 vpv.setDevice(device.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530768
769 nni, _ := GetApplication().GetNniPort(device.Name)
770 if nni == "" {
771 logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name})
772 return
773 }
774
Akash Sonia8246972023-01-03 10:37:08 +0530775 if nniPort := device.GetPort(nni); nniPort != nil {
776 //If NNI port is not mached to nb nni port dont send flows
777 devConfig := GetApplication().GetDeviceConfig(device.SerialNum)
778 if devConfig != nil {
Akash Soni53da2852023-03-15 00:31:31 +0530779 if devConfig.UplinkPort != strconv.Itoa(int(nniPort.ID)) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530780 logger.Warnw(ctx, "NNI port not configured from NB, not pushing flows", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": nniPort.ID})
Akash Sonia8246972023-01-03 10:37:08 +0530781 return
782 }
783 }
784 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530785
Naveen Sampath04696f72022-06-13 15:19:14 +0530786 if vpv.Blocked {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530787 logger.Warnw(ctx, "VPV Blocked for Processing. Ignoring flow push request", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
Naveen Sampath04696f72022-06-13 15:19:14 +0530788 return
789 }
790
791 if vpv.DhcpRelay || vpv.ArpRelay || vpv.PppoeIa {
792 // If MAC Learning is true if no MAC is configured, push DS/US DHCP, US HSIA flows without MAC.
793 // DS HSIA flows are installed after learning the MAC.
794 logger.Infow(ctx, "Port Up - Trap Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530795 // no HSIA flows for multicast service and DPU_MGMT Service
vinokuma926cb3e2023-03-29 11:41:06 +0530796 if !vpv.McastService && vpv.VnetType != DpuMgmtTraffic {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530797 vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530798 }
vinokuma926cb3e2023-03-29 11:41:06 +0530799 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530800 vpv.RangeOnServices(cntx, AddMeterToDevice, false)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530801 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530802 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530803 if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
804 logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530805 /*In case of DPU_MGMT_TRAFFIC, need to install both US and DS traffic */
vinokuma926cb3e2023-03-29 11:41:06 +0530806 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530807 vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530808 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530809 // US & DS DHCP, US HSIA flows are already installed
810 // install only DS HSIA flow here.
811 // no HSIA flows for multicast service
Akash Soni53da2852023-03-15 00:31:31 +0530812 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530813 vpv.RangeOnServices(cntx, AddDsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530814 }
815 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530816 } else {
817 // DHCP relay is not configured. This implies that the service must use
818 // 1:1 and does not require MAC learning. In a completely uncommon but
819 // plausible case, the MAC address can be learnt from N:1 without DHCP
820 // relay by configuring any unknown MAC address to be reported. This
821 // however is not seen as a real use case.
822 logger.Infow(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
823 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530824 vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530825 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530827 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530828 vpv.RangeOnServices(cntx, AddDsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530829 }
830 }
831
832 // Process IGMP proxy - install IGMP trap rules before DHCP trap rules
833 if vpv.IgmpEnabled {
834 logger.Infow(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530835 vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice, false)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530836 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530837 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530838 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
839 }
840
841 if vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530842 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530843 }
844 }
845
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530846 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530847}
848
849// PortDownInd : When the port status changes to down, we delete all configured flows
850// The same indication is also passed to the services enqueued for them
851// to take appropriate actions
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530852// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
853func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool, delFlowsInDevice bool) {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530854 if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
855 logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
856 return
857 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530858 logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
Akash Sonief452f12024-12-12 18:20:28 +0530859 log.Fields{"service count": vpv.servicesCount.Load(), "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530860
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530861 //vpv.RangeOnServices(cntx, DelAllFlows)
862 vpv.DelTrapFlows(cntx)
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530863 vpv.DelHsiaFlows(cntx, delFlowsInDevice)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530864 vpv.WriteToDb(cntx)
865 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530866}
867
868// SetMacAddr : The MAC address is set when a MAC address is learnt through the
869// packets received from the network. Currently, DHCP packets are
870// only packets we learn the MAC address from
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530871func (vpv *VoltPortVnet) SetMacAddr(cntx context.Context, addr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530872 logger.Infow(ctx, "Set Mac Addr", log.Fields{"MAC addr": addr.String(), "Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530873 //Store Learnt MAC address and return if MACLearning is not enabled
874 vpv.LearntMacAddr = addr
875 if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
876 (NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
877 return
878 }
879
880 // Compare the two MAC addresses to see if it is same
881 // If they are same, we just return. If not, we perform
882 // actions to address the change in MAC address
883 //if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
884 if !util.MacAddrsMatch(vpv.MacAddr, addr) {
885 expectedPort := GetApplication().GetMacInPortMap(addr)
886 if expectedPort != "" && expectedPort != vpv.Port {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530887 logger.Warnw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
Naveen Sampath04696f72022-06-13 15:19:14 +0530888 log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
889 return
890 }
891 if NonZeroMacAddress(vpv.MacAddr) {
892 logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
893
894 // The newly learnt MAC address is different than earlier one.
895 // The existing MAC based HSIA flows need to be undone as the device
896 // may have been changed
897 // Atleast one HSIA flow should be present in adapter to retain the TP and GEM
898 // hence delete one after the other
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530899 vpv.RangeOnServices(cntx, DelUsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530900 vpv.MacAddr = addr
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530901 vpv.RangeOnServices(cntx, vpv.setLearntMAC, false)
902 vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
903 vpv.RangeOnServices(cntx, DelDsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530904 GetApplication().DeleteMacInPortMap(vpv.MacAddr)
905 } else {
906 vpv.MacAddr = addr
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530907 vpv.RangeOnServices(cntx, vpv.setLearntMAC, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530908 logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
909 }
910 GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
911 } else {
912 logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
913 }
914
915 _, err := GetApplication().GetDeviceFromPort(vpv.Port)
916 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530917 logger.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
Akash Sonia8246972023-01-03 10:37:08 +0530918 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530919 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
920 return
921 }
922 // Ds Hsia flows has to be pushed
923 if vpv.FlowsApplied {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530924 // In case of DPU_MGMT_TRAFFIC install both US and DS Flows
vinokuma926cb3e2023-03-29 11:41:06 +0530925 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530926 vpv.RangeOnServices(cntx, AddUsHsiaFlows, false)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530927 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530928 // no HSIA flows for multicast service
929 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530930 vpv.RangeOnServices(cntx, AddDsHsiaFlows, false)
Naveen Sampath04696f72022-06-13 15:19:14 +0530931 }
932 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530933 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530934}
935
936// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
937func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530938 logger.Debugw(ctx, "Matches Vlans", log.Fields{"Svlan": svlan, "Cvlan": cvlan, "Univlan": univlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530939 if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
940 return false
941 }
942 return true
943}
944
945// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
946func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530947 logger.Debugw(ctx, "Matches Cvlans", log.Fields{"Cvlan": cvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530948 if len(cvlan) != 1 && !vpv.AllowTransparent {
949 return false
950 }
951 if vpv.CVlan != cvlan[0] {
952 return false
953 }
954 return true
955}
956
957// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
958func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530959 logger.Debugw(ctx, "Matches Priority", log.Fields{"Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +0530960 var service *VoltService
961 pbitFound := false
962 matchpbitsFunc := func(key, value interface{}) bool {
963 svc := value.(*VoltService)
964 for _, pbit := range svc.Pbits {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530965 if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530966 logger.Infow(ctx, "Pbit match found with service",
967 log.Fields{"Pbit": priority, "serviceName": svc.Name})
968 pbitFound = true
969 service = svc
970 return false //Returning false to stop the Range loop
971 }
972 }
973 return true
974 }
975 _ = pbitFound
976 vpv.services.Range(matchpbitsFunc)
977 return service
978}
979
Akash Sonief452f12024-12-12 18:20:28 +0530980func (vpv *VoltPortVnet) GetSvcFromVPV() *VoltService {
981 var service *VoltService
982 vpv.services.Range(func(key, value interface{}) bool {
983 service = value.(*VoltService)
984 logger.Debugw(ctx, "Get Service from VPV", log.Fields{"Service": value})
985 return false
986 })
987 return service
988}
989
Naveen Sampath04696f72022-06-13 15:19:14 +0530990// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
991func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530992 logger.Debugw(ctx, "Get Remarked Priority", log.Fields{"Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +0530993 dsPbit := uint8(0)
994 matchpbitsFunc := func(key, value interface{}) bool {
995 svc := value.(*VoltService)
996 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530997 logger.Warnw(ctx, "Pbit match found with service",
Naveen Sampath04696f72022-06-13 15:19:14 +0530998 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
999 dsPbit = uint8(remarkPbit)
1000 return false //Returning false to stop the Range loop
1001 }
1002 // When no remarking info is available, remark the incoming pbit
1003 // to highest pbit configured for the subscriber (across all subservices associated)
1004 svcPbit := uint8(svc.Pbits[0])
1005 if svcPbit > dsPbit {
1006 dsPbit = svcPbit
1007 }
1008 return true
1009 }
1010 vpv.services.Range(matchpbitsFunc)
1011 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
1012 return dsPbit
1013}
1014
1015// AddSvc adds a service on the VNET on a port. The addition is
1016// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301017func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301018 logger.Infow(ctx, "Add Service to VPV", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301019 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301020 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +05301021 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
1022
1023 // Learn the circuit-id and remote-id from the service
1024 // TODO: There must be a better way of doing this. This
1025 // may be explored
1026 if svc.IgmpEnabled {
1027 vpv.IgmpEnabled = true
1028 }
1029 // first time service activation MacLearning will have default value as None.
1030 // to handle reciliency if anythng other then None we should retain it .
1031 if svc.MacLearning == MacLearningNone {
1032 if !vpv.DhcpRelay && !vpv.ArpRelay {
1033 svc.MacLearning = MacLearningNone
1034 } else if vpv.MacLearning == Learn {
1035 svc.MacLearning = Learn
1036 } else if vpv.MacLearning == ReLearn {
1037 svc.MacLearning = ReLearn
1038 }
1039 }
1040
vinokuma926cb3e2023-03-29 11:41:06 +05301041 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301042 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1043 svc.MacAddr = vpv.MacAddr
1044 } else if vpv.servicesCount.Load() == 1 {
1045 vpv.MacAddr = svc.MacAddr
1046 }
1047
1048 vpv.MacLearning = svc.MacLearning
1049 vpv.PonPort = svc.PonPort
1050 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301051 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301052 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301053 if svc.McastService {
1054 vpv.McastService = true
1055 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301056 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301057 vpv.McastPbit = svc.Pbits[0]
1058 vpv.McastUsMeterID = svc.UsMeterID
1059 vpv.SchedID = svc.SchedID
1060 }
1061 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1062 svc.AllowTransparent = vpv.AllowTransparent
1063 svc.SVlanTpid = vpv.SVlanTpid
1064
vinokuma926cb3e2023-03-29 11:41:06 +05301065 // Ensure configuring the mvlan profile only once
1066 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301067 if svc.MvlanProfileName != "" {
1068 if vpv.MvlanProfileName == "" {
1069 vpv.MvlanProfileName = svc.MvlanProfileName
1070 } else {
1071 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1072 }
1073 }
1074
Akash Sonia8246972023-01-03 10:37:08 +05301075 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301076 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +05301077 logger.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301078 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1079 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301080 return
1081 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301082 if !svc.IsActivated {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301083 logger.Warnw(ctx, "Not pushing Service Flows: Service Not activated", log.Fields{"ServiceName": svc.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05301084 return
1085 }
Akash Sonia8246972023-01-03 10:37:08 +05301086
vinokuma926cb3e2023-03-29 11:41:06 +05301087 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301088 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1089
Akash Soni53da2852023-03-15 00:31:31 +05301090 if devConfig.UplinkPort != voltDevice.NniPort {
Akash Sonief452f12024-12-12 18:20:28 +05301091 logger.Errorw(ctx, "NNI port mismatch", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": voltDevice.NniPort})
Akash Sonia8246972023-01-03 10:37:08 +05301092 return
1093 }
vinokuma926cb3e2023-03-29 11:41:06 +05301094 // Push Service Flows if DHCP relay is not configured
1095 // or already DHCP flows are configured for the VPV
1096 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301097 if vpv.FlowsApplied {
1098 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301099 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301100 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301101 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301102 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1103 }
1104 }
1105 }
1106
vinokuma926cb3e2023-03-29 11:41:06 +05301107 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301108 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1109 // service with Igmp Enabled needs to be installed
1110 if svc.IgmpEnabled && vpv.FlowsApplied {
1111 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301112 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301113 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301114 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1115 }
1116
1117 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301118 // For McastService, send Service Activated indication once IGMP US flow is pushed
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301119 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301120 }
1121 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301122 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301123}
1124
1125// setLearntMAC to set learnt mac
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301126func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301127 svc := value.(*VoltService)
1128 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301130 return true
1131}
1132
1133// PostAccessConfigSuccessInd for posting access config success indication
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301134func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301135 return true
1136}
1137
1138// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301139func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301140 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301141 logger.Debugw(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301142 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301143 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301144
1145 return true
1146}
1147
1148// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301149func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301150 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301151 logger.Debugw(ctx, "Updating Ipv6 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301152 svc.SetIpv6Addr(vpv.Ipv6Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301153 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301154
1155 return true
1156}
1157
1158// AddUsHsiaFlows to add upstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301159func AddUsHsiaFlows(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301160 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301161 logger.Debugw(ctx, "Add US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301162 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301163 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1164 }
1165 return true
1166}
1167
1168// AddDsHsiaFlows to add downstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301169func AddDsHsiaFlows(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301170 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301171 logger.Debugw(ctx, "Add DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301172 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301173 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1174 }
1175 return true
1176}
1177
1178// ClearFlagsInService to clear the flags used in service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301179func ClearFlagsInService(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301180 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301181 logger.Debugw(ctx, "Received Cleared Flow Flags for service", log.Fields{"name": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301182 svc.ServiceLock.Lock()
1183 svc.IgmpFlowsApplied = false
1184 svc.DsDhcpFlowsApplied = false
1185 svc.DsHSIAFlowsApplied = false
1186 svc.Icmpv6FlowsApplied = false
1187 svc.UsHSIAFlowsApplied = false
1188 svc.UsDhcpFlowsApplied = false
1189 svc.PendingFlows = make(map[string]bool)
1190 svc.AssociatedFlows = make(map[string]bool)
1191 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301192 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301193 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1194 return true
1195}
1196
1197// DelDsHsiaFlows to delete hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301198// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
1199func DelDsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301200 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301201 logger.Debugw(ctx, "Delete DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301202 if err := svc.DelDsHsiaFlows(cntx, delFlowsInDevice); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301203 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1204 }
1205 return true
1206}
1207
1208// DelUsHsiaFlows to delete upstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301209// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
1210func DelUsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301211 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301212 logger.Debugw(ctx, "Delete US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301213 if err := svc.DelUsHsiaFlows(cntx, delFlowsInDevice); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301214 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1215 }
1216 return true
1217}
1218
1219// ClearServiceCounters to clear the service counters
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301220func ClearServiceCounters(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301221 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301222 logger.Debugw(ctx, "Received Clear Service Counters", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301223 //Delete the per service counter too
1224 GetApplication().ServiceCounters.Delete(svc.Name)
1225 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301226 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301227 }
1228 return true
1229}
1230
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301231// AddMeterToDevice to add meter config to device, used in FTTB case
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301232func AddMeterToDevice(cntx context.Context, key, value interface{}, flag bool) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301233 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301234 logger.Debugw(ctx, "Received Add Meter To Device", log.Fields{"ServiceName": svc.Name})
Akash Soni53da2852023-03-15 00:31:31 +05301235 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301236 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1237 }
1238 return true
1239}
1240
vinokuma926cb3e2023-03-29 11:41:06 +05301241// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301242func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301243 logger.Debugw(ctx, "Received Add US & DS DHCP, IGMP Trap Flows", log.Fields{"FlowsApplied": vpv.FlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301244 if !vpv.FlowsApplied || vgcRebooted {
1245 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301246 if err := vpv.AddUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301247 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301248 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1249 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301250 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301251 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301252 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1253 }
1254 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1255 log.Fields{"port": vpv.Port})
1256 //vpv.updateICMPv6McGroup(true)
1257 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301258 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301259 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301260 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1261 }
1262 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301263 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301264 if err := vpv.AddUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301265 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301266 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1267 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301268 if err := vpv.AddDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301269 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301270 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1271 }
1272 }
1273 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301274 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301275 }
1276}
1277
vinokuma926cb3e2023-03-29 11:41:06 +05301278// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301279func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301280 logger.Debugw(ctx, "Received Delete US & DS DHCP, IGMP Trap Flows", log.Fields{"FlowsApplied": vpv.FlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301281 // Delete HSIA & DHCP flows before deleting IGMP flows
1282 if vpv.FlowsApplied || vgcRebooted {
1283 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301284 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301285 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1286 "UniVlan": vpv.UniVlan, "Error": err})
1287 }
1288 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1289 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301290 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301291 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301292 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1293 }
1294 //vpv.updateICMPv6McGroup(false)
1295 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301296 if err := vpv.DelUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301297 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301298 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1299 }
1300 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301301 if err := vpv.DelUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301302 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301303 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1304 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301305 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301306 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301307 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1308 }
1309 }
1310 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301311 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 }
Akash Sonia8246972023-01-03 10:37:08 +05301313 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301314 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1315 "UniVlan": vpv.UniVlan, "Error": err})
1316 }
1317}
1318
1319// DelHsiaFlows deletes the service flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301320func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context, delFlowsInDevice bool) {
Akash Sonief452f12024-12-12 18:20:28 +05301321 logger.Debugw(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
Naveen Sampath04696f72022-06-13 15:19:14 +05301322 // no HSIA flows for multicast service
1323 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301324 vpv.RangeOnServices(cntx, DelUsHsiaFlows, delFlowsInDevice)
1325 vpv.RangeOnServices(cntx, DelDsHsiaFlows, delFlowsInDevice)
Naveen Sampath04696f72022-06-13 15:19:14 +05301326 }
1327}
1328
vinokuma926cb3e2023-03-29 11:41:06 +05301329// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301330func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301331 //send flows deleted indication to submgr
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301332 vpv.RangeOnServices(cntx, ClearServiceCounters, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301333}
1334
1335// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301336func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301337 var vd *VoltDevice
1338 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301339 logger.Debugw(ctx, "Received Add US DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301340
1341 if vd = GetApplication().GetDevice(device); vd != nil {
1342 if vd.State != controller.DeviceStateUP {
1343 logger.Errorw(ctx, "Skipping US DHCP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1344 return nil
1345 }
1346 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301347 err := errorCodes.ErrDeviceNotFound
1348 return fmt.Errorf("us dhcp flow push failed - device not found for Port %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301349 }
1350
1351 flows, err := vpv.BuildUsDhcpFlows()
1352 if err == nil {
1353 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301354 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301355 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301356 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301357 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1358 }
1359 } else {
1360 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301361 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301362 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301363 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301364 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301365 return nil
1366}
1367
1368// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301369func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301370 var vd *VoltDevice
1371 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301372 logger.Debugw(ctx, "Received Add DS DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301373
1374 if vd = GetApplication().GetDevice(device); vd != nil {
1375 if vd.State != controller.DeviceStateUP {
1376 logger.Errorw(ctx, "Skipping DS DHCP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1377 return nil
1378 }
1379 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301380 err := errorCodes.ErrDeviceNotFound
1381 return fmt.Errorf("ds dhcp flow push failed - device not found for Port %s, Svlan %d, Cvlan %d, UniVlan %d. Device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301382 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301383 if vd.GlobalDhcpFlowAdded {
1384 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301385 return nil
1386 }
1387
1388 flows, err := vpv.BuildDsDhcpFlows()
1389 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301390 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301391 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301392 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301393 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301394 }
1395 } else {
1396 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301397 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301398 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301399 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301400 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301401 if GetApplication().GetVendorID() != Radisys {
1402 vd.GlobalDhcpFlowAdded = true
1403 }
1404 return nil
1405}
1406
1407// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301408func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301409 logger.Info(ctx, "Received Delete DHCP Flows")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301410 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301411 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301412 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1413 }
1414
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301415 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301416 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301417 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1418 }
1419}
1420
1421// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1422// Write the status of the VPV to the DB once the delete is scheduled
1423// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301424func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301425 logger.Debugw(ctx, "Received Delete US DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301426 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1427 if err != nil {
1428 return err
1429 }
1430
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301431 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301432 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301433 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301434 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1435 }
Akash Sonia8246972023-01-03 10:37:08 +05301436
Naveen Sampath04696f72022-06-13 15:19:14 +05301437 return nil
1438}
1439
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301440func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301441 logger.Debugw(ctx, "Received US Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301442 flows, err := vpv.BuildUsDhcpFlows()
1443 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301444 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301445 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301446 return fmt.Errorf("US DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301447}
Naveen Sampath04696f72022-06-13 15:19:14 +05301448
1449// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1450// Write the status of the VPV to the DB once the delete is scheduled
1451// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301452func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301453 logger.Debugw(ctx, "Received Delete DS DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301454 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1455 if err != nil {
1456 return err
1457 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301458 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301459 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301460 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301461 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1462 }
1463 /*
Akash Sonia8246972023-01-03 10:37:08 +05301464 err = vpv.delDsDhcp6Flows(device)
1465 if err != nil {
1466 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1467 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1468 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301469 return nil
1470}
1471
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301472func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301473 logger.Debugw(ctx, "Received DS Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301474 flows, err := vpv.BuildDsDhcpFlows()
1475 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301476 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301477 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301478 return fmt.Errorf("DS DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301479}
1480
1481/*
1482func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1483 flows, err := vpv.BuildDsDhcp6Flows()
1484 if err == nil {
1485 return vpv.RemoveFlows(device, flows)
1486 }
1487 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1488 return err
1489}*/
1490
1491// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301492func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301493 var vd *VoltDevice
1494 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301495 logger.Debugw(ctx, "Received Add US Arp Flows", log.Fields{"DeviceName": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301496 if vd = GetApplication().GetDevice(device); vd != nil {
1497 if vd.State != controller.DeviceStateUP {
1498 logger.Errorw(ctx, "Skipping US ARP Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1499 return nil
1500 }
1501 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301502 err := errorCodes.ErrDeviceNotFound
1503 return fmt.Errorf("US ARP Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301504 }
1505
1506 flows, err := vpv.BuildUsArpFlows()
1507 if err == nil {
1508 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301509 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301510 return fmt.Errorf("Pushing US ARP Flow Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301511 }
1512 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301513 return fmt.Errorf("US ARP Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301514 }
1515 return nil
1516}
1517
1518// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1519// Write the status of the VPV to the DB once the delete is scheduled
1520// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301521func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301522 logger.Debugw(ctx, "Delete US ARP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301523 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1524 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301525 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301526 }
1527 flows, err := vpv.BuildUsArpFlows()
1528 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301529 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301530 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301531 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301532}
1533
1534// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301535func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301536 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1537
1538 var vd *VoltDevice
1539 device := vpv.Device
1540
1541 if vd = GetApplication().GetDevice(device); vd != nil {
1542 if vd.State != controller.DeviceStateUP {
1543 logger.Errorw(ctx, "Skipping US PPPoE Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1544 return nil
1545 }
1546 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301547 err := errorCodes.ErrDeviceNotFound
1548 return fmt.Errorf("US PPPoE Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301549 }
1550
1551 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1552 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1553
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301554 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301555 return fmt.Errorf("Pushing US PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301556 }
1557 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301558 return fmt.Errorf("US PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301559 }
1560 return nil
1561}
1562
1563// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301564func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301565 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1566 var vd *VoltDevice
1567 device := vpv.Device
1568
1569 if vd = GetApplication().GetDevice(device); vd != nil {
1570 if vd.State != controller.DeviceStateUP {
1571 logger.Errorw(ctx, "Skipping DS PPPoE Flow Push - Device state DOWN", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1572 return nil
1573 }
1574 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301575 err := errorCodes.ErrDeviceNotFound
1576 return fmt.Errorf("DS PPPoE Flow Push Failed- Device not found : Port %s : SVLAN %d : CVLAN %d : UNIVlan %d : device %s : %w", vpv.Port, vpv.SVlan, vpv.CVlan, vpv.UniVlan, device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301577 }
1578
1579 flows, err := vpv.BuildDsPppoeFlows()
1580 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301581 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301582 return fmt.Errorf("Pushing DS PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301583 }
1584 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301585 return fmt.Errorf("DS PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301586 }
1587 return nil
1588}
1589
1590// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1591// Write the status of the VPV to the DB once the delete is scheduled
1592// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301593func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301594 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1595 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1596 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301597 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301598 }
1599 flows, err := vpv.BuildUsPppoeFlows()
1600 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301601 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301602 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301603 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301604}
1605
1606// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1607// Write the status of the VPV to the DB once the delete is scheduled
1608// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301609func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Akash Sonief452f12024-12-12 18:20:28 +05301610 logger.Infow(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301611 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1612 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301613 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301614 }
1615 flows, err := vpv.BuildDsPppoeFlows()
1616 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301617 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301618 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301619 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301620}
1621
1622// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301623func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301624 logger.Debugw(ctx, "Received Add Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301625 if !vpv.IgmpFlowsApplied || vgcRebooted {
1626 if vpv.MvlanProfileName == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301627 logger.Warn(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
Naveen Sampath04696f72022-06-13 15:19:14 +05301628 return nil
1629 }
1630 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1631 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301632 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301633 } else if device.State != controller.DeviceStateUP {
1634 logger.Warnw(ctx, "Device state Down. Ignoring US IGMP Flow Push", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan})
1635 return nil
1636 }
1637 flows, err := vpv.BuildIgmpFlows()
1638 if err == nil {
1639 for cookie := range flows.SubFlows {
1640 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1641 cookie := strconv.FormatUint(cookie, 10)
1642 fe := &FlowEvent{
1643 eType: EventTypeUsIgmpFlowAdded,
1644 cookie: cookie,
1645 eventData: vpv,
1646 }
1647 vd.RegisterFlowAddEvent(cookie, fe)
1648 }
1649 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301650 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301651 return err1
1652 }
1653 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301654 return fmt.Errorf("IGMP Flow Add Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301655 }
1656 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301657 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301658 }
1659 return nil
1660}
1661
1662// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1663// Write the status of the VPV to the DB once the delete is scheduled
1664// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301665func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301666 logger.Debugw(ctx, "Received Delete Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301667 if vpv.IgmpFlowsApplied || vgcRebooted {
1668 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1669 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301670 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301671 }
1672 flows, err := vpv.BuildIgmpFlows()
1673 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301674 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301675 return err1
1676 }
1677 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301678 return fmt.Errorf("IGMP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301679 }
1680 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301681 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301682 }
1683 return nil
1684}
1685
1686// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1687// The flows included by this function cover US only as the DS is
1688// created either automatically by the VOLTHA or at the device level
1689// earlier
1690func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301691 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301692 flow := &of.VoltFlow{}
1693 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1694
Naveen Sampath04696f72022-06-13 15:19:14 +05301695 subFlow := of.NewVoltSubFlow()
1696 subFlow.SetTableID(0)
1697
vinokuma926cb3e2023-03-29 11:41:06 +05301698 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301699 subFlow.SetMatchVlan(vpv.CVlan)
1700 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1701 subFlow.SetPcp(vpv.UsPonSTagPriority)
1702 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301703 } else {
1704 subFlow.SetMatchVlan(vpv.UniVlan)
1705 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301706 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301707 }
1708 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301709 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301710 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301711 uniport, err := GetApplication().GetPortID(vpv.Port)
1712 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301713 return nil, fmt.Errorf("failed to fetch uni port %s from vpv : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301714 }
1715 subFlow.SetInPort(uniport)
1716 // PortName and PortID to be used for validation of port before flow pushing
1717 flow.PortID = uniport
1718 flow.PortName = vpv.Port
1719 subFlow.SetReportToController()
1720
1721 // Set techprofile, meterid of first service
1722 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301723 vs := value.(*VoltService)
1724 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301725 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301726 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301727 } else {
1728 writemetadata = uint64(vs.TechProfileID) << 32
1729 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301730 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301731 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301732 return false
1733 })
1734
Naveen Sampath04696f72022-06-13 15:19:14 +05301735 // metadata := uint64(uniport)
1736 // subFlow.SetWriteMetadata(metadata)
1737 allowTransparent := 0
1738 if vpv.AllowTransparent {
1739 allowTransparent = 1
1740 }
vinokuma926cb3e2023-03-29 11:41:06 +05301741 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301742 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1743 subFlow.SetTableMetadata(metadata)
1744 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301745 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1746 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1747 subFlow.Priority = of.DhcpFlowPriority
1748
1749 flow.SubFlows[subFlow.Cookie] = subFlow
1750 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1751 return flow, nil
1752}
1753
1754// BuildDsDhcpFlows to build the downstream dhcp flows
1755func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301756 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1757 flow := &of.VoltFlow{}
1758 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1759 subFlow := of.NewVoltSubFlow()
1760 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301761 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301762 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301763 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301764 }
1765 subFlow.SetUdpv4Match()
1766 subFlow.SrcPort = 67
1767 subFlow.DstPort = 68
1768 uniport, _ := GetApplication().GetPortID(vpv.Port)
1769 nni, err := GetApplication().GetNniPort(vpv.Device)
1770 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301771 return nil, fmt.Errorf("failed to fetch nni port %s from vpv : %w", nni, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301772 }
1773 nniport, err := GetApplication().GetPortID(nni)
1774 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301775 return nil, fmt.Errorf("failed to fetch port id %d for nni : %w", nniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301776 }
1777 subFlow.SetInPort(nniport)
1778 // PortName and PortID to be used for validation of port before flow pushing
1779 flow.PortID = uniport
1780 flow.PortName = vpv.Port
1781 // metadata := uint64(uniport)
1782 // subFlow.SetWriteMetadata(metadata)
1783 allowTransparent := 0
1784 if vpv.AllowTransparent {
1785 allowTransparent = 1
1786 }
vinokuma926cb3e2023-03-29 11:41:06 +05301787 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301788 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1789 subFlow.SetTableMetadata(metadata)
1790 subFlow.Priority = of.DhcpFlowPriority
1791 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301792 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301793 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301794 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301795
1796 flow.SubFlows[subFlow.Cookie] = subFlow
1797 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1798
1799 return flow, nil
1800}
1801
1802// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1803// application.
1804func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301805 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301806 flow := &of.VoltFlow{}
1807 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1808
Naveen Sampath04696f72022-06-13 15:19:14 +05301809 subFlow := of.NewVoltSubFlow()
1810 subFlow.SetTableID(0)
1811
1812 subFlow.SetMatchVlan(vpv.UniVlan)
1813 subFlow.SetSetVlan(vpv.CVlan)
1814 subFlow.SetUdpv6Match()
1815 subFlow.SrcPort = 546
1816 subFlow.DstPort = 547
1817 uniport, err := GetApplication().GetPortID(vpv.Port)
1818 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301819 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301820 }
1821 // Set techprofile, meterid of first service
1822 vpv.services.Range(func(key, value interface{}) bool {
1823 svc := value.(*VoltService)
1824 writemetadata := uint64(svc.TechProfileID) << 32
1825 subFlow.SetWriteMetadata(writemetadata)
1826 subFlow.SetMeterID(svc.UsMeterID)
1827 return false
1828 })
1829 subFlow.SetInPort(uniport)
1830 // PortName and PortID to be used for validation of port before flow pushing
1831 flow.PortID = uniport
1832 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301833 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301834 // metadata := uint64(uniport)
1835 // subFlow.SetWriteMetadata(metadata)
1836 allowTransparent := 0
1837 if vpv.AllowTransparent {
1838 allowTransparent = 1
1839 }
1840 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1841 subFlow.SetTableMetadata(metadata)
1842 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301843 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301844 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1845 subFlow.Priority = of.DhcpFlowPriority
1846
1847 flow.SubFlows[subFlow.Cookie] = subFlow
1848 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1849 return flow, nil
1850}
1851
1852// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1853// application.
1854func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1855 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1856
1857 flow := &of.VoltFlow{}
1858 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1859 subFlow := of.NewVoltSubFlow()
1860 subFlow.SetTableID(0)
1861
1862 vpv.setDsMatchVlan(subFlow)
1863 subFlow.SetUdpv6Match()
1864 subFlow.SrcPort = 547
1865 subFlow.DstPort = 547
1866 uniport, _ := GetApplication().GetPortID(vpv.Port)
1867 nni, err := GetApplication().GetNniPort(vpv.Device)
1868 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301869 logger.Errorw(ctx, "Failed to fetch nni port from vpv", log.Fields{"error": err, "device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301870 return nil, err
1871 }
1872 nniport, err := GetApplication().GetPortID(nni)
1873 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301874 logger.Errorw(ctx, "Failed to fetch port ID for nni", log.Fields{"error": err, "nni": nni})
Naveen Sampath04696f72022-06-13 15:19:14 +05301875 return nil, err
1876 }
1877 subFlow.SetInPort(nniport)
1878 // PortName and PortID to be used for validation of port before flow pushing
1879 flow.PortID = uniport
1880 flow.PortName = vpv.Port
1881 // metadata := uint64(uniport)
1882 // subFlow.SetWriteMetadata(metadata)
1883 allowTransparent := 0
1884 if vpv.AllowTransparent {
1885 allowTransparent = 1
1886 }
1887 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1888 subFlow.SetTableMetadata(metadata)
1889 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301890 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301891 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1892 subFlow.Priority = of.DhcpFlowPriority
1893
1894 flow.SubFlows[subFlow.Cookie] = subFlow
1895 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1896 return flow, nil
1897}
1898
1899// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1900// The flows included by this function cover US only as the DS is
1901// created either automatically by the VOLTHA or at the device level
1902// earlier
1903func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301904 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301905 flow := &of.VoltFlow{}
1906 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1907
Naveen Sampath04696f72022-06-13 15:19:14 +05301908 subFlow := of.NewVoltSubFlow()
1909 subFlow.SetTableID(0)
1910
1911 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1912 subFlow.SetMatchSrcMac(vpv.MacAddr)
1913 }
1914
1915 subFlow.SetMatchDstMac(BroadcastMAC)
1916 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1917 return nil, err
1918 }
1919 subFlow.SetArpMatch()
1920 uniport, err := GetApplication().GetPortID(vpv.Port)
1921 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301922 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301923 }
1924 subFlow.SetInPort(uniport)
1925 // PortName and PortID to be used for validation of port before flow pushing
1926 flow.PortID = uniport
1927 flow.PortName = vpv.Port
1928 subFlow.SetReportToController()
1929 allowTransparent := 0
1930 if vpv.AllowTransparent {
1931 allowTransparent = 1
1932 }
1933 metadata := uint64(uniport)
1934 subFlow.SetWriteMetadata(metadata)
1935 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1936 subFlow.SetTableMetadata(metadata)
1937 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1938 subFlow.Priority = of.ArpFlowPriority
1939
1940 flow.SubFlows[subFlow.Cookie] = subFlow
1941 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1942 return flow, nil
1943}
1944
1945// setUsMatchVlan to set upstream match vlan
1946func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301947 logger.Debugw(ctx, "Set Us Match Vlan", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05301948 switch vpv.VlanControl {
1949 case None:
1950 flow.SetMatchVlan(vpv.SVlan)
1951 case ONUCVlanOLTSVlan:
1952 flow.SetMatchVlan(vpv.CVlan)
1953 case OLTCVlanOLTSVlan:
1954 flow.SetMatchVlan(vpv.UniVlan)
1955 //flow.SetSetVlan(vpv.CVlan)
1956 case ONUCVlan:
1957 flow.SetMatchVlan(vpv.SVlan)
1958 case OLTSVlan:
1959 flow.SetMatchVlan(vpv.UniVlan)
1960 //flow.SetSetVlan(vpv.SVlan)
1961 default:
1962 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1963 return errorCodes.ErrInvalidParamInRequest
1964 }
1965 return nil
1966}
1967
1968// BuildUsPppoeFlows to build upstream pppoe flows
1969func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301970 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301971 flow := &of.VoltFlow{}
1972 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301973 subFlow := of.NewVoltSubFlow()
1974 subFlow.SetTableID(0)
1975
1976 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1977 subFlow.SetMatchSrcMac(vpv.MacAddr)
1978 }
1979
1980 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1981 return nil, err
1982 }
1983 subFlow.SetPppoeDiscoveryMatch()
1984 uniport, err := GetApplication().GetPortID(vpv.Port)
1985 if err != nil {
1986 return nil, err
1987 }
1988 subFlow.SetInPort(uniport)
1989 subFlow.SetReportToController()
1990 // PortName and PortID to be used for validation of port before flow pushing
1991 flow.PortID = uniport
1992 flow.PortName = vpv.Port
1993
1994 allowTransparent := 0
1995 if vpv.AllowTransparent {
1996 allowTransparent = 1
1997 }
1998 metadata := uint64(uniport)
1999 subFlow.SetWriteMetadata(metadata)
2000
2001 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2002 subFlow.SetTableMetadata(metadata)
2003
vinokuma926cb3e2023-03-29 11:41:06 +05302004 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302005 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
2006 subFlow.Priority = of.PppoeFlowPriority
2007
2008 flow.SubFlows[subFlow.Cookie] = subFlow
2009 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2010 return flow, nil
2011}
2012
2013// BuildDsPppoeFlows to build downstream pppoe flows
2014func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302015 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
2016 flow := &of.VoltFlow{}
2017 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2018 subFlow := of.NewVoltSubFlow()
2019 subFlow.SetTableID(0)
2020
2021 vpv.setDsMatchVlan(subFlow)
2022 subFlow.SetPppoeDiscoveryMatch()
2023
2024 if NonZeroMacAddress(vpv.MacAddr) {
2025 subFlow.SetMatchDstMac(vpv.MacAddr)
2026 }
2027
2028 uniport, _ := GetApplication().GetPortID(vpv.Port)
2029 nni, err := GetApplication().GetNniPort(vpv.Device)
2030 if err != nil {
2031 return nil, err
2032 }
2033 nniport, err := GetApplication().GetPortID(nni)
2034 if err != nil {
2035 return nil, err
2036 }
2037 subFlow.SetInPort(nniport)
2038 // PortName and PortID to be used for validation of port before flow pushing
2039 flow.PortID = uniport
2040 flow.PortName = vpv.Port
2041 metadata := uint64(uniport)
2042 subFlow.SetWriteMetadata(metadata)
2043 allowTransparent := 0
2044 if vpv.AllowTransparent {
2045 allowTransparent = 1
2046 }
2047 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2048 subFlow.SetTableMetadata(metadata)
2049 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302050 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302051 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2052 subFlow.Priority = of.PppoeFlowPriority
2053
2054 flow.SubFlows[subFlow.Cookie] = subFlow
2055 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2056 return flow, nil
2057}
2058
2059// setDsMatchVlan to set downstream match vlan
2060func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302061 logger.Debugw(ctx, "Set Ds Match Vlan", log.Fields{"Vlan": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302062 switch vpv.VlanControl {
2063 case None:
2064 flow.SetMatchVlan(vpv.SVlan)
2065 case ONUCVlanOLTSVlan,
2066 OLTCVlanOLTSVlan,
2067 ONUCVlan,
2068 OLTSVlan:
2069 flow.SetMatchVlan(vpv.SVlan)
2070 default:
2071 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2072 }
2073}
2074
2075// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2076// in the US direction.
2077func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2078 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2079 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2080 if mvp == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302081 return nil, errors.New("mvlan profile configured not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05302082 }
2083 mvlan := mvp.GetUsMatchVlan()
2084 flow := &of.VoltFlow{}
2085 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2086 subFlow := of.NewVoltSubFlow()
2087 subFlow.SetTableID(0)
2088
Akash Sonia8246972023-01-03 10:37:08 +05302089 subFlow.SetMatchVlan(vpv.UniVlan)
2090 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302091
2092 uniport, err := GetApplication().GetPortID(vpv.Port)
2093 if err != nil {
2094 return nil, err
2095 }
2096 subFlow.SetInPort(uniport)
2097 // PortName and PortID to be used for validation of port before flow pushing
2098 flow.PortID = uniport
2099 flow.PortName = vpv.Port
2100
2101 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2102 subFlow.SetMatchSrcMac(vpv.MacAddr)
2103 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302104 logger.Debugw(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302105 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302106
2107 if vpv.McastService {
2108 metadata := uint64(vpv.McastUsMeterID)
2109 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2110 subFlow.SetMatchPbit(vpv.McastPbit)
2111 subFlow.SetMeterID(vpv.McastUsMeterID)
2112 subFlow.SetWriteMetadata(metadata)
2113 } else {
2114 // Set techprofile, meterid of first service
2115 vpv.services.Range(func(key, value interface{}) bool {
2116 svc := value.(*VoltService)
2117 writemetadata := uint64(svc.TechProfileID) << 32
2118 subFlow.SetWriteMetadata(writemetadata)
2119 subFlow.SetMeterID(svc.UsMeterID)
2120 return false
2121 })
2122 }
2123
2124 allowTransparent := 0
2125 if vpv.AllowTransparent {
2126 allowTransparent = 1
2127 }
2128 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2129 subFlow.SetTableMetadata(metadata)
2130 subFlow.SetIgmpMatch()
2131 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302132 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302133 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2134 subFlow.Priority = of.IgmpFlowPriority
2135
2136 flow.SubFlows[subFlow.Cookie] = subFlow
2137 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2138 return flow, nil
2139}
2140
2141// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302142func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302143 if vpv.DeleteInProgress {
2144 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2145 return
2146 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302147 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302148}
2149
vinokuma926cb3e2023-03-29 11:41:06 +05302150// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302151func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302152 vpv.PendingFlowLock.RLock()
2153 defer vpv.PendingFlowLock.RUnlock()
2154 vpv.Version = database.PresentVersionMap[database.VpvPath]
2155 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302156 if err := db.PutVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan), string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302157 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2158 "UniVlan": vpv.UniVlan, "Error": err})
2159 }
2160 }
2161}
2162
2163// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302164func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302165 logger.Debugw(ctx, "Deleting VPV from DB", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302166 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302167}
2168
2169// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302170func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302171 vpv.RangeOnServices(cntx, ClearFlagsInService, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302172}
2173
2174// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302175func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302176 logger.Debugw(ctx, "Clear All Vpv Flags", log.Fields{"Port": vpv.Port, "Device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302177 vpv.PendingFlowLock.Lock()
2178 vpv.FlowsApplied = false
2179 vpv.IgmpFlowsApplied = false
2180 vpv.PendingDeleteFlow = make(map[string]bool)
2181 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302182 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302183 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2184 log.Fields{"device": vpv.Device, "port": vpv.Port,
2185 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2186}
2187
2188// CreateVpvFromString to create vpv from string
2189func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302190 logger.Info(ctx, "Create Vpv From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05302191 var vpv VoltPortVnet
2192 if err := json.Unmarshal(b, &vpv); err == nil {
2193 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2194 if !ok {
2195 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2196 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2197 }
2198 vpv.servicesCount = atomic.NewUint64(0)
2199 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2200 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2201 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2202 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2203 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2204 vnet.associatePortToVnet(vpv.Port)
2205 }
2206
2207 if vpv.DeleteInProgress {
2208 va.VoltPortVnetsToDelete[&vpv] = true
2209 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2210 }
2211 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2212 }
2213}
2214
2215// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302216func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302217 logger.Info(ctx, "Restore Vpvs From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302218 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302219 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302220 for hash, vpv := range vpvs {
2221 b, ok := vpv.Value.([]byte)
2222 if !ok {
2223 logger.Warn(ctx, "The value type is not []byte")
2224 continue
2225 }
2226 va.CreateVpvFromString(b, hash)
2227 }
2228}
2229
2230// GetVnetByPort : VNET related functionality of VOLT Application here on.
2231// Get the VNET from a port. The port identity is passed as device and port identities in string.
2232// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2233// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2234func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302235 logger.Debugw(ctx, "Get Vnet By Port", log.Fields{"port": port, "svlan": svlan, "cvlan": cvlan, "univlan": univlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302236 if _, ok := va.VnetsByPort.Load(port); !ok {
2237 return nil
2238 }
2239 vpvs, _ := va.VnetsByPort.Load(port)
2240 for _, vpv := range vpvs.([]*VoltPortVnet) {
2241 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2242 return vpv
2243 }
2244 }
2245 return nil
2246}
2247
2248// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302249func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302250 // The VNET is not on the port and is to be added
2251 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2252 vpv := NewVoltPortVnet(vvnet)
2253 vpv.MacLearning = vvnet.MacLearning
2254 vpv.Port = port
2255 vvnet.associatePortToVnet(port)
2256 if _, ok := va.VnetsByPort.Load(port); !ok {
2257 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2258 }
2259 vpvsIntf, _ := va.VnetsByPort.Load(port)
2260 vpvs := vpvsIntf.([]*VoltPortVnet)
2261 vpvs = append(vpvs, vpv)
2262 va.VnetsByPort.Store(port, vpvs)
2263 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2264
2265 vpv.VpvLock.Lock()
2266 defer vpv.VpvLock.Unlock()
2267
2268 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302269 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302270
Tinoj Josephec742f62022-09-29 19:11:10 +05302271 if !vs.IsActivated {
2272 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2273 // Process the PORT UP if the port is already up
2274 d, err := va.GetDeviceFromPort(port)
2275 if err == nil {
2276 vpv.setDevice(d.Name)
2277 }
2278 vpv.WriteToDb(cntx)
2279 return vpv
2280 }
2281
Naveen Sampath04696f72022-06-13 15:19:14 +05302282 // Process the PORT UP if the port is already up
2283 d, err := va.GetDeviceFromPort(port)
2284 if err == nil {
2285 vpv.setDevice(d.Name)
2286 p := d.GetPort(port)
2287 if p != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302288 logger.Debugw(ctx, "Checking UNI port state", log.Fields{"State": p.State})
Akash Soni024eb8e2023-04-28 16:25:09 +05302289 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
2290 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302291 }
2292 }
2293 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302294 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302295 return vpv
2296}
2297
2298// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302299func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302300 logger.Debugw(ctx, "Delete Vnet From Port", log.Fields{"Port": port, "VNET": vpv.Device})
vinokuma926cb3e2023-03-29 11:41:06 +05302301 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302302 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2303
vinokuma926cb3e2023-03-29 11:41:06 +05302304 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302305 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2306
vinokuma926cb3e2023-03-29 11:41:06 +05302307 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302308 va.DeleteMacInPortMap(vpv.MacAddr)
2309
vinokuma926cb3e2023-03-29 11:41:06 +05302310 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302311 vpvsIntf, ok := va.VnetsByPort.Load(port)
2312 if !ok {
2313 return
2314 }
2315 vpvs := vpvsIntf.([]*VoltPortVnet)
2316 for i, lvpv := range vpvs {
vinokuma04dc9f82023-07-31 15:47:49 +05302317 if reflect.DeepEqual(lvpv, vpv) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302318 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2319 "UNIVLAN": vpv.UniVlan})
2320
2321 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2322
2323 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302324 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302325
2326 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302327 vpv.DelTrapFlows(cntx)
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302328 vpv.DelHsiaFlows(cntx, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302329 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2330 vpv.PendingFlowLock.RLock()
2331 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302332 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302333 }
2334 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302335 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302336 }
2337 vpv.PendingFlowLock.RUnlock()
2338 return
2339 }
2340 }
2341}
2342
2343// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302344func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302345 logger.Info(ctx, "Restore Vnets From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302346 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302347 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302348 for _, net := range vnets {
2349 b, ok := net.Value.([]byte)
2350 if !ok {
2351 logger.Warn(ctx, "The value type is not []byte")
2352 continue
2353 }
2354 var vnet VoltVnet
2355 err := json.Unmarshal(b, &vnet)
2356 if err != nil {
2357 logger.Warn(ctx, "Unmarshal of VNET failed")
2358 continue
2359 }
2360 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302361 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302362 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2363 }
2364
2365 if vnet.DeleteInProgress {
2366 va.VnetsToDelete[vnet.Name] = true
2367 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2368 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302369 }
2370}
2371
2372// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2373// are used as the key to locate the service. If more than one service is on the
2374// same port (essentially a UNI of ONU), the services must be separated by different
2375// CVLANs
2376func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302377 logger.Debugw(ctx, "Get Service From Cvlan", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302378 // Fetch the device first to make sure the device exists
2379 dIntf, ok := va.DevicesDisc.Load(device)
2380 if !ok {
2381 return nil
2382 }
2383 d := dIntf.(*VoltDevice)
2384
2385 // If the port is NNI port, the services dont exist on it. The svc then
2386 // must be obtained from a different context and is not included here
2387 if port == d.NniPort {
2388 return nil
2389 }
2390
vinokuma926cb3e2023-03-29 11:41:06 +05302391 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302392 var service *VoltService
2393
2394 // This is an access port and the port should have all the associated
2395 // services which can be uniquely identified by the VLANs in the packet
2396 vnets, ok := va.VnetsByPort.Load(port)
2397
2398 if !ok {
2399 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2400 return nil
2401 }
2402 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2403 for _, vnet := range vnets.([]*VoltPortVnet) {
2404 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2405 switch vnet.VlanControl {
2406 case ONUCVlanOLTSVlan:
2407 service = vnet.MatchesPriority(priority)
2408 if vnet.MatchesCvlan(vlans) && service != nil {
2409 return service
2410 }
2411 case ONUCVlan,
2412 None:
2413 service = vnet.MatchesPriority(priority)
Naveen Sampath04696f72022-06-13 15:19:14 +05302414 // In case of HSIA Flow - cvlan == Svlan
Akash Sonief452f12024-12-12 18:20:28 +05302415 // In case of DHCP flow, match for cvlan as we are setting cvlan for DHCP flows
2416 if len(vlans) == 1 && (vlans[0] == vnet.CVlan || vlans[0] == of.VlanNone) && (service != nil && service.IsActivated) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302417 return service
2418 }
Akash Sonief452f12024-12-12 18:20:28 +05302419 case OLTCVlanOLTSVlan:
Naveen Sampath04696f72022-06-13 15:19:14 +05302420 service = vnet.MatchesPriority(priority)
2421 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2422 return service
2423 }
Akash Sonief452f12024-12-12 18:20:28 +05302424 case OLTSVlan:
2425 // For OLTSVlan, return only the active service attached to the VPV.
2426 service = vnet.GetSvcFromVPV()
2427 if service != nil && service.IsActivated {
2428 return service
2429 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302430 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302431 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302432 }
2433 }
2434 return nil
2435}
2436
2437// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2438// are used as the key to locate the service. If more than one service is on the
2439// same port (essentially a UNI of ONU), the services must be separated by different
2440// CVLANs
2441func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2442 // Fetch the device first to make sure the device exists
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302443 logger.Debugw(ctx, "Get Vnet From Fields", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302444 dIntf, ok := va.DevicesDisc.Load(device)
2445 if !ok {
2446 return nil, nil
2447 }
2448 d := dIntf.(*VoltDevice)
2449
2450 // If the port is NNI port, the services dont exist on it. The svc then
2451 // must be obtained from a different context and is not included here
2452 if port == d.NniPort {
2453 return nil, nil
2454 }
2455
2456 //To return the matched service
2457 var service *VoltService
2458
2459 // This is an access port and the port should have all the associated
2460 // services which can be uniquely identified by the VLANs in the packet
2461 if vnets, ok := va.VnetsByPort.Load(port); ok {
2462 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2463 for _, vnet := range vnets.([]*VoltPortVnet) {
2464 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2465 switch vnet.VlanControl {
2466 case ONUCVlanOLTSVlan:
2467 service = vnet.MatchesPriority(priority)
2468 if vnet.MatchesCvlan(vlans) && service != nil {
2469 return vnet, service
2470 }
2471 case ONUCVlan,
2472 None:
2473 service = vnet.MatchesPriority(priority)
2474 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2475 return vnet, service
2476 }
2477 case OLTCVlanOLTSVlan,
2478 OLTSVlan:
2479 service = vnet.MatchesPriority(priority)
2480 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2481 return vnet, service
2482 }
2483 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302484 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302485 }
2486 }
2487 }
2488 return nil, nil
2489}
2490
2491// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2492// are used as the key to locate the service. If more than one service is on the
2493// same port (essentially a UNI of ONU), the services must be separated by different
2494// CVLANs
2495func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302496 logger.Debugw(ctx, "Get Vnet From Pkt", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05302497 vlans := GetVlans(pkt)
2498 priority := GetPriority(pkt)
2499 return va.GetVnetFromFields(device, port, vlans, priority)
2500}
2501
2502// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302503func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302504 logger.Debugw(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302505 pushflow := func(key interface{}, value interface{}) bool {
2506 device := value.(*VoltDevice)
2507 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302508 logger.Warnw(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302509 return true
2510 }
2511 if device.State != controller.DeviceStateUP {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302512 logger.Warnw(ctx, "Push Dev Flows Failed - Device state DOWN", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan, "device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302513 return true
2514 }
2515 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302516 logger.Warnw(ctx, "Push Dev Flows Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302517 return true
2518 }
2519
2520 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2521 vnetList := vnetListIntf.(*util.ConcurrentMap)
2522 vnetList.Set(vnet.Name, true)
2523 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2524 logger.Infow(ctx, "Flow already pushed for these Vlans. Adding profile to list", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2525 return true
2526 }
2527 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2528 err := ProcessIcmpv6McGroup(device.Name, false)
2529 if err != nil {
2530 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2531 return true
2532 }
2533 if portID, err := va.GetPortID(device.NniPort); err == nil {
2534 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2535 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2536 return true
2537 }
2538
vinokuma926cb3e2023-03-29 11:41:06 +05302539 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302540 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302541 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302542 if err != nil {
2543 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2544 return true
2545 }
2546 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2547
2548 // Pushing ARP Flow
2549 flow = BuildDSArpFlow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302550 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302551 if err != nil {
2552 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2553 return true
2554 }
2555 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2556
2557 vnetList := util.NewConcurrentMap()
2558 vnetList.Set(vnet.Name, true)
2559 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2560 }
2561 return true
2562 }
2563 va.DevicesDisc.Range(pushflow)
2564}
2565
2566// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302567func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302568 logger.Debugw(ctx, "PushDevFlowForDevice", log.Fields{"device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302569 err := ProcessIcmpv6McGroup(device.Name, false)
2570 if err != nil {
2571 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2572 return
2573 }
2574 pushicmpv6 := func(key, value interface{}) bool {
2575 vnet := value.(*VoltVnet)
2576 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2577 vnetList := vnetListIntf.(*util.ConcurrentMap)
2578 vnetList.Set(vnet.Name, true)
2579 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2580 logger.Infow(ctx, "Flow already pushed for these Vlans. Adding profile to list", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2581 return true
2582 }
2583 nniPortID, err := va.GetPortID(device.NniPort)
2584 if err != nil {
2585 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2586 }
2587 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2588 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2589 return true
2590 }
2591 flow := BuildICMPv6Flow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302592 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302593 if err != nil {
2594 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2595 return true
2596 }
2597 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2598
2599 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302600 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302601 if err != nil {
2602 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2603 return true
2604 }
2605 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2606
2607 vnetList := util.NewConcurrentMap()
2608 vnetList.Set(vnet.Name, true)
2609 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2610 return true
2611 }
2612 va.VnetsByName.Range(pushicmpv6)
2613}
2614
2615// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302616func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302617 logger.Debugw(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302618 delflows := func(key interface{}, value interface{}) bool {
2619 device := value.(*VoltDevice)
2620
2621 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2622 vnetList := vnetListIntf.(*util.ConcurrentMap)
2623 vnetList.Remove(vnet.Name)
2624 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2625 if vnetList.Length() != 0 {
2626 logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2627 return true
2628 }
2629 }
2630 if portID, err := va.GetPortID(device.NniPort); err == nil {
2631 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2632 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2633 return true
2634 }
vinokuma926cb3e2023-03-29 11:41:06 +05302635 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302636 flow := BuildICMPv6Flow(portID, vnet)
2637 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302638 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302639 if err != nil {
2640 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2641 return true
2642 }
2643 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2644
vinokuma926cb3e2023-03-29 11:41:06 +05302645 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302646 flow = BuildDSArpFlow(portID, vnet)
2647 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302648 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302649 if err != nil {
2650 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2651 return true
2652 }
2653 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2654
2655 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2656 }
2657 return true
2658 }
2659 va.DevicesDisc.Range(delflows)
2660}
2661
2662// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302663func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302664 logger.Debugw(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302665 delicmpv6 := func(key, value interface{}) bool {
2666 vnet := value.(*VoltVnet)
2667 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2668 vnetList := vnetListIntf.(*util.ConcurrentMap)
2669 vnetList.Remove(vnet.Name)
2670 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2671 if vnetList.Length() != 0 {
2672 logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2673 return true
2674 }
2675 } else {
2676 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2677 return true
2678 }
2679 nniPortID, err := va.GetPortID(device.NniPort)
2680 if err != nil {
2681 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2682 }
2683 flow := BuildICMPv6Flow(nniPortID, vnet)
2684 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302685 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302686 if err != nil {
2687 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2688 return true
2689 }
2690
2691 flow = BuildDSArpFlow(nniPortID, vnet)
2692 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302693 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302694 if err != nil {
2695 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2696 return true
2697 }
2698
2699 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2700 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2701 return true
2702 }
2703 va.VnetsByName.Range(delicmpv6)
2704 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2705 err := ProcessIcmpv6McGroup(device.Name, true)
2706 if err != nil {
2707 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2708 return
2709 }
2710}
2711
2712// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302713func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Akash Sonief452f12024-12-12 18:20:28 +05302714 logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302715 delflows := func(key interface{}, value interface{}) bool {
2716 device := value.(*VoltDevice)
2717 if device.SerialNum != deviceSerialNum {
2718 return true
2719 }
2720 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2721 vnetList := vnetListIntf.(*util.ConcurrentMap)
2722 vnetList.Remove(vnet.Name)
2723 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2724 if vnetList.Length() != 0 {
2725 logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2726 return true
2727 }
2728 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2729 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2730 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2731 // The step will be as follow:
2732 // 1. Deact Service
2733 // 2. Pod Reboot
2734 // 3. Pending Delete Service triggered
2735 // 4. Del Service Ind followed by DelVnet req from NB
2736 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2737 // hence the flow will not be cleared
2738 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2739 return true
2740 }
2741 if portID, err := va.GetPortID(device.NniPort); err == nil {
2742 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2743 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2744 return false
2745 }
2746 flow := BuildICMPv6Flow(portID, vnet)
2747 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302748 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302749 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2750 }
2751 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2752
2753 flow = BuildDSArpFlow(portID, vnet)
2754 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302755 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302756 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2757 }
2758 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2759 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2760 }
2761 return false
2762 }
2763 va.DevicesDisc.Range(delflows)
2764}
2765
2766// BuildICMPv6Flow to Build DS flow for ICMPv6
2767func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302768 logger.Debugw(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302769 flow := &of.VoltFlow{}
2770 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2771 subFlow := of.NewVoltSubFlow()
2772
2773 subFlow.SetICMPv6Match()
2774 subFlow.SetMatchVlan(vnet.SVlan)
2775 subFlow.SetInPort(inport)
2776 subFlow.SetPopVlan()
2777 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2778 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2779 subFlow.Priority = of.McFlowPriority
2780 var metadata uint64
2781 if vnet.VlanControl == None {
2782 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2783 } else {
2784 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2785 }
2786 subFlow.SetTableMetadata(metadata)
2787 metadata = uint64(vnet.setPbitRemarking())
2788
2789 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2790 subFlow.SetWriteMetadata(metadata)
2791 flow.SubFlows[subFlow.Cookie] = subFlow
2792 return flow
2793}
2794
vinokuma926cb3e2023-03-29 11:41:06 +05302795// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302796func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302797 logger.Debugw(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302798
2799 flow := &of.VoltFlow{}
2800 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2801 subFlow := of.NewVoltSubFlow()
2802
2803 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2804 subFlow.SetArpMatch()
2805 subFlow.SetMatchDstMac(BcastMAC)
2806 subFlow.SetMatchVlan(vnet.SVlan)
2807 subFlow.SetInPort(inport)
2808 subFlow.SetPopVlan()
2809 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2810
2811 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2812 subFlow.Priority = of.McFlowPriority
2813
2814 var metadata uint64
2815 if vnet.VlanControl == None {
2816 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2817 } else {
2818 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2819 }
2820 subFlow.SetTableMetadata(metadata)
2821 metadata = uint64(vnet.setPbitRemarking())
2822 subFlow.SetWriteMetadata(metadata)
2823
2824 flow.SubFlows[subFlow.Cookie] = subFlow
2825 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2826 return flow
2827}
2828
2829// setPbitRemarking to set Pbit remarking
2830func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302831 // Remarkable
2832 // Remarked Pbit Pbit
2833 // |-----------------------------| |------|
2834 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2835 // 000 000 000 000 000 000 000 000 00000000
2836
2837 // Eg:
2838 // For 6:3 & 7:1
2839 // 001 011 000 000 000 000 000 000 11000000
2840
2841 var remarkable uint8
2842 var remarked uint32
2843 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2844 remarkable = remarkable | 1<<refPbit
2845 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2846 }
2847 return remarked<<8 | uint32(remarkable)
2848}
2849
2850// ProcessIcmpv6McGroup to add icmpv6 multicast group
2851func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302852 logger.Info(ctx, "Creating ICMPv6 MC Group")
2853 va := GetApplication()
2854 vd := va.GetDevice(device)
2855 group := &of.Group{}
2856 group.GroupID = ICMPv6ArpGroupID
2857 group.Device = device
2858 if delete {
2859 if !vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302860 logger.Debug(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
Naveen Sampath04696f72022-06-13 15:19:14 +05302861 return nil //TODO
2862 }
2863 vd.icmpv6GroupAdded = false
2864 group.Command = of.GroupCommandDel
2865 group.ForceAction = true
2866 } else {
2867 if vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302868 logger.Debug(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
Naveen Sampath04696f72022-06-13 15:19:14 +05302869 return nil //TODO
2870 }
2871 vd.icmpv6GroupAdded = true
2872 group.Command = of.GroupCommandAdd
2873 receivers := GetApplication().GetIcmpv6Receivers(device)
2874 group.Buckets = append(group.Buckets, receivers...)
2875 }
2876 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2877 port, _ := GetApplication().GetNniPort(device)
2878 err := cntlr.GetController().GroupUpdate(port, device, group)
2879 return err
2880}
2881
vinokuma926cb3e2023-03-29 11:41:06 +05302882// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302883func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302884 logger.Debugw(ctx, "Is Vlan Matching", log.Fields{"cvlan": cvlan, "svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302885 switch vpv.VlanControl {
2886 case ONUCVlanOLTSVlan,
2887 OLTCVlanOLTSVlan:
2888 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2889 return true
2890 }
2891 case ONUCVlan,
2892 OLTSVlan,
2893 None:
2894 if vpv.SVlan == svlan {
2895 return true
2896 }
2897 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302898 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302899 }
2900 return false
2901}
2902
vinokuma926cb3e2023-03-29 11:41:06 +05302903// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302904func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302905 logger.Debugw(ctx, "Push Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302906 for cookie := range flow.SubFlows {
2907 cookie := strconv.FormatUint(cookie, 10)
2908 fe := &FlowEvent{
2909 eType: EventTypeControlFlowAdded,
2910 cookie: cookie,
2911 eventData: vpv,
2912 }
2913 device.RegisterFlowAddEvent(cookie, fe)
2914 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302915 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302916}
2917
vinokuma926cb3e2023-03-29 11:41:06 +05302918// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302919func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302920 logger.Debugw(ctx, "Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05302921 sendFlowFailureInd := func(key, value interface{}) bool {
2922 //svc := value.(*VoltService)
2923 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2924 return true
2925 }
2926 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2927 vpv.services.Range(sendFlowFailureInd)
2928}
2929
vinokuma926cb3e2023-03-29 11:41:06 +05302930// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302931func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302932 logger.Debugw(ctx, "Remove Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302933 vpv.PendingFlowLock.Lock()
2934 defer vpv.PendingFlowLock.Unlock()
2935
2936 for cookie := range flow.SubFlows {
2937 cookie := strconv.FormatUint(cookie, 10)
2938 fe := &FlowEvent{
2939 eType: EventTypeControlFlowRemoved,
2940 device: device.Name,
2941 cookie: cookie,
2942 eventData: vpv,
2943 }
2944 device.RegisterFlowDelEvent(cookie, fe)
2945 vpv.PendingDeleteFlow[cookie] = true
2946 }
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302947 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302948}
2949
vinokuma926cb3e2023-03-29 11:41:06 +05302950// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302951func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302952 logger.Debugw(ctx, "Check And Delete Vpv", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302953 vpv.PendingFlowLock.RLock()
2954 defer vpv.PendingFlowLock.RUnlock()
2955 if !vpv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302956 logger.Warnw(ctx, "Skipping removing VPV from DB as VPV delete is in progress", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
Naveen Sampath04696f72022-06-13 15:19:14 +05302957 return
2958 }
2959 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302960 logger.Debugw(ctx, "All Flows removed for VPV. Triggering VPV Deletion from DB", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302961 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302962 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2963 }
2964}
2965
vinokuma926cb3e2023-03-29 11:41:06 +05302966// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302967func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302968 vpv.PendingFlowLock.Lock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302969 logger.Debugw(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302970
2971 delete(vpv.PendingDeleteFlow, cookie)
2972 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302973 vpv.CheckAndDeleteVpv(cntx)
2974 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302975}
2976
vinokuma926cb3e2023-03-29 11:41:06 +05302977// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302978func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302979 vpv.PendingFlowLock.Lock()
2980
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302981 logger.Debugw(ctx, "VPV Flow Remove Failure Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302982
2983 sendFlowFailureInd := func(key, value interface{}) bool {
2984 svc := value.(*VoltService)
2985 svc.triggerServiceFailureInd(errorCode, errReason)
2986 return true
2987 }
2988 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2989 vpv.services.Range(sendFlowFailureInd)
2990
2991 if vpv.DeleteInProgress {
2992 delete(vpv.PendingDeleteFlow, cookie)
2993 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302994 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302995 } else {
2996 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302997 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302998 }
2999}
3000
vinokuma926cb3e2023-03-29 11:41:06 +05303001// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303002func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303003 logger.Debugw(ctx, "Remove Flows", log.Fields{"PortName": flow.PortName, "DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05303004 vv.VnetLock.Lock()
3005 defer vv.VnetLock.Unlock()
3006
3007 var flowMap map[string]bool
3008 var ok bool
3009
3010 for cookie := range flow.SubFlows {
3011 cookie := strconv.FormatUint(cookie, 10)
3012 fe := &FlowEvent{
3013 eType: EventTypeDeviceFlowRemoved,
3014 device: device.Name,
3015 cookie: cookie,
3016 eventData: vv,
3017 }
3018 device.RegisterFlowDelEvent(cookie, fe)
3019 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
3020 flowMap = make(map[string]bool)
3021 }
3022 flowMap[cookie] = true
3023 vv.PendingDeleteFlow[device.Name] = flowMap
3024 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303025 vv.WriteToDb(cntx)
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05303026 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05303027}
3028
vinokuma926cb3e2023-03-29 11:41:06 +05303029// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303030func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303031 logger.Debugw(ctx, "Check And Delete Vnet", log.Fields{"Device": device, "Vnet": vv.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05303032 if !vv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303033 logger.Warnw(ctx, "Skipping removing Vnet from DB as Vnet delete is in progress", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303034 return
3035 }
3036 vv.VnetPortLock.RLock()
3037 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
3038 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
3039 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303040 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05303041 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
3042 } else {
3043 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
3044 }
3045 vv.VnetPortLock.RUnlock()
3046}
3047
vinokuma926cb3e2023-03-29 11:41:06 +05303048// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303049func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303050 vv.VnetLock.Lock()
3051 defer vv.VnetLock.Unlock()
3052
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303053 logger.Debugw(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303054
3055 if _, ok := vv.PendingDeleteFlow[device]; ok {
3056 delete(vv.PendingDeleteFlow[device], cookie)
3057 }
3058
3059 //Check and update success for pending disable request
3060 if d := GetApplication().GetDevice(device); d != nil {
3061 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
3062 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303063 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303064 }
3065 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303066 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05303067}
3068
vinokuma926cb3e2023-03-29 11:41:06 +05303069// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303070func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303071 vv.VnetLock.Lock()
3072 defer vv.VnetLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303073 logger.Debugw(ctx, "Vnet Flow Remove Failure Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303074
3075 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3076 if _, ok := flowMap[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303077 logger.Debugw(ctx, "Device Flow Remove Failure Notification", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303078
3079 if vv.DeleteInProgress {
3080 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303081 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303082 }
3083 return
3084 }
3085 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303086 logger.Debugw(ctx, "Device Flow Remove Failure Notification for Unknown cookie", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303087}
3088
vinokuma926cb3e2023-03-29 11:41:06 +05303089// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303090func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303091 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3092 // When multiple Igmp-suported service enabled, comment "return false"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303093 logger.Debugw(ctx, "Igmp Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303094
3095 sendFlowFailureInd := func(key, value interface{}) bool {
3096 svc := value.(*VoltService)
3097 if svc.IgmpEnabled {
3098 svc.triggerServiceFailureInd(errorCode, errReason)
3099 return false
3100 }
3101 return true
3102 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303103 logger.Debugw(ctx, "US IGMP Flow Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303104 vpv.services.Range(sendFlowFailureInd)
3105}
3106
3107// GetMatchingMcastService to get matching multicast service
3108func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303109 logger.Debugw(ctx, "Get Matching Mcast Service", log.Fields{"Port": port, "Device": device, "Cvlan": cvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05303110 var service *VoltService
3111 dIntf, ok := va.DevicesDisc.Load(device)
3112 if !ok {
3113 return nil
3114 }
3115 d := dIntf.(*VoltDevice)
3116
3117 // If the port is NNI port, the services dont exist on it. The svc then
3118 // must be obtained from a different context and is not included here
3119 if port == d.NniPort {
3120 return nil
3121 }
3122
3123 // This is an access port and the port should have all the associated
3124 // services which can be uniquely identified by the VLANs in the packet
3125 vnets, ok := va.VnetsByPort.Load(port)
3126
3127 if !ok {
3128 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3129 return nil
3130 }
3131 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3132 getMcastService := func(key, value interface{}) bool {
3133 srv := value.(*VoltService)
3134 if srv.IgmpEnabled {
3135 service = srv
3136
3137 //TODO: Current implementation supports only for single service with Igmp Enabled
3138 //FIX-ME: When multiple service suports Igmp, update of logic required
3139 return false
3140 }
3141 return true
3142 }
3143
3144 for _, vpv := range vnets.([]*VoltPortVnet) {
3145 if vpv.CVlan == cvlan {
3146 vpv.services.Range(getMcastService)
3147 if service != nil {
3148 break
3149 }
3150 }
3151 }
3152 return service
3153}
3154
vinokuma926cb3e2023-03-29 11:41:06 +05303155// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303156func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303157 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303158 vv.VnetLock.Lock()
3159 cookieList := []uint64{}
3160 flowMap := vv.PendingDeleteFlow[device]
3161
3162 for cookie := range flowMap {
3163 cookieList = append(cookieList, convertToUInt64(cookie))
3164 }
3165 vv.VnetLock.Unlock()
3166
3167 if len(cookieList) == 0 {
3168 return false
3169 }
3170
3171 for _, cookie := range cookieList {
3172 if vd := GetApplication().GetDevice(device); vd != nil {
3173 flow := &of.VoltFlow{}
3174 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3175 subFlow := of.NewVoltSubFlow()
3176 subFlow.Cookie = cookie
3177 flow.SubFlows[cookie] = subFlow
3178 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303179 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303180 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3181 }
3182 }
3183 }
3184 return true
3185}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303186
vinokuma926cb3e2023-03-29 11:41:06 +05303187// JSONMarshal wrapper function for json Marshal VoltVnet
3188func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303189 return json.Marshal(VoltVnet{
3190 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303191 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303192 VnetOper: VnetOper{
3193 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3194 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3195 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3196 },
3197 })
3198}
3199
vinokuma926cb3e2023-03-29 11:41:06 +05303200// JSONMarshal wrapper function for json Marshal VoltPortVnet
3201func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303202 return json.Marshal(VoltPortVnet{
3203 Device: vpv.Device,
3204 Port: vpv.Port,
3205 PonPort: vpv.PonPort,
3206 VnetName: vpv.VnetName,
3207 SVlan: vpv.SVlan,
3208 CVlan: vpv.CVlan,
3209 UniVlan: vpv.UniVlan,
3210 SVlanTpid: vpv.SVlanTpid,
3211 DhcpRelay: vpv.DhcpRelay,
3212 ArpRelay: vpv.ArpRelay,
3213 PppoeIa: vpv.PppoeIa,
3214 MacLearning: vpv.MacLearning,
3215 DhcpStatus: vpv.DhcpStatus,
3216 DhcpExpiryTime: vpv.DhcpExpiryTime,
3217 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3218 FlowsApplied: vpv.FlowsApplied,
3219 Ipv4Addr: vpv.Ipv4Addr,
3220 Ipv6Addr: vpv.Ipv6Addr,
3221 MacAddr: vpv.MacAddr,
3222 LearntMacAddr: vpv.LearntMacAddr,
3223 CircuitID: vpv.CircuitID,
3224 RemoteID: vpv.RemoteID,
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05303225 IsOption82Enabled: vpv.IsOption82Enabled,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303226 RelayState: vpv.RelayState,
3227 PPPoeState: vpv.PPPoeState,
3228 RelayStatev6: vpv.RelayStatev6,
3229 IgmpEnabled: vpv.IgmpEnabled,
3230 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3231 McastService: vpv.McastService,
3232 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3233 VlanControl: vpv.VlanControl,
3234 MvlanProfileName: vpv.MvlanProfileName,
3235 Version: vpv.Version,
3236 McastTechProfileID: vpv.McastTechProfileID,
3237 McastPbit: vpv.McastPbit,
3238 McastUsMeterID: vpv.McastUsMeterID,
3239 AllowTransparent: vpv.AllowTransparent,
3240 SchedID: vpv.SchedID,
3241 DHCPv6DUID: vpv.DHCPv6DUID,
3242 PendingDeleteFlow: vpv.PendingDeleteFlow,
3243 DeleteInProgress: vpv.DeleteInProgress,
3244 Blocked: vpv.Blocked,
3245 DhcpPbit: vpv.DhcpPbit,
3246 })
3247}
Tinoj Josephec742f62022-09-29 19:11:10 +05303248
3249func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303250 logger.Debugw(ctx, "Is Service Activated", log.Fields{"Name": vpv.Port})
Tinoj Josephec742f62022-09-29 19:11:10 +05303251 isActivated := false
3252 vpv.services.Range(func(key, value interface{}) bool {
3253 svc := value.(*VoltService)
3254 if svc.IsActivated {
3255 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3256 isActivated = true
3257 return false //to exit loop
3258 }
3259 return true
3260 })
3261 return isActivated
3262}