blob: 72c43fd7963a64b61873e486c8dc9a558cda3117 [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 {
Tinoj Joseph1d108322022-07-13 10:07:39 +0530317 logger.Debugw(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 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530764 logger.Warnw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion 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",
859 log.Fields{"service count": vpv.servicesCount.Load()})
860
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
980// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
981func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530982 logger.Debugw(ctx, "Get Remarked Priority", log.Fields{"Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +0530983 dsPbit := uint8(0)
984 matchpbitsFunc := func(key, value interface{}) bool {
985 svc := value.(*VoltService)
986 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530987 logger.Warnw(ctx, "Pbit match found with service",
Naveen Sampath04696f72022-06-13 15:19:14 +0530988 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
989 dsPbit = uint8(remarkPbit)
990 return false //Returning false to stop the Range loop
991 }
992 // When no remarking info is available, remark the incoming pbit
993 // to highest pbit configured for the subscriber (across all subservices associated)
994 svcPbit := uint8(svc.Pbits[0])
995 if svcPbit > dsPbit {
996 dsPbit = svcPbit
997 }
998 return true
999 }
1000 vpv.services.Range(matchpbitsFunc)
1001 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
1002 return dsPbit
1003}
1004
1005// AddSvc adds a service on the VNET on a port. The addition is
1006// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301007func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301008 logger.Infow(ctx, "Add Service to VPV", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301009 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301010 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +05301011 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
1012
1013 // Learn the circuit-id and remote-id from the service
1014 // TODO: There must be a better way of doing this. This
1015 // may be explored
1016 if svc.IgmpEnabled {
1017 vpv.IgmpEnabled = true
1018 }
1019 // first time service activation MacLearning will have default value as None.
1020 // to handle reciliency if anythng other then None we should retain it .
1021 if svc.MacLearning == MacLearningNone {
1022 if !vpv.DhcpRelay && !vpv.ArpRelay {
1023 svc.MacLearning = MacLearningNone
1024 } else if vpv.MacLearning == Learn {
1025 svc.MacLearning = Learn
1026 } else if vpv.MacLearning == ReLearn {
1027 svc.MacLearning = ReLearn
1028 }
1029 }
1030
vinokuma926cb3e2023-03-29 11:41:06 +05301031 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301032 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1033 svc.MacAddr = vpv.MacAddr
1034 } else if vpv.servicesCount.Load() == 1 {
1035 vpv.MacAddr = svc.MacAddr
1036 }
1037
1038 vpv.MacLearning = svc.MacLearning
1039 vpv.PonPort = svc.PonPort
1040 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301041 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301042 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301043 if svc.McastService {
1044 vpv.McastService = true
1045 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301046 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301047 vpv.McastPbit = svc.Pbits[0]
1048 vpv.McastUsMeterID = svc.UsMeterID
1049 vpv.SchedID = svc.SchedID
1050 }
1051 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1052 svc.AllowTransparent = vpv.AllowTransparent
1053 svc.SVlanTpid = vpv.SVlanTpid
1054
vinokuma926cb3e2023-03-29 11:41:06 +05301055 // Ensure configuring the mvlan profile only once
1056 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301057 if svc.MvlanProfileName != "" {
1058 if vpv.MvlanProfileName == "" {
1059 vpv.MvlanProfileName = svc.MvlanProfileName
1060 } else {
1061 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1062 }
1063 }
1064
Akash Sonia8246972023-01-03 10:37:08 +05301065 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301066 if err != nil {
1067 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301068 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1069 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301070 return
1071 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301072 if !svc.IsActivated {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301073 logger.Warnw(ctx, "Not pushing Service Flows: Service Not activated", log.Fields{"ServiceName": svc.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05301074 return
1075 }
Akash Sonia8246972023-01-03 10:37:08 +05301076
vinokuma926cb3e2023-03-29 11:41:06 +05301077 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301078 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1079
Akash Soni53da2852023-03-15 00:31:31 +05301080 if devConfig.UplinkPort != voltDevice.NniPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301081 logger.Warnw(ctx, "NNI port mismatch", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": voltDevice.NniPort})
Akash Sonia8246972023-01-03 10:37:08 +05301082 return
1083 }
vinokuma926cb3e2023-03-29 11:41:06 +05301084 // Push Service Flows if DHCP relay is not configured
1085 // or already DHCP flows are configured for the VPV
1086 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301087 if vpv.FlowsApplied {
1088 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301089 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301090 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301091 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301092 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1093 }
1094 }
1095 }
1096
vinokuma926cb3e2023-03-29 11:41:06 +05301097 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301098 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1099 // service with Igmp Enabled needs to be installed
1100 if svc.IgmpEnabled && vpv.FlowsApplied {
1101 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301102 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301103 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301104 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1105 }
1106
1107 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301108 // For McastService, send Service Activated indication once IGMP US flow is pushed
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301109 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301110 }
1111 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301112 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301113}
1114
1115// setLearntMAC to set learnt mac
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301116func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301117 svc := value.(*VoltService)
1118 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301119 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301120 return true
1121}
1122
1123// PostAccessConfigSuccessInd for posting access config success indication
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301124func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301125 return true
1126}
1127
1128// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301129func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301130 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301131 logger.Debugw(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301132 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301133 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301134
1135 return true
1136}
1137
1138// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301139func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(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 Ipv6 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301142 svc.SetIpv6Addr(vpv.Ipv6Addr)
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// AddUsHsiaFlows to add upstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301149func AddUsHsiaFlows(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, "Add US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301152 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301153 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1154 }
1155 return true
1156}
1157
1158// AddDsHsiaFlows to add downstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301159func AddDsHsiaFlows(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 DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301162 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301163 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1164 }
1165 return true
1166}
1167
1168// ClearFlagsInService to clear the flags used in service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301169func ClearFlagsInService(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, "Received Cleared Flow Flags for service", log.Fields{"name": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301172 svc.ServiceLock.Lock()
1173 svc.IgmpFlowsApplied = false
1174 svc.DsDhcpFlowsApplied = false
1175 svc.DsHSIAFlowsApplied = false
1176 svc.Icmpv6FlowsApplied = false
1177 svc.UsHSIAFlowsApplied = false
1178 svc.UsDhcpFlowsApplied = false
1179 svc.PendingFlows = make(map[string]bool)
1180 svc.AssociatedFlows = make(map[string]bool)
1181 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301182 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301183 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1184 return true
1185}
1186
1187// DelDsHsiaFlows to delete hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301188// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
1189func DelDsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301190 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301191 logger.Debugw(ctx, "Delete DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301192 if err := svc.DelDsHsiaFlows(cntx, delFlowsInDevice); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301193 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1194 }
1195 return true
1196}
1197
1198// DelUsHsiaFlows to delete upstream hsia flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301199// delFlowsInDevice flag indicates that flows should be deleted only in DB/device and should not be forwarded to core
1200func DelUsHsiaFlows(cntx context.Context, key, value interface{}, delFlowsInDevice bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301201 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301202 logger.Debugw(ctx, "Delete US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301203 if err := svc.DelUsHsiaFlows(cntx, delFlowsInDevice); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301204 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1205 }
1206 return true
1207}
1208
1209// ClearServiceCounters to clear the service counters
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301210func ClearServiceCounters(cntx context.Context, key, value interface{}, flag bool) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301211 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301212 logger.Debugw(ctx, "Received Clear Service Counters", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301213 //Delete the per service counter too
1214 GetApplication().ServiceCounters.Delete(svc.Name)
1215 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301216 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301217 }
1218 return true
1219}
1220
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301221// AddMeterToDevice to add meter config to device, used in FTTB case
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301222func AddMeterToDevice(cntx context.Context, key, value interface{}, flag bool) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301223 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301224 logger.Debugw(ctx, "Received Add Meter To Device", log.Fields{"ServiceName": svc.Name})
Akash Soni53da2852023-03-15 00:31:31 +05301225 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301226 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1227 }
1228 return true
1229}
1230
vinokuma926cb3e2023-03-29 11:41:06 +05301231// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301232func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301233 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 +05301234 if !vpv.FlowsApplied || vgcRebooted {
1235 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301236 if err := vpv.AddUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301237 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301238 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1239 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301240 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301241 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301242 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1243 }
1244 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1245 log.Fields{"port": vpv.Port})
1246 //vpv.updateICMPv6McGroup(true)
1247 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301248 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301249 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301250 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1251 }
1252 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301253 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301254 if err := vpv.AddUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301255 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301256 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1257 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301258 if err := vpv.AddDsPppoeFlows(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 }
1263 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301264 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301265 }
1266}
1267
vinokuma926cb3e2023-03-29 11:41:06 +05301268// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301269func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301270 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 +05301271 // Delete HSIA & DHCP flows before deleting IGMP flows
1272 if vpv.FlowsApplied || vgcRebooted {
1273 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301274 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301275 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1276 "UniVlan": vpv.UniVlan, "Error": err})
1277 }
1278 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1279 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301280 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301281 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301282 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1283 }
1284 //vpv.updateICMPv6McGroup(false)
1285 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301286 if err := vpv.DelUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301287 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301288 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1289 }
1290 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301291 if err := vpv.DelUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301292 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301293 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1294 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301295 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301296 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301297 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1298 }
1299 }
1300 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301301 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301302 }
Akash Sonia8246972023-01-03 10:37:08 +05301303 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301304 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1305 "UniVlan": vpv.UniVlan, "Error": err})
1306 }
1307}
1308
1309// DelHsiaFlows deletes the service flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301310func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context, delFlowsInDevice bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301311 logger.Infow(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 // no HSIA flows for multicast service
1313 if !vpv.McastService {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301314 vpv.RangeOnServices(cntx, DelUsHsiaFlows, delFlowsInDevice)
1315 vpv.RangeOnServices(cntx, DelDsHsiaFlows, delFlowsInDevice)
Naveen Sampath04696f72022-06-13 15:19:14 +05301316 }
1317}
1318
vinokuma926cb3e2023-03-29 11:41:06 +05301319// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301320func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301321 //send flows deleted indication to submgr
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301322 vpv.RangeOnServices(cntx, ClearServiceCounters, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301323}
1324
1325// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301326func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301327 var vd *VoltDevice
1328 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301329 logger.Debugw(ctx, "Received Add US DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301330
1331 if vd = GetApplication().GetDevice(device); vd != nil {
1332 if vd.State != controller.DeviceStateUP {
1333 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})
1334 return nil
1335 }
1336 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301337 err := errorCodes.ErrDeviceNotFound
1338 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 +05301339 }
1340
1341 flows, err := vpv.BuildUsDhcpFlows()
1342 if err == nil {
1343 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301344 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301345 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301346 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301347 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1348 }
1349 } else {
1350 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301351 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301352 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301353 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301354 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301355 return nil
1356}
1357
1358// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301359func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301360 var vd *VoltDevice
1361 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301362 logger.Debugw(ctx, "Received Add DS DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301363
1364 if vd = GetApplication().GetDevice(device); vd != nil {
1365 if vd.State != controller.DeviceStateUP {
1366 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})
1367 return nil
1368 }
1369 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301370 err := errorCodes.ErrDeviceNotFound
1371 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 +05301372 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301373 if vd.GlobalDhcpFlowAdded {
1374 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301375 return nil
1376 }
1377
1378 flows, err := vpv.BuildDsDhcpFlows()
1379 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301380 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301381 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301382 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301383 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301384 }
1385 } else {
1386 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301387 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301388 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301389 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301390 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301391 if GetApplication().GetVendorID() != Radisys {
1392 vd.GlobalDhcpFlowAdded = true
1393 }
1394 return nil
1395}
1396
1397// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301398func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301399 logger.Info(ctx, "Received Delete DHCP Flows")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301400 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301401 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301402 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1403 }
1404
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301405 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301406 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301407 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1408 }
1409}
1410
1411// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1412// Write the status of the VPV to the DB once the delete is scheduled
1413// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301414func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301415 logger.Debugw(ctx, "Received Delete US DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301416 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1417 if err != nil {
1418 return err
1419 }
1420
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301421 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301422 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301423 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301424 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1425 }
Akash Sonia8246972023-01-03 10:37:08 +05301426
Naveen Sampath04696f72022-06-13 15:19:14 +05301427 return nil
1428}
1429
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301430func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301431 logger.Debugw(ctx, "Received US Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301432 flows, err := vpv.BuildUsDhcpFlows()
1433 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301434 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301435 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301436 return fmt.Errorf("US DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301437}
Naveen Sampath04696f72022-06-13 15:19:14 +05301438
1439// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1440// Write the status of the VPV to the DB once the delete is scheduled
1441// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301442func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301443 logger.Debugw(ctx, "Received Delete DS DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301444 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1445 if err != nil {
1446 return err
1447 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301448 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301449 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301450 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301451 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1452 }
1453 /*
Akash Sonia8246972023-01-03 10:37:08 +05301454 err = vpv.delDsDhcp6Flows(device)
1455 if err != nil {
1456 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1457 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1458 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301459 return nil
1460}
1461
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301462func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301463 logger.Debugw(ctx, "Received DS Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301464 flows, err := vpv.BuildDsDhcpFlows()
1465 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301466 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301467 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301468 return fmt.Errorf("DS DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301469}
1470
1471/*
1472func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1473 flows, err := vpv.BuildDsDhcp6Flows()
1474 if err == nil {
1475 return vpv.RemoveFlows(device, flows)
1476 }
1477 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1478 return err
1479}*/
1480
1481// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301482func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301483 var vd *VoltDevice
1484 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301485 logger.Debugw(ctx, "Received Add US Arp Flows", log.Fields{"DeviceName": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301486 if vd = GetApplication().GetDevice(device); vd != nil {
1487 if vd.State != controller.DeviceStateUP {
1488 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})
1489 return nil
1490 }
1491 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301492 err := errorCodes.ErrDeviceNotFound
1493 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 +05301494 }
1495
1496 flows, err := vpv.BuildUsArpFlows()
1497 if err == nil {
1498 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301499 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301500 return fmt.Errorf("Pushing US ARP Flow Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301501 }
1502 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301503 return fmt.Errorf("US ARP Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301504 }
1505 return nil
1506}
1507
1508// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1509// Write the status of the VPV to the DB once the delete is scheduled
1510// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301511func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301512 logger.Debugw(ctx, "Delete US ARP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301513 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1514 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301515 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301516 }
1517 flows, err := vpv.BuildUsArpFlows()
1518 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301519 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301520 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301521 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301522}
1523
1524// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301525func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301526 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1527
1528 var vd *VoltDevice
1529 device := vpv.Device
1530
1531 if vd = GetApplication().GetDevice(device); vd != nil {
1532 if vd.State != controller.DeviceStateUP {
1533 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})
1534 return nil
1535 }
1536 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301537 err := errorCodes.ErrDeviceNotFound
1538 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 +05301539 }
1540
1541 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1542 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1543
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301544 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301545 return fmt.Errorf("Pushing US PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301546 }
1547 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301548 return fmt.Errorf("US PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301549 }
1550 return nil
1551}
1552
1553// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301554func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301555 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1556 var vd *VoltDevice
1557 device := vpv.Device
1558
1559 if vd = GetApplication().GetDevice(device); vd != nil {
1560 if vd.State != controller.DeviceStateUP {
1561 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})
1562 return nil
1563 }
1564 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301565 err := errorCodes.ErrDeviceNotFound
1566 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 +05301567 }
1568
1569 flows, err := vpv.BuildDsPppoeFlows()
1570 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301571 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301572 return fmt.Errorf("Pushing DS PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301573 }
1574 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301575 return fmt.Errorf("DS PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301576 }
1577 return nil
1578}
1579
1580// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1581// Write the status of the VPV to the DB once the delete is scheduled
1582// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301583func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301584 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1585 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1586 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301587 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301588 }
1589 flows, err := vpv.BuildUsPppoeFlows()
1590 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301591 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301592 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301593 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301594}
1595
1596// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1597// Write the status of the VPV to the DB once the delete is scheduled
1598// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301599func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301600 logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1601 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1602 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301603 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301604 }
1605 flows, err := vpv.BuildDsPppoeFlows()
1606 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301607 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301608 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301609 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301610}
1611
1612// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301613func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301614 logger.Debugw(ctx, "Received Add Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301615 if !vpv.IgmpFlowsApplied || vgcRebooted {
1616 if vpv.MvlanProfileName == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301617 logger.Warn(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
Naveen Sampath04696f72022-06-13 15:19:14 +05301618 return nil
1619 }
1620 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1621 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301622 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301623 } else if device.State != controller.DeviceStateUP {
1624 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})
1625 return nil
1626 }
1627 flows, err := vpv.BuildIgmpFlows()
1628 if err == nil {
1629 for cookie := range flows.SubFlows {
1630 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1631 cookie := strconv.FormatUint(cookie, 10)
1632 fe := &FlowEvent{
1633 eType: EventTypeUsIgmpFlowAdded,
1634 cookie: cookie,
1635 eventData: vpv,
1636 }
1637 vd.RegisterFlowAddEvent(cookie, fe)
1638 }
1639 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301640 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301641 return err1
1642 }
1643 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301644 return fmt.Errorf("IGMP Flow Add Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301645 }
1646 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301647 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301648 }
1649 return nil
1650}
1651
1652// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1653// Write the status of the VPV to the DB once the delete is scheduled
1654// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301655func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301656 logger.Debugw(ctx, "Received Delete Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301657 if vpv.IgmpFlowsApplied || vgcRebooted {
1658 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1659 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301660 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301661 }
1662 flows, err := vpv.BuildIgmpFlows()
1663 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301664 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301665 return err1
1666 }
1667 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301668 return fmt.Errorf("IGMP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301669 }
1670 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301671 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301672 }
1673 return nil
1674}
1675
1676// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1677// The flows included by this function cover US only as the DS is
1678// created either automatically by the VOLTHA or at the device level
1679// earlier
1680func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301681 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301682 flow := &of.VoltFlow{}
1683 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1684
Naveen Sampath04696f72022-06-13 15:19:14 +05301685 subFlow := of.NewVoltSubFlow()
1686 subFlow.SetTableID(0)
1687
vinokuma926cb3e2023-03-29 11:41:06 +05301688 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301689 subFlow.SetMatchVlan(vpv.CVlan)
1690 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1691 subFlow.SetPcp(vpv.UsPonSTagPriority)
1692 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301693 } else {
1694 subFlow.SetMatchVlan(vpv.UniVlan)
1695 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301696 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301697 }
1698 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301699 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301700 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301701 uniport, err := GetApplication().GetPortID(vpv.Port)
1702 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301703 return nil, fmt.Errorf("failed to fetch uni port %s from vpv : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301704 }
1705 subFlow.SetInPort(uniport)
1706 // PortName and PortID to be used for validation of port before flow pushing
1707 flow.PortID = uniport
1708 flow.PortName = vpv.Port
1709 subFlow.SetReportToController()
1710
1711 // Set techprofile, meterid of first service
1712 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301713 vs := value.(*VoltService)
1714 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301715 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301716 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301717 } else {
1718 writemetadata = uint64(vs.TechProfileID) << 32
1719 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301720 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301721 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301722 return false
1723 })
1724
Naveen Sampath04696f72022-06-13 15:19:14 +05301725 // metadata := uint64(uniport)
1726 // subFlow.SetWriteMetadata(metadata)
1727 allowTransparent := 0
1728 if vpv.AllowTransparent {
1729 allowTransparent = 1
1730 }
vinokuma926cb3e2023-03-29 11:41:06 +05301731 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301732 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1733 subFlow.SetTableMetadata(metadata)
1734 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301735 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1736 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1737 subFlow.Priority = of.DhcpFlowPriority
1738
1739 flow.SubFlows[subFlow.Cookie] = subFlow
1740 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1741 return flow, nil
1742}
1743
1744// BuildDsDhcpFlows to build the downstream dhcp flows
1745func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301746 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1747 flow := &of.VoltFlow{}
1748 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1749 subFlow := of.NewVoltSubFlow()
1750 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301751 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301752 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301753 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301754 }
1755 subFlow.SetUdpv4Match()
1756 subFlow.SrcPort = 67
1757 subFlow.DstPort = 68
1758 uniport, _ := GetApplication().GetPortID(vpv.Port)
1759 nni, err := GetApplication().GetNniPort(vpv.Device)
1760 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301761 return nil, fmt.Errorf("failed to fetch nni port %s from vpv : %w", nni, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301762 }
1763 nniport, err := GetApplication().GetPortID(nni)
1764 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301765 return nil, fmt.Errorf("failed to fetch port id %d for nni : %w", nniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301766 }
1767 subFlow.SetInPort(nniport)
1768 // PortName and PortID to be used for validation of port before flow pushing
1769 flow.PortID = uniport
1770 flow.PortName = vpv.Port
1771 // metadata := uint64(uniport)
1772 // subFlow.SetWriteMetadata(metadata)
1773 allowTransparent := 0
1774 if vpv.AllowTransparent {
1775 allowTransparent = 1
1776 }
vinokuma926cb3e2023-03-29 11:41:06 +05301777 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301778 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1779 subFlow.SetTableMetadata(metadata)
1780 subFlow.Priority = of.DhcpFlowPriority
1781 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301782 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301783 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301784 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301785
1786 flow.SubFlows[subFlow.Cookie] = subFlow
1787 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1788
1789 return flow, nil
1790}
1791
1792// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1793// application.
1794func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301795 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301796 flow := &of.VoltFlow{}
1797 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1798
Naveen Sampath04696f72022-06-13 15:19:14 +05301799 subFlow := of.NewVoltSubFlow()
1800 subFlow.SetTableID(0)
1801
1802 subFlow.SetMatchVlan(vpv.UniVlan)
1803 subFlow.SetSetVlan(vpv.CVlan)
1804 subFlow.SetUdpv6Match()
1805 subFlow.SrcPort = 546
1806 subFlow.DstPort = 547
1807 uniport, err := GetApplication().GetPortID(vpv.Port)
1808 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301809 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301810 }
1811 // Set techprofile, meterid of first service
1812 vpv.services.Range(func(key, value interface{}) bool {
1813 svc := value.(*VoltService)
1814 writemetadata := uint64(svc.TechProfileID) << 32
1815 subFlow.SetWriteMetadata(writemetadata)
1816 subFlow.SetMeterID(svc.UsMeterID)
1817 return false
1818 })
1819 subFlow.SetInPort(uniport)
1820 // PortName and PortID to be used for validation of port before flow pushing
1821 flow.PortID = uniport
1822 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301823 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301824 // metadata := uint64(uniport)
1825 // subFlow.SetWriteMetadata(metadata)
1826 allowTransparent := 0
1827 if vpv.AllowTransparent {
1828 allowTransparent = 1
1829 }
1830 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1831 subFlow.SetTableMetadata(metadata)
1832 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301833 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301834 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1835 subFlow.Priority = of.DhcpFlowPriority
1836
1837 flow.SubFlows[subFlow.Cookie] = subFlow
1838 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1839 return flow, nil
1840}
1841
1842// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1843// application.
1844func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1845 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1846
1847 flow := &of.VoltFlow{}
1848 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1849 subFlow := of.NewVoltSubFlow()
1850 subFlow.SetTableID(0)
1851
1852 vpv.setDsMatchVlan(subFlow)
1853 subFlow.SetUdpv6Match()
1854 subFlow.SrcPort = 547
1855 subFlow.DstPort = 547
1856 uniport, _ := GetApplication().GetPortID(vpv.Port)
1857 nni, err := GetApplication().GetNniPort(vpv.Device)
1858 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301859 logger.Errorw(ctx, "Failed to fetch nni port from vpv", log.Fields{"error": err, "device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301860 return nil, err
1861 }
1862 nniport, err := GetApplication().GetPortID(nni)
1863 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301864 logger.Errorw(ctx, "Failed to fetch port ID for nni", log.Fields{"error": err, "nni": nni})
Naveen Sampath04696f72022-06-13 15:19:14 +05301865 return nil, err
1866 }
1867 subFlow.SetInPort(nniport)
1868 // PortName and PortID to be used for validation of port before flow pushing
1869 flow.PortID = uniport
1870 flow.PortName = vpv.Port
1871 // metadata := uint64(uniport)
1872 // subFlow.SetWriteMetadata(metadata)
1873 allowTransparent := 0
1874 if vpv.AllowTransparent {
1875 allowTransparent = 1
1876 }
1877 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1878 subFlow.SetTableMetadata(metadata)
1879 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301880 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301881 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1882 subFlow.Priority = of.DhcpFlowPriority
1883
1884 flow.SubFlows[subFlow.Cookie] = subFlow
1885 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1886 return flow, nil
1887}
1888
1889// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1890// The flows included by this function cover US only as the DS is
1891// created either automatically by the VOLTHA or at the device level
1892// earlier
1893func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301894 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301895 flow := &of.VoltFlow{}
1896 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1897
Naveen Sampath04696f72022-06-13 15:19:14 +05301898 subFlow := of.NewVoltSubFlow()
1899 subFlow.SetTableID(0)
1900
1901 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1902 subFlow.SetMatchSrcMac(vpv.MacAddr)
1903 }
1904
1905 subFlow.SetMatchDstMac(BroadcastMAC)
1906 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1907 return nil, err
1908 }
1909 subFlow.SetArpMatch()
1910 uniport, err := GetApplication().GetPortID(vpv.Port)
1911 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301912 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301913 }
1914 subFlow.SetInPort(uniport)
1915 // PortName and PortID to be used for validation of port before flow pushing
1916 flow.PortID = uniport
1917 flow.PortName = vpv.Port
1918 subFlow.SetReportToController()
1919 allowTransparent := 0
1920 if vpv.AllowTransparent {
1921 allowTransparent = 1
1922 }
1923 metadata := uint64(uniport)
1924 subFlow.SetWriteMetadata(metadata)
1925 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1926 subFlow.SetTableMetadata(metadata)
1927 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1928 subFlow.Priority = of.ArpFlowPriority
1929
1930 flow.SubFlows[subFlow.Cookie] = subFlow
1931 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1932 return flow, nil
1933}
1934
1935// setUsMatchVlan to set upstream match vlan
1936func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301937 logger.Debugw(ctx, "Set Us Match Vlan", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05301938 switch vpv.VlanControl {
1939 case None:
1940 flow.SetMatchVlan(vpv.SVlan)
1941 case ONUCVlanOLTSVlan:
1942 flow.SetMatchVlan(vpv.CVlan)
1943 case OLTCVlanOLTSVlan:
1944 flow.SetMatchVlan(vpv.UniVlan)
1945 //flow.SetSetVlan(vpv.CVlan)
1946 case ONUCVlan:
1947 flow.SetMatchVlan(vpv.SVlan)
1948 case OLTSVlan:
1949 flow.SetMatchVlan(vpv.UniVlan)
1950 //flow.SetSetVlan(vpv.SVlan)
1951 default:
1952 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1953 return errorCodes.ErrInvalidParamInRequest
1954 }
1955 return nil
1956}
1957
1958// BuildUsPppoeFlows to build upstream pppoe flows
1959func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301960 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301961 flow := &of.VoltFlow{}
1962 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301963 subFlow := of.NewVoltSubFlow()
1964 subFlow.SetTableID(0)
1965
1966 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1967 subFlow.SetMatchSrcMac(vpv.MacAddr)
1968 }
1969
1970 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1971 return nil, err
1972 }
1973 subFlow.SetPppoeDiscoveryMatch()
1974 uniport, err := GetApplication().GetPortID(vpv.Port)
1975 if err != nil {
1976 return nil, err
1977 }
1978 subFlow.SetInPort(uniport)
1979 subFlow.SetReportToController()
1980 // PortName and PortID to be used for validation of port before flow pushing
1981 flow.PortID = uniport
1982 flow.PortName = vpv.Port
1983
1984 allowTransparent := 0
1985 if vpv.AllowTransparent {
1986 allowTransparent = 1
1987 }
1988 metadata := uint64(uniport)
1989 subFlow.SetWriteMetadata(metadata)
1990
1991 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1992 subFlow.SetTableMetadata(metadata)
1993
vinokuma926cb3e2023-03-29 11:41:06 +05301994 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301995 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
1996 subFlow.Priority = of.PppoeFlowPriority
1997
1998 flow.SubFlows[subFlow.Cookie] = subFlow
1999 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2000 return flow, nil
2001}
2002
2003// BuildDsPppoeFlows to build downstream pppoe flows
2004func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302005 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
2006 flow := &of.VoltFlow{}
2007 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2008 subFlow := of.NewVoltSubFlow()
2009 subFlow.SetTableID(0)
2010
2011 vpv.setDsMatchVlan(subFlow)
2012 subFlow.SetPppoeDiscoveryMatch()
2013
2014 if NonZeroMacAddress(vpv.MacAddr) {
2015 subFlow.SetMatchDstMac(vpv.MacAddr)
2016 }
2017
2018 uniport, _ := GetApplication().GetPortID(vpv.Port)
2019 nni, err := GetApplication().GetNniPort(vpv.Device)
2020 if err != nil {
2021 return nil, err
2022 }
2023 nniport, err := GetApplication().GetPortID(nni)
2024 if err != nil {
2025 return nil, err
2026 }
2027 subFlow.SetInPort(nniport)
2028 // PortName and PortID to be used for validation of port before flow pushing
2029 flow.PortID = uniport
2030 flow.PortName = vpv.Port
2031 metadata := uint64(uniport)
2032 subFlow.SetWriteMetadata(metadata)
2033 allowTransparent := 0
2034 if vpv.AllowTransparent {
2035 allowTransparent = 1
2036 }
2037 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2038 subFlow.SetTableMetadata(metadata)
2039 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302040 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302041 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2042 subFlow.Priority = of.PppoeFlowPriority
2043
2044 flow.SubFlows[subFlow.Cookie] = subFlow
2045 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2046 return flow, nil
2047}
2048
2049// setDsMatchVlan to set downstream match vlan
2050func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302051 logger.Debugw(ctx, "Set Ds Match Vlan", log.Fields{"Vlan": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302052 switch vpv.VlanControl {
2053 case None:
2054 flow.SetMatchVlan(vpv.SVlan)
2055 case ONUCVlanOLTSVlan,
2056 OLTCVlanOLTSVlan,
2057 ONUCVlan,
2058 OLTSVlan:
2059 flow.SetMatchVlan(vpv.SVlan)
2060 default:
2061 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2062 }
2063}
2064
2065// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2066// in the US direction.
2067func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2068 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2069 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2070 if mvp == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302071 return nil, errors.New("mvlan profile configured not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05302072 }
2073 mvlan := mvp.GetUsMatchVlan()
2074 flow := &of.VoltFlow{}
2075 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2076 subFlow := of.NewVoltSubFlow()
2077 subFlow.SetTableID(0)
2078
Akash Sonia8246972023-01-03 10:37:08 +05302079 subFlow.SetMatchVlan(vpv.UniVlan)
2080 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302081
2082 uniport, err := GetApplication().GetPortID(vpv.Port)
2083 if err != nil {
2084 return nil, err
2085 }
2086 subFlow.SetInPort(uniport)
2087 // PortName and PortID to be used for validation of port before flow pushing
2088 flow.PortID = uniport
2089 flow.PortName = vpv.Port
2090
2091 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2092 subFlow.SetMatchSrcMac(vpv.MacAddr)
2093 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302094 logger.Debugw(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302095 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302096
2097 if vpv.McastService {
2098 metadata := uint64(vpv.McastUsMeterID)
2099 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2100 subFlow.SetMatchPbit(vpv.McastPbit)
2101 subFlow.SetMeterID(vpv.McastUsMeterID)
2102 subFlow.SetWriteMetadata(metadata)
2103 } else {
2104 // Set techprofile, meterid of first service
2105 vpv.services.Range(func(key, value interface{}) bool {
2106 svc := value.(*VoltService)
2107 writemetadata := uint64(svc.TechProfileID) << 32
2108 subFlow.SetWriteMetadata(writemetadata)
2109 subFlow.SetMeterID(svc.UsMeterID)
2110 return false
2111 })
2112 }
2113
2114 allowTransparent := 0
2115 if vpv.AllowTransparent {
2116 allowTransparent = 1
2117 }
2118 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2119 subFlow.SetTableMetadata(metadata)
2120 subFlow.SetIgmpMatch()
2121 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302122 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302123 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2124 subFlow.Priority = of.IgmpFlowPriority
2125
2126 flow.SubFlows[subFlow.Cookie] = subFlow
2127 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2128 return flow, nil
2129}
2130
2131// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302132func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302133 if vpv.DeleteInProgress {
2134 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2135 return
2136 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302137 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302138}
2139
vinokuma926cb3e2023-03-29 11:41:06 +05302140// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302141func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302142 vpv.PendingFlowLock.RLock()
2143 defer vpv.PendingFlowLock.RUnlock()
2144 vpv.Version = database.PresentVersionMap[database.VpvPath]
2145 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302146 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 +05302147 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2148 "UniVlan": vpv.UniVlan, "Error": err})
2149 }
2150 }
2151}
2152
2153// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302154func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302155 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 +05302156 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302157}
2158
2159// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302160func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302161 vpv.RangeOnServices(cntx, ClearFlagsInService, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302162}
2163
2164// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302165func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302166 logger.Debugw(ctx, "Clear All Vpv Flags", log.Fields{"Port": vpv.Port, "Device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302167 vpv.PendingFlowLock.Lock()
2168 vpv.FlowsApplied = false
2169 vpv.IgmpFlowsApplied = false
2170 vpv.PendingDeleteFlow = make(map[string]bool)
2171 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302172 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302173 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2174 log.Fields{"device": vpv.Device, "port": vpv.Port,
2175 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2176}
2177
2178// CreateVpvFromString to create vpv from string
2179func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302180 logger.Info(ctx, "Create Vpv From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05302181 var vpv VoltPortVnet
2182 if err := json.Unmarshal(b, &vpv); err == nil {
2183 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2184 if !ok {
2185 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2186 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2187 }
2188 vpv.servicesCount = atomic.NewUint64(0)
2189 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2190 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2191 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2192 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2193 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2194 vnet.associatePortToVnet(vpv.Port)
2195 }
2196
2197 if vpv.DeleteInProgress {
2198 va.VoltPortVnetsToDelete[&vpv] = true
2199 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2200 }
2201 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2202 }
2203}
2204
2205// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302206func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302207 logger.Info(ctx, "Restore Vpvs From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302208 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302209 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302210 for hash, vpv := range vpvs {
2211 b, ok := vpv.Value.([]byte)
2212 if !ok {
2213 logger.Warn(ctx, "The value type is not []byte")
2214 continue
2215 }
2216 va.CreateVpvFromString(b, hash)
2217 }
2218}
2219
2220// GetVnetByPort : VNET related functionality of VOLT Application here on.
2221// Get the VNET from a port. The port identity is passed as device and port identities in string.
2222// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2223// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2224func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302225 logger.Debugw(ctx, "Get Vnet By Port", log.Fields{"port": port, "svlan": svlan, "cvlan": cvlan, "univlan": univlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302226 if _, ok := va.VnetsByPort.Load(port); !ok {
2227 return nil
2228 }
2229 vpvs, _ := va.VnetsByPort.Load(port)
2230 for _, vpv := range vpvs.([]*VoltPortVnet) {
2231 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2232 return vpv
2233 }
2234 }
2235 return nil
2236}
2237
2238// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302239func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302240 // The VNET is not on the port and is to be added
2241 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2242 vpv := NewVoltPortVnet(vvnet)
2243 vpv.MacLearning = vvnet.MacLearning
2244 vpv.Port = port
2245 vvnet.associatePortToVnet(port)
2246 if _, ok := va.VnetsByPort.Load(port); !ok {
2247 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2248 }
2249 vpvsIntf, _ := va.VnetsByPort.Load(port)
2250 vpvs := vpvsIntf.([]*VoltPortVnet)
2251 vpvs = append(vpvs, vpv)
2252 va.VnetsByPort.Store(port, vpvs)
2253 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2254
2255 vpv.VpvLock.Lock()
2256 defer vpv.VpvLock.Unlock()
2257
2258 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302259 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302260
Tinoj Josephec742f62022-09-29 19:11:10 +05302261 if !vs.IsActivated {
2262 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2263 // Process the PORT UP if the port is already up
2264 d, err := va.GetDeviceFromPort(port)
2265 if err == nil {
2266 vpv.setDevice(d.Name)
2267 }
2268 vpv.WriteToDb(cntx)
2269 return vpv
2270 }
2271
Naveen Sampath04696f72022-06-13 15:19:14 +05302272 // Process the PORT UP if the port is already up
2273 d, err := va.GetDeviceFromPort(port)
2274 if err == nil {
2275 vpv.setDevice(d.Name)
2276 p := d.GetPort(port)
2277 if p != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302278 logger.Debugw(ctx, "Checking UNI port state", log.Fields{"State": p.State})
Akash Soni024eb8e2023-04-28 16:25:09 +05302279 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
2280 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302281 }
2282 }
2283 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302284 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302285 return vpv
2286}
2287
2288// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302289func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302290 logger.Debugw(ctx, "Delete Vnet From Port", log.Fields{"Port": port, "VNET": vpv.Device})
vinokuma926cb3e2023-03-29 11:41:06 +05302291 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302292 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2293
vinokuma926cb3e2023-03-29 11:41:06 +05302294 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302295 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2296
vinokuma926cb3e2023-03-29 11:41:06 +05302297 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302298 va.DeleteMacInPortMap(vpv.MacAddr)
2299
vinokuma926cb3e2023-03-29 11:41:06 +05302300 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302301 vpvsIntf, ok := va.VnetsByPort.Load(port)
2302 if !ok {
2303 return
2304 }
2305 vpvs := vpvsIntf.([]*VoltPortVnet)
2306 for i, lvpv := range vpvs {
vinokuma04dc9f82023-07-31 15:47:49 +05302307 if reflect.DeepEqual(lvpv, vpv) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302308 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2309 "UNIVLAN": vpv.UniVlan})
2310
2311 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2312
2313 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302314 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302315
2316 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302317 vpv.DelTrapFlows(cntx)
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302318 vpv.DelHsiaFlows(cntx, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302319 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2320 vpv.PendingFlowLock.RLock()
2321 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302322 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302323 }
2324 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302325 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302326 }
2327 vpv.PendingFlowLock.RUnlock()
2328 return
2329 }
2330 }
2331}
2332
2333// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302334func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302335 logger.Info(ctx, "Restore Vnets From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302336 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302337 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302338 for _, net := range vnets {
2339 b, ok := net.Value.([]byte)
2340 if !ok {
2341 logger.Warn(ctx, "The value type is not []byte")
2342 continue
2343 }
2344 var vnet VoltVnet
2345 err := json.Unmarshal(b, &vnet)
2346 if err != nil {
2347 logger.Warn(ctx, "Unmarshal of VNET failed")
2348 continue
2349 }
2350 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302351 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302352 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2353 }
2354
2355 if vnet.DeleteInProgress {
2356 va.VnetsToDelete[vnet.Name] = true
2357 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2358 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302359 }
2360}
2361
2362// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2363// are used as the key to locate the service. If more than one service is on the
2364// same port (essentially a UNI of ONU), the services must be separated by different
2365// CVLANs
2366func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302367 logger.Debugw(ctx, "Get Service From Cvlan", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302368 // Fetch the device first to make sure the device exists
2369 dIntf, ok := va.DevicesDisc.Load(device)
2370 if !ok {
2371 return nil
2372 }
2373 d := dIntf.(*VoltDevice)
2374
2375 // If the port is NNI port, the services dont exist on it. The svc then
2376 // must be obtained from a different context and is not included here
2377 if port == d.NniPort {
2378 return nil
2379 }
2380
vinokuma926cb3e2023-03-29 11:41:06 +05302381 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302382 var service *VoltService
2383
2384 // This is an access port and the port should have all the associated
2385 // services which can be uniquely identified by the VLANs in the packet
2386 vnets, ok := va.VnetsByPort.Load(port)
2387
2388 if !ok {
2389 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2390 return nil
2391 }
2392 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2393 for _, vnet := range vnets.([]*VoltPortVnet) {
2394 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2395 switch vnet.VlanControl {
2396 case ONUCVlanOLTSVlan:
2397 service = vnet.MatchesPriority(priority)
2398 if vnet.MatchesCvlan(vlans) && service != nil {
2399 return service
2400 }
2401 case ONUCVlan,
2402 None:
2403 service = vnet.MatchesPriority(priority)
2404 // In case of DHCP Flow - cvlan == VlanNone
2405 // In case of HSIA Flow - cvlan == Svlan
2406 if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
2407 return service
2408 }
2409 case OLTCVlanOLTSVlan,
2410 OLTSVlan:
2411 service = vnet.MatchesPriority(priority)
2412 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2413 return service
2414 }
2415 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302416 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302417 }
2418 }
2419 return nil
2420}
2421
2422// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2423// are used as the key to locate the service. If more than one service is on the
2424// same port (essentially a UNI of ONU), the services must be separated by different
2425// CVLANs
2426func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2427 // Fetch the device first to make sure the device exists
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302428 logger.Debugw(ctx, "Get Vnet From Fields", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302429 dIntf, ok := va.DevicesDisc.Load(device)
2430 if !ok {
2431 return nil, nil
2432 }
2433 d := dIntf.(*VoltDevice)
2434
2435 // If the port is NNI port, the services dont exist on it. The svc then
2436 // must be obtained from a different context and is not included here
2437 if port == d.NniPort {
2438 return nil, nil
2439 }
2440
2441 //To return the matched service
2442 var service *VoltService
2443
2444 // This is an access port and the port should have all the associated
2445 // services which can be uniquely identified by the VLANs in the packet
2446 if vnets, ok := va.VnetsByPort.Load(port); ok {
2447 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2448 for _, vnet := range vnets.([]*VoltPortVnet) {
2449 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2450 switch vnet.VlanControl {
2451 case ONUCVlanOLTSVlan:
2452 service = vnet.MatchesPriority(priority)
2453 if vnet.MatchesCvlan(vlans) && service != nil {
2454 return vnet, service
2455 }
2456 case ONUCVlan,
2457 None:
2458 service = vnet.MatchesPriority(priority)
2459 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2460 return vnet, service
2461 }
2462 case OLTCVlanOLTSVlan,
2463 OLTSVlan:
2464 service = vnet.MatchesPriority(priority)
2465 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2466 return vnet, service
2467 }
2468 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302469 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302470 }
2471 }
2472 }
2473 return nil, nil
2474}
2475
2476// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2477// are used as the key to locate the service. If more than one service is on the
2478// same port (essentially a UNI of ONU), the services must be separated by different
2479// CVLANs
2480func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302481 logger.Debugw(ctx, "Get Vnet From Pkt", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05302482 vlans := GetVlans(pkt)
2483 priority := GetPriority(pkt)
2484 return va.GetVnetFromFields(device, port, vlans, priority)
2485}
2486
2487// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302488func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302489 logger.Debugw(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302490 pushflow := func(key interface{}, value interface{}) bool {
2491 device := value.(*VoltDevice)
2492 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302493 logger.Warnw(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302494 return true
2495 }
2496 if device.State != controller.DeviceStateUP {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302497 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 +05302498 return true
2499 }
2500 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302501 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 +05302502 return true
2503 }
2504
2505 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2506 vnetList := vnetListIntf.(*util.ConcurrentMap)
2507 vnetList.Set(vnet.Name, true)
2508 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2509 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()})
2510 return true
2511 }
2512 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2513 err := ProcessIcmpv6McGroup(device.Name, false)
2514 if err != nil {
2515 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2516 return true
2517 }
2518 if portID, err := va.GetPortID(device.NniPort); err == nil {
2519 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2520 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2521 return true
2522 }
2523
vinokuma926cb3e2023-03-29 11:41:06 +05302524 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302525 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302526 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302527 if err != nil {
2528 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2529 return true
2530 }
2531 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2532
2533 // Pushing ARP Flow
2534 flow = BuildDSArpFlow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302535 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302536 if err != nil {
2537 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2538 return true
2539 }
2540 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2541
2542 vnetList := util.NewConcurrentMap()
2543 vnetList.Set(vnet.Name, true)
2544 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2545 }
2546 return true
2547 }
2548 va.DevicesDisc.Range(pushflow)
2549}
2550
2551// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302552func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302553 logger.Debugw(ctx, "PushDevFlowForDevice", log.Fields{"device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302554 err := ProcessIcmpv6McGroup(device.Name, false)
2555 if err != nil {
2556 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2557 return
2558 }
2559 pushicmpv6 := func(key, value interface{}) bool {
2560 vnet := value.(*VoltVnet)
2561 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2562 vnetList := vnetListIntf.(*util.ConcurrentMap)
2563 vnetList.Set(vnet.Name, true)
2564 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2565 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()})
2566 return true
2567 }
2568 nniPortID, err := va.GetPortID(device.NniPort)
2569 if err != nil {
2570 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2571 }
2572 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2573 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2574 return true
2575 }
2576 flow := BuildICMPv6Flow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302577 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302578 if err != nil {
2579 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2580 return true
2581 }
2582 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2583
2584 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302585 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302586 if err != nil {
2587 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2588 return true
2589 }
2590 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2591
2592 vnetList := util.NewConcurrentMap()
2593 vnetList.Set(vnet.Name, true)
2594 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2595 return true
2596 }
2597 va.VnetsByName.Range(pushicmpv6)
2598}
2599
2600// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302601func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302602 logger.Debugw(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302603 delflows := func(key interface{}, value interface{}) bool {
2604 device := value.(*VoltDevice)
2605
2606 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2607 vnetList := vnetListIntf.(*util.ConcurrentMap)
2608 vnetList.Remove(vnet.Name)
2609 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2610 if vnetList.Length() != 0 {
2611 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()})
2612 return true
2613 }
2614 }
2615 if portID, err := va.GetPortID(device.NniPort); err == nil {
2616 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2617 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2618 return true
2619 }
vinokuma926cb3e2023-03-29 11:41:06 +05302620 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302621 flow := BuildICMPv6Flow(portID, vnet)
2622 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302623 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302624 if err != nil {
2625 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2626 return true
2627 }
2628 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2629
vinokuma926cb3e2023-03-29 11:41:06 +05302630 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302631 flow = BuildDSArpFlow(portID, vnet)
2632 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302633 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302634 if err != nil {
2635 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2636 return true
2637 }
2638 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2639
2640 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2641 }
2642 return true
2643 }
2644 va.DevicesDisc.Range(delflows)
2645}
2646
2647// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302648func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302649 logger.Debugw(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302650 delicmpv6 := func(key, value interface{}) bool {
2651 vnet := value.(*VoltVnet)
2652 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2653 vnetList := vnetListIntf.(*util.ConcurrentMap)
2654 vnetList.Remove(vnet.Name)
2655 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2656 if vnetList.Length() != 0 {
2657 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()})
2658 return true
2659 }
2660 } else {
2661 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2662 return true
2663 }
2664 nniPortID, err := va.GetPortID(device.NniPort)
2665 if err != nil {
2666 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2667 }
2668 flow := BuildICMPv6Flow(nniPortID, vnet)
2669 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302670 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302671 if err != nil {
2672 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2673 return true
2674 }
2675
2676 flow = BuildDSArpFlow(nniPortID, vnet)
2677 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302678 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302679 if err != nil {
2680 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2681 return true
2682 }
2683
2684 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2685 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2686 return true
2687 }
2688 va.VnetsByName.Range(delicmpv6)
2689 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2690 err := ProcessIcmpv6McGroup(device.Name, true)
2691 if err != nil {
2692 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2693 return
2694 }
2695}
2696
2697// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302698func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302699 logger.Debugw(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302700 delflows := func(key interface{}, value interface{}) bool {
2701 device := value.(*VoltDevice)
2702 if device.SerialNum != deviceSerialNum {
2703 return true
2704 }
2705 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2706 vnetList := vnetListIntf.(*util.ConcurrentMap)
2707 vnetList.Remove(vnet.Name)
2708 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2709 if vnetList.Length() != 0 {
2710 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()})
2711 return true
2712 }
2713 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2714 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2715 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2716 // The step will be as follow:
2717 // 1. Deact Service
2718 // 2. Pod Reboot
2719 // 3. Pending Delete Service triggered
2720 // 4. Del Service Ind followed by DelVnet req from NB
2721 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2722 // hence the flow will not be cleared
2723 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2724 return true
2725 }
2726 if portID, err := va.GetPortID(device.NniPort); err == nil {
2727 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2728 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2729 return false
2730 }
2731 flow := BuildICMPv6Flow(portID, vnet)
2732 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302733 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302734 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2735 }
2736 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2737
2738 flow = BuildDSArpFlow(portID, vnet)
2739 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302740 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302741 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2742 }
2743 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2744 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2745 }
2746 return false
2747 }
2748 va.DevicesDisc.Range(delflows)
2749}
2750
2751// BuildICMPv6Flow to Build DS flow for ICMPv6
2752func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302753 logger.Debugw(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302754 flow := &of.VoltFlow{}
2755 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2756 subFlow := of.NewVoltSubFlow()
2757
2758 subFlow.SetICMPv6Match()
2759 subFlow.SetMatchVlan(vnet.SVlan)
2760 subFlow.SetInPort(inport)
2761 subFlow.SetPopVlan()
2762 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2763 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2764 subFlow.Priority = of.McFlowPriority
2765 var metadata uint64
2766 if vnet.VlanControl == None {
2767 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2768 } else {
2769 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2770 }
2771 subFlow.SetTableMetadata(metadata)
2772 metadata = uint64(vnet.setPbitRemarking())
2773
2774 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2775 subFlow.SetWriteMetadata(metadata)
2776 flow.SubFlows[subFlow.Cookie] = subFlow
2777 return flow
2778}
2779
vinokuma926cb3e2023-03-29 11:41:06 +05302780// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302781func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302782 logger.Debugw(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302783
2784 flow := &of.VoltFlow{}
2785 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2786 subFlow := of.NewVoltSubFlow()
2787
2788 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2789 subFlow.SetArpMatch()
2790 subFlow.SetMatchDstMac(BcastMAC)
2791 subFlow.SetMatchVlan(vnet.SVlan)
2792 subFlow.SetInPort(inport)
2793 subFlow.SetPopVlan()
2794 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2795
2796 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2797 subFlow.Priority = of.McFlowPriority
2798
2799 var metadata uint64
2800 if vnet.VlanControl == None {
2801 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2802 } else {
2803 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2804 }
2805 subFlow.SetTableMetadata(metadata)
2806 metadata = uint64(vnet.setPbitRemarking())
2807 subFlow.SetWriteMetadata(metadata)
2808
2809 flow.SubFlows[subFlow.Cookie] = subFlow
2810 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2811 return flow
2812}
2813
2814// setPbitRemarking to set Pbit remarking
2815func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302816 // Remarkable
2817 // Remarked Pbit Pbit
2818 // |-----------------------------| |------|
2819 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2820 // 000 000 000 000 000 000 000 000 00000000
2821
2822 // Eg:
2823 // For 6:3 & 7:1
2824 // 001 011 000 000 000 000 000 000 11000000
2825
2826 var remarkable uint8
2827 var remarked uint32
2828 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2829 remarkable = remarkable | 1<<refPbit
2830 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2831 }
2832 return remarked<<8 | uint32(remarkable)
2833}
2834
2835// ProcessIcmpv6McGroup to add icmpv6 multicast group
2836func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302837 logger.Info(ctx, "Creating ICMPv6 MC Group")
2838 va := GetApplication()
2839 vd := va.GetDevice(device)
2840 group := &of.Group{}
2841 group.GroupID = ICMPv6ArpGroupID
2842 group.Device = device
2843 if delete {
2844 if !vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302845 logger.Debug(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
Naveen Sampath04696f72022-06-13 15:19:14 +05302846 return nil //TODO
2847 }
2848 vd.icmpv6GroupAdded = false
2849 group.Command = of.GroupCommandDel
2850 group.ForceAction = true
2851 } else {
2852 if vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302853 logger.Debug(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
Naveen Sampath04696f72022-06-13 15:19:14 +05302854 return nil //TODO
2855 }
2856 vd.icmpv6GroupAdded = true
2857 group.Command = of.GroupCommandAdd
2858 receivers := GetApplication().GetIcmpv6Receivers(device)
2859 group.Buckets = append(group.Buckets, receivers...)
2860 }
2861 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2862 port, _ := GetApplication().GetNniPort(device)
2863 err := cntlr.GetController().GroupUpdate(port, device, group)
2864 return err
2865}
2866
vinokuma926cb3e2023-03-29 11:41:06 +05302867// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302868func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302869 logger.Debugw(ctx, "Is Vlan Matching", log.Fields{"cvlan": cvlan, "svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302870 switch vpv.VlanControl {
2871 case ONUCVlanOLTSVlan,
2872 OLTCVlanOLTSVlan:
2873 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2874 return true
2875 }
2876 case ONUCVlan,
2877 OLTSVlan,
2878 None:
2879 if vpv.SVlan == svlan {
2880 return true
2881 }
2882 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302883 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302884 }
2885 return false
2886}
2887
vinokuma926cb3e2023-03-29 11:41:06 +05302888// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302889func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302890 logger.Debugw(ctx, "Push Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302891 for cookie := range flow.SubFlows {
2892 cookie := strconv.FormatUint(cookie, 10)
2893 fe := &FlowEvent{
2894 eType: EventTypeControlFlowAdded,
2895 cookie: cookie,
2896 eventData: vpv,
2897 }
2898 device.RegisterFlowAddEvent(cookie, fe)
2899 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302900 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302901}
2902
vinokuma926cb3e2023-03-29 11:41:06 +05302903// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302904func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302905 logger.Debugw(ctx, "Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05302906 sendFlowFailureInd := func(key, value interface{}) bool {
2907 //svc := value.(*VoltService)
2908 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2909 return true
2910 }
2911 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2912 vpv.services.Range(sendFlowFailureInd)
2913}
2914
vinokuma926cb3e2023-03-29 11:41:06 +05302915// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302916func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302917 logger.Debugw(ctx, "Remove Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302918 vpv.PendingFlowLock.Lock()
2919 defer vpv.PendingFlowLock.Unlock()
2920
2921 for cookie := range flow.SubFlows {
2922 cookie := strconv.FormatUint(cookie, 10)
2923 fe := &FlowEvent{
2924 eType: EventTypeControlFlowRemoved,
2925 device: device.Name,
2926 cookie: cookie,
2927 eventData: vpv,
2928 }
2929 device.RegisterFlowDelEvent(cookie, fe)
2930 vpv.PendingDeleteFlow[cookie] = true
2931 }
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302932 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05302933}
2934
vinokuma926cb3e2023-03-29 11:41:06 +05302935// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302936func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302937 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 +05302938 vpv.PendingFlowLock.RLock()
2939 defer vpv.PendingFlowLock.RUnlock()
2940 if !vpv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302941 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 +05302942 return
2943 }
2944 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302945 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 +05302946 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302947 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2948 }
2949}
2950
vinokuma926cb3e2023-03-29 11:41:06 +05302951// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302952func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302953 vpv.PendingFlowLock.Lock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302954 logger.Debugw(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302955
2956 delete(vpv.PendingDeleteFlow, cookie)
2957 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302958 vpv.CheckAndDeleteVpv(cntx)
2959 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302960}
2961
vinokuma926cb3e2023-03-29 11:41:06 +05302962// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302963func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302964 vpv.PendingFlowLock.Lock()
2965
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302966 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 +05302967
2968 sendFlowFailureInd := func(key, value interface{}) bool {
2969 svc := value.(*VoltService)
2970 svc.triggerServiceFailureInd(errorCode, errReason)
2971 return true
2972 }
2973 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2974 vpv.services.Range(sendFlowFailureInd)
2975
2976 if vpv.DeleteInProgress {
2977 delete(vpv.PendingDeleteFlow, cookie)
2978 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302979 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302980 } else {
2981 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302982 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302983 }
2984}
2985
vinokuma926cb3e2023-03-29 11:41:06 +05302986// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302987func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302988 logger.Debugw(ctx, "Remove Flows", log.Fields{"PortName": flow.PortName, "DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302989 vv.VnetLock.Lock()
2990 defer vv.VnetLock.Unlock()
2991
2992 var flowMap map[string]bool
2993 var ok bool
2994
2995 for cookie := range flow.SubFlows {
2996 cookie := strconv.FormatUint(cookie, 10)
2997 fe := &FlowEvent{
2998 eType: EventTypeDeviceFlowRemoved,
2999 device: device.Name,
3000 cookie: cookie,
3001 eventData: vv,
3002 }
3003 device.RegisterFlowDelEvent(cookie, fe)
3004 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
3005 flowMap = make(map[string]bool)
3006 }
3007 flowMap[cookie] = true
3008 vv.PendingDeleteFlow[device.Name] = flowMap
3009 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303010 vv.WriteToDb(cntx)
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05303011 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05303012}
3013
vinokuma926cb3e2023-03-29 11:41:06 +05303014// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303015func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303016 logger.Debugw(ctx, "Check And Delete Vnet", log.Fields{"Device": device, "Vnet": vv.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05303017 if !vv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303018 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 +05303019 return
3020 }
3021 vv.VnetPortLock.RLock()
3022 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
3023 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
3024 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303025 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05303026 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
3027 } else {
3028 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
3029 }
3030 vv.VnetPortLock.RUnlock()
3031}
3032
vinokuma926cb3e2023-03-29 11:41:06 +05303033// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303034func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303035 vv.VnetLock.Lock()
3036 defer vv.VnetLock.Unlock()
3037
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303038 logger.Debugw(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303039
3040 if _, ok := vv.PendingDeleteFlow[device]; ok {
3041 delete(vv.PendingDeleteFlow[device], cookie)
3042 }
3043
3044 //Check and update success for pending disable request
3045 if d := GetApplication().GetDevice(device); d != nil {
3046 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
3047 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303048 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303049 }
3050 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303051 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05303052}
3053
vinokuma926cb3e2023-03-29 11:41:06 +05303054// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303055func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303056 vv.VnetLock.Lock()
3057 defer vv.VnetLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303058 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 +05303059
3060 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3061 if _, ok := flowMap[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303062 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 +05303063
3064 if vv.DeleteInProgress {
3065 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303066 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303067 }
3068 return
3069 }
3070 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303071 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 +05303072}
3073
vinokuma926cb3e2023-03-29 11:41:06 +05303074// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303075func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303076 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3077 // When multiple Igmp-suported service enabled, comment "return false"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303078 logger.Debugw(ctx, "Igmp Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303079
3080 sendFlowFailureInd := func(key, value interface{}) bool {
3081 svc := value.(*VoltService)
3082 if svc.IgmpEnabled {
3083 svc.triggerServiceFailureInd(errorCode, errReason)
3084 return false
3085 }
3086 return true
3087 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303088 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 +05303089 vpv.services.Range(sendFlowFailureInd)
3090}
3091
3092// GetMatchingMcastService to get matching multicast service
3093func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303094 logger.Debugw(ctx, "Get Matching Mcast Service", log.Fields{"Port": port, "Device": device, "Cvlan": cvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05303095 var service *VoltService
3096 dIntf, ok := va.DevicesDisc.Load(device)
3097 if !ok {
3098 return nil
3099 }
3100 d := dIntf.(*VoltDevice)
3101
3102 // If the port is NNI port, the services dont exist on it. The svc then
3103 // must be obtained from a different context and is not included here
3104 if port == d.NniPort {
3105 return nil
3106 }
3107
3108 // This is an access port and the port should have all the associated
3109 // services which can be uniquely identified by the VLANs in the packet
3110 vnets, ok := va.VnetsByPort.Load(port)
3111
3112 if !ok {
3113 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3114 return nil
3115 }
3116 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3117 getMcastService := func(key, value interface{}) bool {
3118 srv := value.(*VoltService)
3119 if srv.IgmpEnabled {
3120 service = srv
3121
3122 //TODO: Current implementation supports only for single service with Igmp Enabled
3123 //FIX-ME: When multiple service suports Igmp, update of logic required
3124 return false
3125 }
3126 return true
3127 }
3128
3129 for _, vpv := range vnets.([]*VoltPortVnet) {
3130 if vpv.CVlan == cvlan {
3131 vpv.services.Range(getMcastService)
3132 if service != nil {
3133 break
3134 }
3135 }
3136 }
3137 return service
3138}
3139
vinokuma926cb3e2023-03-29 11:41:06 +05303140// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303141func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303142 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303143 vv.VnetLock.Lock()
3144 cookieList := []uint64{}
3145 flowMap := vv.PendingDeleteFlow[device]
3146
3147 for cookie := range flowMap {
3148 cookieList = append(cookieList, convertToUInt64(cookie))
3149 }
3150 vv.VnetLock.Unlock()
3151
3152 if len(cookieList) == 0 {
3153 return false
3154 }
3155
3156 for _, cookie := range cookieList {
3157 if vd := GetApplication().GetDevice(device); vd != nil {
3158 flow := &of.VoltFlow{}
3159 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3160 subFlow := of.NewVoltSubFlow()
3161 subFlow.Cookie = cookie
3162 flow.SubFlows[cookie] = subFlow
3163 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303164 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303165 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3166 }
3167 }
3168 }
3169 return true
3170}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303171
vinokuma926cb3e2023-03-29 11:41:06 +05303172// JSONMarshal wrapper function for json Marshal VoltVnet
3173func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303174 return json.Marshal(VoltVnet{
3175 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303176 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303177 VnetOper: VnetOper{
3178 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3179 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3180 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3181 },
3182 })
3183}
3184
vinokuma926cb3e2023-03-29 11:41:06 +05303185// JSONMarshal wrapper function for json Marshal VoltPortVnet
3186func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303187 return json.Marshal(VoltPortVnet{
3188 Device: vpv.Device,
3189 Port: vpv.Port,
3190 PonPort: vpv.PonPort,
3191 VnetName: vpv.VnetName,
3192 SVlan: vpv.SVlan,
3193 CVlan: vpv.CVlan,
3194 UniVlan: vpv.UniVlan,
3195 SVlanTpid: vpv.SVlanTpid,
3196 DhcpRelay: vpv.DhcpRelay,
3197 ArpRelay: vpv.ArpRelay,
3198 PppoeIa: vpv.PppoeIa,
3199 MacLearning: vpv.MacLearning,
3200 DhcpStatus: vpv.DhcpStatus,
3201 DhcpExpiryTime: vpv.DhcpExpiryTime,
3202 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3203 FlowsApplied: vpv.FlowsApplied,
3204 Ipv4Addr: vpv.Ipv4Addr,
3205 Ipv6Addr: vpv.Ipv6Addr,
3206 MacAddr: vpv.MacAddr,
3207 LearntMacAddr: vpv.LearntMacAddr,
3208 CircuitID: vpv.CircuitID,
3209 RemoteID: vpv.RemoteID,
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05303210 IsOption82Enabled: vpv.IsOption82Enabled,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303211 RelayState: vpv.RelayState,
3212 PPPoeState: vpv.PPPoeState,
3213 RelayStatev6: vpv.RelayStatev6,
3214 IgmpEnabled: vpv.IgmpEnabled,
3215 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3216 McastService: vpv.McastService,
3217 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3218 VlanControl: vpv.VlanControl,
3219 MvlanProfileName: vpv.MvlanProfileName,
3220 Version: vpv.Version,
3221 McastTechProfileID: vpv.McastTechProfileID,
3222 McastPbit: vpv.McastPbit,
3223 McastUsMeterID: vpv.McastUsMeterID,
3224 AllowTransparent: vpv.AllowTransparent,
3225 SchedID: vpv.SchedID,
3226 DHCPv6DUID: vpv.DHCPv6DUID,
3227 PendingDeleteFlow: vpv.PendingDeleteFlow,
3228 DeleteInProgress: vpv.DeleteInProgress,
3229 Blocked: vpv.Blocked,
3230 DhcpPbit: vpv.DhcpPbit,
3231 })
3232}
Tinoj Josephec742f62022-09-29 19:11:10 +05303233
3234func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303235 logger.Debugw(ctx, "Is Service Activated", log.Fields{"Name": vpv.Port})
Tinoj Josephec742f62022-09-29 19:11:10 +05303236 isActivated := false
3237 vpv.services.Range(func(key, value interface{}) bool {
3238 svc := value.(*VoltService)
3239 if svc.IsActivated {
3240 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3241 isActivated = true
3242 return false //to exit loop
3243 }
3244 return true
3245 })
3246 return isActivated
3247}