blob: df89c6815e9701b57bcda409b119e9969988ace9 [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
677func (vpv *VoltPortVnet) RangeOnServices(cntx context.Context, callback func(cntx context.Context, key, value interface{}) bool) {
678 vpv.services.Range(func(key, value interface{}) bool {
679 return callback(cntx, key, value)
680 })
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
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530692 vpv.RangeOnServices(cntx, vpv.updateIPv4AndProvisionFlows)
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
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530720 vpv.RangeOnServices(cntx, vpv.updateIPv6AndProvisionFlows)
721 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530722}
723
724// AddSvcUsMeterToDevice to add service upstream meter info to device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530725func AddSvcUsMeterToDevice(cntx context.Context, key, value interface{}) 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 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530797 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530798 }
vinokuma926cb3e2023-03-29 11:41:06 +0530799 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530800 vpv.RangeOnServices(cntx, AddMeterToDevice)
801 }
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 {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530807 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
808 }
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 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530813 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
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 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530824 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
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 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530828 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
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})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530835 vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice)
836 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 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530842 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
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
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530852func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool) {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530853 if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
854 logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
855 return
856 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530857 logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
858 log.Fields{"service count": vpv.servicesCount.Load()})
859
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530860 //vpv.RangeOnServices(cntx, DelAllFlows)
861 vpv.DelTrapFlows(cntx)
862 vpv.DelHsiaFlows(cntx)
863 vpv.WriteToDb(cntx)
864 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530865}
866
867// SetMacAddr : The MAC address is set when a MAC address is learnt through the
868// packets received from the network. Currently, DHCP packets are
869// only packets we learn the MAC address from
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530870func (vpv *VoltPortVnet) SetMacAddr(cntx context.Context, addr net.HardwareAddr) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530871 logger.Infow(ctx, "Set Mac Addr", log.Fields{"MAC addr": addr.String(), "Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530872 //Store Learnt MAC address and return if MACLearning is not enabled
873 vpv.LearntMacAddr = addr
874 if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
875 (NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
876 return
877 }
878
879 // Compare the two MAC addresses to see if it is same
880 // If they are same, we just return. If not, we perform
881 // actions to address the change in MAC address
882 //if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
883 if !util.MacAddrsMatch(vpv.MacAddr, addr) {
884 expectedPort := GetApplication().GetMacInPortMap(addr)
885 if expectedPort != "" && expectedPort != vpv.Port {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530886 logger.Warnw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
Naveen Sampath04696f72022-06-13 15:19:14 +0530887 log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
888 return
889 }
890 if NonZeroMacAddress(vpv.MacAddr) {
891 logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
892
893 // The newly learnt MAC address is different than earlier one.
894 // The existing MAC based HSIA flows need to be undone as the device
895 // may have been changed
896 // Atleast one HSIA flow should be present in adapter to retain the TP and GEM
897 // hence delete one after the other
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530898 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530899 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530900 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
901 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
902 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530903 GetApplication().DeleteMacInPortMap(vpv.MacAddr)
904 } else {
905 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530906 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
Naveen Sampath04696f72022-06-13 15:19:14 +0530907 logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
908 }
909 GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
910 } else {
911 logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
912 }
913
914 _, err := GetApplication().GetDeviceFromPort(vpv.Port)
915 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530916 logger.Errorw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
Akash Sonia8246972023-01-03 10:37:08 +0530917 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530918 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
919 return
920 }
921 // Ds Hsia flows has to be pushed
922 if vpv.FlowsApplied {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530923 // In case of DPU_MGMT_TRAFFIC install both US and DS Flows
vinokuma926cb3e2023-03-29 11:41:06 +0530924 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530925 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
926 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530927 // no HSIA flows for multicast service
928 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530929 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530930 }
931 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530932 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530933}
934
935// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
936func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530937 logger.Debugw(ctx, "Matches Vlans", log.Fields{"Svlan": svlan, "Cvlan": cvlan, "Univlan": univlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530938 if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
939 return false
940 }
941 return true
942}
943
944// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
945func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530946 logger.Debugw(ctx, "Matches Cvlans", log.Fields{"Cvlan": cvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530947 if len(cvlan) != 1 && !vpv.AllowTransparent {
948 return false
949 }
950 if vpv.CVlan != cvlan[0] {
951 return false
952 }
953 return true
954}
955
956// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
957func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530958 logger.Debugw(ctx, "Matches Priority", log.Fields{"Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +0530959 var service *VoltService
960 pbitFound := false
961 matchpbitsFunc := func(key, value interface{}) bool {
962 svc := value.(*VoltService)
963 for _, pbit := range svc.Pbits {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530964 if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530965 logger.Infow(ctx, "Pbit match found with service",
966 log.Fields{"Pbit": priority, "serviceName": svc.Name})
967 pbitFound = true
968 service = svc
969 return false //Returning false to stop the Range loop
970 }
971 }
972 return true
973 }
974 _ = pbitFound
975 vpv.services.Range(matchpbitsFunc)
976 return service
977}
978
979// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
980func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530981 logger.Debugw(ctx, "Get Remarked Priority", log.Fields{"Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +0530982 dsPbit := uint8(0)
983 matchpbitsFunc := func(key, value interface{}) bool {
984 svc := value.(*VoltService)
985 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530986 logger.Warnw(ctx, "Pbit match found with service",
Naveen Sampath04696f72022-06-13 15:19:14 +0530987 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
988 dsPbit = uint8(remarkPbit)
989 return false //Returning false to stop the Range loop
990 }
991 // When no remarking info is available, remark the incoming pbit
992 // to highest pbit configured for the subscriber (across all subservices associated)
993 svcPbit := uint8(svc.Pbits[0])
994 if svcPbit > dsPbit {
995 dsPbit = svcPbit
996 }
997 return true
998 }
999 vpv.services.Range(matchpbitsFunc)
1000 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
1001 return dsPbit
1002}
1003
1004// AddSvc adds a service on the VNET on a port. The addition is
1005// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301006func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301007 logger.Infow(ctx, "Add Service to VPV", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301008 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301009 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +05301010 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
1011
1012 // Learn the circuit-id and remote-id from the service
1013 // TODO: There must be a better way of doing this. This
1014 // may be explored
1015 if svc.IgmpEnabled {
1016 vpv.IgmpEnabled = true
1017 }
1018 // first time service activation MacLearning will have default value as None.
1019 // to handle reciliency if anythng other then None we should retain it .
1020 if svc.MacLearning == MacLearningNone {
1021 if !vpv.DhcpRelay && !vpv.ArpRelay {
1022 svc.MacLearning = MacLearningNone
1023 } else if vpv.MacLearning == Learn {
1024 svc.MacLearning = Learn
1025 } else if vpv.MacLearning == ReLearn {
1026 svc.MacLearning = ReLearn
1027 }
1028 }
1029
vinokuma926cb3e2023-03-29 11:41:06 +05301030 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301031 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1032 svc.MacAddr = vpv.MacAddr
1033 } else if vpv.servicesCount.Load() == 1 {
1034 vpv.MacAddr = svc.MacAddr
1035 }
1036
1037 vpv.MacLearning = svc.MacLearning
1038 vpv.PonPort = svc.PonPort
1039 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301040 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301041 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301042 if svc.McastService {
1043 vpv.McastService = true
1044 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301045 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301046 vpv.McastPbit = svc.Pbits[0]
1047 vpv.McastUsMeterID = svc.UsMeterID
1048 vpv.SchedID = svc.SchedID
1049 }
1050 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1051 svc.AllowTransparent = vpv.AllowTransparent
1052 svc.SVlanTpid = vpv.SVlanTpid
1053
vinokuma926cb3e2023-03-29 11:41:06 +05301054 // Ensure configuring the mvlan profile only once
1055 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301056 if svc.MvlanProfileName != "" {
1057 if vpv.MvlanProfileName == "" {
1058 vpv.MvlanProfileName = svc.MvlanProfileName
1059 } else {
1060 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1061 }
1062 }
1063
Akash Sonia8246972023-01-03 10:37:08 +05301064 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301065 if err != nil {
1066 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301067 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1068 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301069 return
1070 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301071 if !svc.IsActivated {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301072 logger.Warnw(ctx, "Not pushing Service Flows: Service Not activated", log.Fields{"ServiceName": svc.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05301073 return
1074 }
Akash Sonia8246972023-01-03 10:37:08 +05301075
vinokuma926cb3e2023-03-29 11:41:06 +05301076 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301077 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1078
Akash Soni53da2852023-03-15 00:31:31 +05301079 if devConfig.UplinkPort != voltDevice.NniPort {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301080 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 +05301081 return
1082 }
vinokuma926cb3e2023-03-29 11:41:06 +05301083 // Push Service Flows if DHCP relay is not configured
1084 // or already DHCP flows are configured for the VPV
1085 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301086 if vpv.FlowsApplied {
1087 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301088 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301089 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301090 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301091 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1092 }
1093 }
1094 }
1095
vinokuma926cb3e2023-03-29 11:41:06 +05301096 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301097 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1098 // service with Igmp Enabled needs to be installed
1099 if svc.IgmpEnabled && vpv.FlowsApplied {
1100 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301101 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301102 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301103 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1104 }
1105
1106 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301107 // For McastService, send Service Activated indication once IGMP US flow is pushed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301108 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +05301109 }
1110 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301111 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301112}
1113
1114// setLearntMAC to set learnt mac
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301115func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301116 svc := value.(*VoltService)
1117 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301118 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301119 return true
1120}
1121
1122// PostAccessConfigSuccessInd for posting access config success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301123func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301124 return true
1125}
1126
1127// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301128func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301129 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301130 logger.Debugw(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301131 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301132 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301133
1134 return true
1135}
1136
1137// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301138func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301139 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301140 logger.Debugw(ctx, "Updating Ipv6 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301141 svc.SetIpv6Addr(vpv.Ipv6Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301142 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301143
1144 return true
1145}
1146
1147// AddUsHsiaFlows to add upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301148func AddUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301149 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301150 logger.Debugw(ctx, "Add US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301151 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301152 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1153 }
1154 return true
1155}
1156
1157// AddDsHsiaFlows to add downstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301158func AddDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301159 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301160 logger.Debugw(ctx, "Add DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301161 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301162 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1163 }
1164 return true
1165}
1166
1167// ClearFlagsInService to clear the flags used in service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301168func ClearFlagsInService(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301169 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301170 logger.Debugw(ctx, "Received Cleared Flow Flags for service", log.Fields{"name": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301171 svc.ServiceLock.Lock()
1172 svc.IgmpFlowsApplied = false
1173 svc.DsDhcpFlowsApplied = false
1174 svc.DsHSIAFlowsApplied = false
1175 svc.Icmpv6FlowsApplied = false
1176 svc.UsHSIAFlowsApplied = false
1177 svc.UsDhcpFlowsApplied = false
1178 svc.PendingFlows = make(map[string]bool)
1179 svc.AssociatedFlows = make(map[string]bool)
1180 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301181 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301182 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1183 return true
1184}
1185
1186// DelDsHsiaFlows to delete hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301187func DelDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301188 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301189 logger.Debugw(ctx, "Delete DS Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301190 if err := svc.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301191 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1192 }
1193 return true
1194}
1195
1196// DelUsHsiaFlows to delete upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301197func DelUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301198 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301199 logger.Debugw(ctx, "Delete US Hsia Flows", log.Fields{"ServiceName": svc.Name})
Akash Sonia8246972023-01-03 10:37:08 +05301200 if err := svc.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301201 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1202 }
1203 return true
1204}
1205
1206// ClearServiceCounters to clear the service counters
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301207func ClearServiceCounters(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301208 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301209 logger.Debugw(ctx, "Received Clear Service Counters", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301210 //Delete the per service counter too
1211 GetApplication().ServiceCounters.Delete(svc.Name)
1212 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301213 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301214 }
1215 return true
1216}
1217
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301218// AddMeterToDevice to add meter config to device, used in FTTB case
1219func AddMeterToDevice(cntx context.Context, key, value interface{}) bool {
1220 svc := value.(*VoltService)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301221 logger.Debugw(ctx, "Received Add Meter To Device", log.Fields{"ServiceName": svc.Name})
Akash Soni53da2852023-03-15 00:31:31 +05301222 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301223 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1224 }
1225 return true
1226}
1227
vinokuma926cb3e2023-03-29 11:41:06 +05301228// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301229func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301230 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 +05301231 if !vpv.FlowsApplied || vgcRebooted {
1232 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301233 if err := vpv.AddUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301234 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1236 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301237 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301238 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301239 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1240 }
1241 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1242 log.Fields{"port": vpv.Port})
1243 //vpv.updateICMPv6McGroup(true)
1244 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301245 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301246 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301247 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1248 }
1249 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301250 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301251 if err := vpv.AddUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301252 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301253 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1254 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301255 if err := vpv.AddDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301256 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301257 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1258 }
1259 }
1260 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301261 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301262 }
1263}
1264
vinokuma926cb3e2023-03-29 11:41:06 +05301265// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301266func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301267 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 +05301268 // Delete HSIA & DHCP flows before deleting IGMP flows
1269 if vpv.FlowsApplied || vgcRebooted {
1270 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301271 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301272 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1273 "UniVlan": vpv.UniVlan, "Error": err})
1274 }
1275 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1276 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301277 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301278 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301279 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1280 }
1281 //vpv.updateICMPv6McGroup(false)
1282 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301283 if err := vpv.DelUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301284 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301285 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1286 }
1287 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301288 if err := vpv.DelUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301289 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301290 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1291 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301292 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301293 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301294 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1295 }
1296 }
1297 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301298 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301299 }
Akash Sonia8246972023-01-03 10:37:08 +05301300 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301301 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1302 "UniVlan": vpv.UniVlan, "Error": err})
1303 }
1304}
1305
1306// DelHsiaFlows deletes the service flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301307func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301308 logger.Infow(ctx, "Received Delete Hsia Flows", log.Fields{"McastService": vpv.McastService})
Naveen Sampath04696f72022-06-13 15:19:14 +05301309 // no HSIA flows for multicast service
1310 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301311 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
1312 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301313 }
1314}
1315
vinokuma926cb3e2023-03-29 11:41:06 +05301316// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301317func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301318 //send flows deleted indication to submgr
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301319 vpv.RangeOnServices(cntx, ClearServiceCounters)
Naveen Sampath04696f72022-06-13 15:19:14 +05301320}
1321
1322// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301323func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301324 var vd *VoltDevice
1325 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301326 logger.Debugw(ctx, "Received Add US DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301327
1328 if vd = GetApplication().GetDevice(device); vd != nil {
1329 if vd.State != controller.DeviceStateUP {
1330 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})
1331 return nil
1332 }
1333 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301334 err := errorCodes.ErrDeviceNotFound
1335 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 +05301336 }
1337
1338 flows, err := vpv.BuildUsDhcpFlows()
1339 if err == nil {
1340 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301341 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301342 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301343 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301344 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1345 }
1346 } else {
1347 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301348 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301349 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301350 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301351 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301352 return nil
1353}
1354
1355// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301356func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301357 var vd *VoltDevice
1358 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301359 logger.Debugw(ctx, "Received Add DS DHCP Flows", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301360
1361 if vd = GetApplication().GetDevice(device); vd != nil {
1362 if vd.State != controller.DeviceStateUP {
1363 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})
1364 return nil
1365 }
1366 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301367 err := errorCodes.ErrDeviceNotFound
1368 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 +05301369 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301370 if vd.GlobalDhcpFlowAdded {
1371 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301372 return nil
1373 }
1374
1375 flows, err := vpv.BuildDsDhcpFlows()
1376 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301377 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301378 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301379 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301380 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301381 }
1382 } else {
1383 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301384 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301385 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301386 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301387 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301388 if GetApplication().GetVendorID() != Radisys {
1389 vd.GlobalDhcpFlowAdded = true
1390 }
1391 return nil
1392}
1393
1394// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301395func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301396 logger.Info(ctx, "Received Delete DHCP Flows")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301397 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301398 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301399 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1400 }
1401
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301402 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301403 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301404 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1405 }
1406}
1407
1408// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1409// Write the status of the VPV to the DB once the delete is scheduled
1410// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301411func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301412 logger.Debugw(ctx, "Received Delete US DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301413 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1414 if err != nil {
1415 return err
1416 }
1417
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301418 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301419 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301420 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301421 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1422 }
Akash Sonia8246972023-01-03 10:37:08 +05301423
Naveen Sampath04696f72022-06-13 15:19:14 +05301424 return nil
1425}
1426
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301427func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301428 logger.Debugw(ctx, "Received US Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301429 flows, err := vpv.BuildUsDhcpFlows()
1430 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301431 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301432 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301433 return fmt.Errorf("US DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301434}
Naveen Sampath04696f72022-06-13 15:19:14 +05301435
1436// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1437// Write the status of the VPV to the DB once the delete is scheduled
1438// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301439func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301440 logger.Debugw(ctx, "Received Delete DS DHCP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301441 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1442 if err != nil {
1443 return err
1444 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301445 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301446 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301447 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301448 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1449 }
1450 /*
Akash Sonia8246972023-01-03 10:37:08 +05301451 err = vpv.delDsDhcp6Flows(device)
1452 if err != nil {
1453 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1454 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1455 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301456 return nil
1457}
1458
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301459func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301460 logger.Debugw(ctx, "Received DS Delete DHCP4 Flows", log.Fields{"DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301461 flows, err := vpv.BuildDsDhcpFlows()
1462 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301463 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301464 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301465 return fmt.Errorf("DS DHCP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301466}
1467
1468/*
1469func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1470 flows, err := vpv.BuildDsDhcp6Flows()
1471 if err == nil {
1472 return vpv.RemoveFlows(device, flows)
1473 }
1474 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1475 return err
1476}*/
1477
1478// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301479func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301480 var vd *VoltDevice
1481 device := vpv.Device
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301482 logger.Debugw(ctx, "Received Add US Arp Flows", log.Fields{"DeviceName": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301483 if vd = GetApplication().GetDevice(device); vd != nil {
1484 if vd.State != controller.DeviceStateUP {
1485 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})
1486 return nil
1487 }
1488 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301489 err := errorCodes.ErrDeviceNotFound
1490 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 +05301491 }
1492
1493 flows, err := vpv.BuildUsArpFlows()
1494 if err == nil {
1495 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301496 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301497 return fmt.Errorf("Pushing US ARP Flow Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301498 }
1499 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301500 return fmt.Errorf("US ARP Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301501 }
1502 return nil
1503}
1504
1505// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1506// Write the status of the VPV to the DB once the delete is scheduled
1507// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301508func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301509 logger.Debugw(ctx, "Delete US ARP Flows", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301510 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1511 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301512 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301513 }
1514 flows, err := vpv.BuildUsArpFlows()
1515 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301516 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301517 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301518 return fmt.Errorf("US ARP Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301519}
1520
1521// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301522func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301523 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1524
1525 var vd *VoltDevice
1526 device := vpv.Device
1527
1528 if vd = GetApplication().GetDevice(device); vd != nil {
1529 if vd.State != controller.DeviceStateUP {
1530 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})
1531 return nil
1532 }
1533 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301534 err := errorCodes.ErrDeviceNotFound
1535 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 +05301536 }
1537
1538 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1539 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1540
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301541 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301542 return fmt.Errorf("Pushing US PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301543 }
1544 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301545 return fmt.Errorf("US PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301546 }
1547 return nil
1548}
1549
1550// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301551func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301552 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1553 var vd *VoltDevice
1554 device := vpv.Device
1555
1556 if vd = GetApplication().GetDevice(device); vd != nil {
1557 if vd.State != controller.DeviceStateUP {
1558 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})
1559 return nil
1560 }
1561 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301562 err := errorCodes.ErrDeviceNotFound
1563 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 +05301564 }
1565
1566 flows, err := vpv.BuildDsPppoeFlows()
1567 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301568 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301569 return fmt.Errorf("Pushing DS PPPoE Flows Failed : %w", err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301570 }
1571 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301572 return fmt.Errorf("DS PPPoE Flow Add Failed : Device %s : %w", device, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301573 }
1574 return nil
1575}
1576
1577// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1578// Write the status of the VPV to the DB once the delete is scheduled
1579// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301580func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301581 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1582 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1583 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301584 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301585 }
1586 flows, err := vpv.BuildUsPppoeFlows()
1587 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301588 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301589 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301590 return fmt.Errorf("US PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301591}
1592
1593// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1594// Write the status of the VPV to the DB once the delete is scheduled
1595// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301596func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301597 logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1598 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1599 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301600 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301601 }
1602 flows, err := vpv.BuildDsPppoeFlows()
1603 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301604 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301605 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301606 return fmt.Errorf("DS PPPoE Flow Delete Failed : DeviceName %s : %w", device.Name, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301607}
1608
1609// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301610func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301611 logger.Debugw(ctx, "Received Add Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301612 if !vpv.IgmpFlowsApplied || vgcRebooted {
1613 if vpv.MvlanProfileName == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301614 logger.Warn(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
Naveen Sampath04696f72022-06-13 15:19:14 +05301615 return nil
1616 }
1617 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1618 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301619 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301620 } else if device.State != controller.DeviceStateUP {
1621 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})
1622 return nil
1623 }
1624 flows, err := vpv.BuildIgmpFlows()
1625 if err == nil {
1626 for cookie := range flows.SubFlows {
1627 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1628 cookie := strconv.FormatUint(cookie, 10)
1629 fe := &FlowEvent{
1630 eType: EventTypeUsIgmpFlowAdded,
1631 cookie: cookie,
1632 eventData: vpv,
1633 }
1634 vd.RegisterFlowAddEvent(cookie, fe)
1635 }
1636 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301637 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301638 return err1
1639 }
1640 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301641 return fmt.Errorf("IGMP Flow Add Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301642 }
1643 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301644 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301645 }
1646 return nil
1647}
1648
1649// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1650// Write the status of the VPV to the DB once the delete is scheduled
1651// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301652func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301653 logger.Debugw(ctx, "Received Delete Igmp Flows", log.Fields{"IgmpFlowsApplied": vpv.IgmpFlowsApplied, "VgcRebooted": vgcRebooted})
Naveen Sampath04696f72022-06-13 15:19:14 +05301654 if vpv.IgmpFlowsApplied || vgcRebooted {
1655 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1656 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301657 return fmt.Errorf("Error getting device from port : Port %s : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301658 }
1659 flows, err := vpv.BuildIgmpFlows()
1660 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301661 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301662 return err1
1663 }
1664 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301665 return fmt.Errorf("IGMP Flow Delete Failed : %w", err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301666 }
1667 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301668 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301669 }
1670 return nil
1671}
1672
1673// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1674// The flows included by this function cover US only as the DS is
1675// created either automatically by the VOLTHA or at the device level
1676// earlier
1677func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301678 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301679 flow := &of.VoltFlow{}
1680 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1681
Naveen Sampath04696f72022-06-13 15:19:14 +05301682 subFlow := of.NewVoltSubFlow()
1683 subFlow.SetTableID(0)
1684
vinokuma926cb3e2023-03-29 11:41:06 +05301685 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301686 subFlow.SetMatchVlan(vpv.CVlan)
1687 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1688 subFlow.SetPcp(vpv.UsPonSTagPriority)
1689 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301690 } else {
1691 subFlow.SetMatchVlan(vpv.UniVlan)
1692 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301693 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301694 }
1695 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301696 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301697 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301698 uniport, err := GetApplication().GetPortID(vpv.Port)
1699 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301700 return nil, fmt.Errorf("failed to fetch uni port %s from vpv : %w", vpv.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301701 }
1702 subFlow.SetInPort(uniport)
1703 // PortName and PortID to be used for validation of port before flow pushing
1704 flow.PortID = uniport
1705 flow.PortName = vpv.Port
1706 subFlow.SetReportToController()
1707
1708 // Set techprofile, meterid of first service
1709 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301710 vs := value.(*VoltService)
1711 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301712 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301713 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301714 } else {
1715 writemetadata = uint64(vs.TechProfileID) << 32
1716 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301717 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301718 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301719 return false
1720 })
1721
Naveen Sampath04696f72022-06-13 15:19:14 +05301722 // metadata := uint64(uniport)
1723 // subFlow.SetWriteMetadata(metadata)
1724 allowTransparent := 0
1725 if vpv.AllowTransparent {
1726 allowTransparent = 1
1727 }
vinokuma926cb3e2023-03-29 11:41:06 +05301728 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301729 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1730 subFlow.SetTableMetadata(metadata)
1731 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301732 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1733 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1734 subFlow.Priority = of.DhcpFlowPriority
1735
1736 flow.SubFlows[subFlow.Cookie] = subFlow
1737 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1738 return flow, nil
1739}
1740
1741// BuildDsDhcpFlows to build the downstream dhcp flows
1742func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301743 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1744 flow := &of.VoltFlow{}
1745 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1746 subFlow := of.NewVoltSubFlow()
1747 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301748 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301749 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301750 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301751 }
1752 subFlow.SetUdpv4Match()
1753 subFlow.SrcPort = 67
1754 subFlow.DstPort = 68
1755 uniport, _ := GetApplication().GetPortID(vpv.Port)
1756 nni, err := GetApplication().GetNniPort(vpv.Device)
1757 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301758 return nil, fmt.Errorf("failed to fetch nni port %s from vpv : %w", nni, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301759 }
1760 nniport, err := GetApplication().GetPortID(nni)
1761 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301762 return nil, fmt.Errorf("failed to fetch port id %d for nni : %w", nniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301763 }
1764 subFlow.SetInPort(nniport)
1765 // PortName and PortID to be used for validation of port before flow pushing
1766 flow.PortID = uniport
1767 flow.PortName = vpv.Port
1768 // metadata := uint64(uniport)
1769 // subFlow.SetWriteMetadata(metadata)
1770 allowTransparent := 0
1771 if vpv.AllowTransparent {
1772 allowTransparent = 1
1773 }
vinokuma926cb3e2023-03-29 11:41:06 +05301774 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301775 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1776 subFlow.SetTableMetadata(metadata)
1777 subFlow.Priority = of.DhcpFlowPriority
1778 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301779 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301780 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301781 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301782
1783 flow.SubFlows[subFlow.Cookie] = subFlow
1784 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1785
1786 return flow, nil
1787}
1788
1789// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1790// application.
1791func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301792 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301793 flow := &of.VoltFlow{}
1794 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1795
Naveen Sampath04696f72022-06-13 15:19:14 +05301796 subFlow := of.NewVoltSubFlow()
1797 subFlow.SetTableID(0)
1798
1799 subFlow.SetMatchVlan(vpv.UniVlan)
1800 subFlow.SetSetVlan(vpv.CVlan)
1801 subFlow.SetUdpv6Match()
1802 subFlow.SrcPort = 546
1803 subFlow.DstPort = 547
1804 uniport, err := GetApplication().GetPortID(vpv.Port)
1805 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301806 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301807 }
1808 // Set techprofile, meterid of first service
1809 vpv.services.Range(func(key, value interface{}) bool {
1810 svc := value.(*VoltService)
1811 writemetadata := uint64(svc.TechProfileID) << 32
1812 subFlow.SetWriteMetadata(writemetadata)
1813 subFlow.SetMeterID(svc.UsMeterID)
1814 return false
1815 })
1816 subFlow.SetInPort(uniport)
1817 // PortName and PortID to be used for validation of port before flow pushing
1818 flow.PortID = uniport
1819 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301820 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301821 // metadata := uint64(uniport)
1822 // subFlow.SetWriteMetadata(metadata)
1823 allowTransparent := 0
1824 if vpv.AllowTransparent {
1825 allowTransparent = 1
1826 }
1827 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1828 subFlow.SetTableMetadata(metadata)
1829 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301830 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301831 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1832 subFlow.Priority = of.DhcpFlowPriority
1833
1834 flow.SubFlows[subFlow.Cookie] = subFlow
1835 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1836 return flow, nil
1837}
1838
1839// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1840// application.
1841func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1842 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1843
1844 flow := &of.VoltFlow{}
1845 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1846 subFlow := of.NewVoltSubFlow()
1847 subFlow.SetTableID(0)
1848
1849 vpv.setDsMatchVlan(subFlow)
1850 subFlow.SetUdpv6Match()
1851 subFlow.SrcPort = 547
1852 subFlow.DstPort = 547
1853 uniport, _ := GetApplication().GetPortID(vpv.Port)
1854 nni, err := GetApplication().GetNniPort(vpv.Device)
1855 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301856 logger.Errorw(ctx, "Failed to fetch nni port from vpv", log.Fields{"error": err, "device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05301857 return nil, err
1858 }
1859 nniport, err := GetApplication().GetPortID(nni)
1860 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301861 logger.Errorw(ctx, "Failed to fetch port ID for nni", log.Fields{"error": err, "nni": nni})
Naveen Sampath04696f72022-06-13 15:19:14 +05301862 return nil, err
1863 }
1864 subFlow.SetInPort(nniport)
1865 // PortName and PortID to be used for validation of port before flow pushing
1866 flow.PortID = uniport
1867 flow.PortName = vpv.Port
1868 // metadata := uint64(uniport)
1869 // subFlow.SetWriteMetadata(metadata)
1870 allowTransparent := 0
1871 if vpv.AllowTransparent {
1872 allowTransparent = 1
1873 }
1874 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1875 subFlow.SetTableMetadata(metadata)
1876 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301877 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301878 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1879 subFlow.Priority = of.DhcpFlowPriority
1880
1881 flow.SubFlows[subFlow.Cookie] = subFlow
1882 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1883 return flow, nil
1884}
1885
1886// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1887// The flows included by this function cover US only as the DS is
1888// created either automatically by the VOLTHA or at the device level
1889// earlier
1890func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301891 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301892 flow := &of.VoltFlow{}
1893 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1894
Naveen Sampath04696f72022-06-13 15:19:14 +05301895 subFlow := of.NewVoltSubFlow()
1896 subFlow.SetTableID(0)
1897
1898 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1899 subFlow.SetMatchSrcMac(vpv.MacAddr)
1900 }
1901
1902 subFlow.SetMatchDstMac(BroadcastMAC)
1903 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1904 return nil, err
1905 }
1906 subFlow.SetArpMatch()
1907 uniport, err := GetApplication().GetPortID(vpv.Port)
1908 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301909 return nil, fmt.Errorf("failed to fetch uni port %d from vpv : %w", uniport, err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301910 }
1911 subFlow.SetInPort(uniport)
1912 // PortName and PortID to be used for validation of port before flow pushing
1913 flow.PortID = uniport
1914 flow.PortName = vpv.Port
1915 subFlow.SetReportToController()
1916 allowTransparent := 0
1917 if vpv.AllowTransparent {
1918 allowTransparent = 1
1919 }
1920 metadata := uint64(uniport)
1921 subFlow.SetWriteMetadata(metadata)
1922 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1923 subFlow.SetTableMetadata(metadata)
1924 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1925 subFlow.Priority = of.ArpFlowPriority
1926
1927 flow.SubFlows[subFlow.Cookie] = subFlow
1928 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1929 return flow, nil
1930}
1931
1932// setUsMatchVlan to set upstream match vlan
1933func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301934 logger.Debugw(ctx, "Set Us Match Vlan", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05301935 switch vpv.VlanControl {
1936 case None:
1937 flow.SetMatchVlan(vpv.SVlan)
1938 case ONUCVlanOLTSVlan:
1939 flow.SetMatchVlan(vpv.CVlan)
1940 case OLTCVlanOLTSVlan:
1941 flow.SetMatchVlan(vpv.UniVlan)
1942 //flow.SetSetVlan(vpv.CVlan)
1943 case ONUCVlan:
1944 flow.SetMatchVlan(vpv.SVlan)
1945 case OLTSVlan:
1946 flow.SetMatchVlan(vpv.UniVlan)
1947 //flow.SetSetVlan(vpv.SVlan)
1948 default:
1949 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1950 return errorCodes.ErrInvalidParamInRequest
1951 }
1952 return nil
1953}
1954
1955// BuildUsPppoeFlows to build upstream pppoe flows
1956func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301957 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301958 flow := &of.VoltFlow{}
1959 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301960 subFlow := of.NewVoltSubFlow()
1961 subFlow.SetTableID(0)
1962
1963 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1964 subFlow.SetMatchSrcMac(vpv.MacAddr)
1965 }
1966
1967 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1968 return nil, err
1969 }
1970 subFlow.SetPppoeDiscoveryMatch()
1971 uniport, err := GetApplication().GetPortID(vpv.Port)
1972 if err != nil {
1973 return nil, err
1974 }
1975 subFlow.SetInPort(uniport)
1976 subFlow.SetReportToController()
1977 // PortName and PortID to be used for validation of port before flow pushing
1978 flow.PortID = uniport
1979 flow.PortName = vpv.Port
1980
1981 allowTransparent := 0
1982 if vpv.AllowTransparent {
1983 allowTransparent = 1
1984 }
1985 metadata := uint64(uniport)
1986 subFlow.SetWriteMetadata(metadata)
1987
1988 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1989 subFlow.SetTableMetadata(metadata)
1990
vinokuma926cb3e2023-03-29 11:41:06 +05301991 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301992 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
1993 subFlow.Priority = of.PppoeFlowPriority
1994
1995 flow.SubFlows[subFlow.Cookie] = subFlow
1996 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1997 return flow, nil
1998}
1999
2000// BuildDsPppoeFlows to build downstream pppoe flows
2001func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302002 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
2003 flow := &of.VoltFlow{}
2004 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2005 subFlow := of.NewVoltSubFlow()
2006 subFlow.SetTableID(0)
2007
2008 vpv.setDsMatchVlan(subFlow)
2009 subFlow.SetPppoeDiscoveryMatch()
2010
2011 if NonZeroMacAddress(vpv.MacAddr) {
2012 subFlow.SetMatchDstMac(vpv.MacAddr)
2013 }
2014
2015 uniport, _ := GetApplication().GetPortID(vpv.Port)
2016 nni, err := GetApplication().GetNniPort(vpv.Device)
2017 if err != nil {
2018 return nil, err
2019 }
2020 nniport, err := GetApplication().GetPortID(nni)
2021 if err != nil {
2022 return nil, err
2023 }
2024 subFlow.SetInPort(nniport)
2025 // PortName and PortID to be used for validation of port before flow pushing
2026 flow.PortID = uniport
2027 flow.PortName = vpv.Port
2028 metadata := uint64(uniport)
2029 subFlow.SetWriteMetadata(metadata)
2030 allowTransparent := 0
2031 if vpv.AllowTransparent {
2032 allowTransparent = 1
2033 }
2034 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2035 subFlow.SetTableMetadata(metadata)
2036 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302037 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302038 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2039 subFlow.Priority = of.PppoeFlowPriority
2040
2041 flow.SubFlows[subFlow.Cookie] = subFlow
2042 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2043 return flow, nil
2044}
2045
2046// setDsMatchVlan to set downstream match vlan
2047func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302048 logger.Debugw(ctx, "Set Ds Match Vlan", log.Fields{"Vlan": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302049 switch vpv.VlanControl {
2050 case None:
2051 flow.SetMatchVlan(vpv.SVlan)
2052 case ONUCVlanOLTSVlan,
2053 OLTCVlanOLTSVlan,
2054 ONUCVlan,
2055 OLTSVlan:
2056 flow.SetMatchVlan(vpv.SVlan)
2057 default:
2058 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2059 }
2060}
2061
2062// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2063// in the US direction.
2064func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2065 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2066 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2067 if mvp == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302068 return nil, errors.New("mvlan profile configured not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05302069 }
2070 mvlan := mvp.GetUsMatchVlan()
2071 flow := &of.VoltFlow{}
2072 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2073 subFlow := of.NewVoltSubFlow()
2074 subFlow.SetTableID(0)
2075
Akash Sonia8246972023-01-03 10:37:08 +05302076 subFlow.SetMatchVlan(vpv.UniVlan)
2077 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302078
2079 uniport, err := GetApplication().GetPortID(vpv.Port)
2080 if err != nil {
2081 return nil, err
2082 }
2083 subFlow.SetInPort(uniport)
2084 // PortName and PortID to be used for validation of port before flow pushing
2085 flow.PortID = uniport
2086 flow.PortName = vpv.Port
2087
2088 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2089 subFlow.SetMatchSrcMac(vpv.MacAddr)
2090 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302091 logger.Debugw(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302092 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302093
2094 if vpv.McastService {
2095 metadata := uint64(vpv.McastUsMeterID)
2096 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2097 subFlow.SetMatchPbit(vpv.McastPbit)
2098 subFlow.SetMeterID(vpv.McastUsMeterID)
2099 subFlow.SetWriteMetadata(metadata)
2100 } else {
2101 // Set techprofile, meterid of first service
2102 vpv.services.Range(func(key, value interface{}) bool {
2103 svc := value.(*VoltService)
2104 writemetadata := uint64(svc.TechProfileID) << 32
2105 subFlow.SetWriteMetadata(writemetadata)
2106 subFlow.SetMeterID(svc.UsMeterID)
2107 return false
2108 })
2109 }
2110
2111 allowTransparent := 0
2112 if vpv.AllowTransparent {
2113 allowTransparent = 1
2114 }
2115 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2116 subFlow.SetTableMetadata(metadata)
2117 subFlow.SetIgmpMatch()
2118 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302119 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302120 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2121 subFlow.Priority = of.IgmpFlowPriority
2122
2123 flow.SubFlows[subFlow.Cookie] = subFlow
2124 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2125 return flow, nil
2126}
2127
2128// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302129func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302130 if vpv.DeleteInProgress {
2131 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2132 return
2133 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302134 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302135}
2136
vinokuma926cb3e2023-03-29 11:41:06 +05302137// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302138func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302139 vpv.PendingFlowLock.RLock()
2140 defer vpv.PendingFlowLock.RUnlock()
2141 vpv.Version = database.PresentVersionMap[database.VpvPath]
2142 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302143 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 +05302144 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2145 "UniVlan": vpv.UniVlan, "Error": err})
2146 }
2147 }
2148}
2149
2150// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302151func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302152 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 +05302153 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302154}
2155
2156// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302157func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
2158 vpv.RangeOnServices(cntx, ClearFlagsInService)
Naveen Sampath04696f72022-06-13 15:19:14 +05302159}
2160
2161// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302162func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302163 logger.Debugw(ctx, "Clear All Vpv Flags", log.Fields{"Port": vpv.Port, "Device": vpv.Device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302164 vpv.PendingFlowLock.Lock()
2165 vpv.FlowsApplied = false
2166 vpv.IgmpFlowsApplied = false
2167 vpv.PendingDeleteFlow = make(map[string]bool)
2168 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302169 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302170 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2171 log.Fields{"device": vpv.Device, "port": vpv.Port,
2172 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2173}
2174
2175// CreateVpvFromString to create vpv from string
2176func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302177 logger.Info(ctx, "Create Vpv From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05302178 var vpv VoltPortVnet
2179 if err := json.Unmarshal(b, &vpv); err == nil {
2180 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2181 if !ok {
2182 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2183 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2184 }
2185 vpv.servicesCount = atomic.NewUint64(0)
2186 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2187 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2188 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2189 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2190 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2191 vnet.associatePortToVnet(vpv.Port)
2192 }
2193
2194 if vpv.DeleteInProgress {
2195 va.VoltPortVnetsToDelete[&vpv] = true
2196 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2197 }
2198 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2199 }
2200}
2201
2202// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302203func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302204 logger.Info(ctx, "Restore Vpvs From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302205 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302206 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302207 for hash, vpv := range vpvs {
2208 b, ok := vpv.Value.([]byte)
2209 if !ok {
2210 logger.Warn(ctx, "The value type is not []byte")
2211 continue
2212 }
2213 va.CreateVpvFromString(b, hash)
2214 }
2215}
2216
2217// GetVnetByPort : VNET related functionality of VOLT Application here on.
2218// Get the VNET from a port. The port identity is passed as device and port identities in string.
2219// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2220// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2221func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302222 logger.Debugw(ctx, "Get Vnet By Port", log.Fields{"port": port, "svlan": svlan, "cvlan": cvlan, "univlan": univlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302223 if _, ok := va.VnetsByPort.Load(port); !ok {
2224 return nil
2225 }
2226 vpvs, _ := va.VnetsByPort.Load(port)
2227 for _, vpv := range vpvs.([]*VoltPortVnet) {
2228 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2229 return vpv
2230 }
2231 }
2232 return nil
2233}
2234
2235// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302236func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302237 // The VNET is not on the port and is to be added
2238 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2239 vpv := NewVoltPortVnet(vvnet)
2240 vpv.MacLearning = vvnet.MacLearning
2241 vpv.Port = port
2242 vvnet.associatePortToVnet(port)
2243 if _, ok := va.VnetsByPort.Load(port); !ok {
2244 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2245 }
2246 vpvsIntf, _ := va.VnetsByPort.Load(port)
2247 vpvs := vpvsIntf.([]*VoltPortVnet)
2248 vpvs = append(vpvs, vpv)
2249 va.VnetsByPort.Store(port, vpvs)
2250 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2251
2252 vpv.VpvLock.Lock()
2253 defer vpv.VpvLock.Unlock()
2254
2255 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302256 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302257
Tinoj Josephec742f62022-09-29 19:11:10 +05302258 if !vs.IsActivated {
2259 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2260 // Process the PORT UP if the port is already up
2261 d, err := va.GetDeviceFromPort(port)
2262 if err == nil {
2263 vpv.setDevice(d.Name)
2264 }
2265 vpv.WriteToDb(cntx)
2266 return vpv
2267 }
2268
Naveen Sampath04696f72022-06-13 15:19:14 +05302269 // Process the PORT UP if the port is already up
2270 d, err := va.GetDeviceFromPort(port)
2271 if err == nil {
2272 vpv.setDevice(d.Name)
2273 p := d.GetPort(port)
2274 if p != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302275 logger.Debugw(ctx, "Checking UNI port state", log.Fields{"State": p.State})
Akash Soni024eb8e2023-04-28 16:25:09 +05302276 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
2277 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302278 }
2279 }
2280 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302281 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302282 return vpv
2283}
2284
2285// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302286func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302287 logger.Debugw(ctx, "Delete Vnet From Port", log.Fields{"Port": port, "VNET": vpv.Device})
vinokuma926cb3e2023-03-29 11:41:06 +05302288 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302289 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2290
vinokuma926cb3e2023-03-29 11:41:06 +05302291 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302292 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2293
vinokuma926cb3e2023-03-29 11:41:06 +05302294 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302295 va.DeleteMacInPortMap(vpv.MacAddr)
2296
vinokuma926cb3e2023-03-29 11:41:06 +05302297 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302298 vpvsIntf, ok := va.VnetsByPort.Load(port)
2299 if !ok {
2300 return
2301 }
2302 vpvs := vpvsIntf.([]*VoltPortVnet)
2303 for i, lvpv := range vpvs {
vinokuma04dc9f82023-07-31 15:47:49 +05302304 if reflect.DeepEqual(lvpv, vpv) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302305 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2306 "UNIVLAN": vpv.UniVlan})
2307
2308 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2309
2310 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302311 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302312
2313 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302314 vpv.DelTrapFlows(cntx)
2315 vpv.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302316 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2317 vpv.PendingFlowLock.RLock()
2318 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302319 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302320 }
2321 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302322 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302323 }
2324 vpv.PendingFlowLock.RUnlock()
2325 return
2326 }
2327 }
2328}
2329
2330// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302331func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302332 logger.Info(ctx, "Restore Vnets From Db")
Naveen Sampath04696f72022-06-13 15:19:14 +05302333 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302334 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302335 for _, net := range vnets {
2336 b, ok := net.Value.([]byte)
2337 if !ok {
2338 logger.Warn(ctx, "The value type is not []byte")
2339 continue
2340 }
2341 var vnet VoltVnet
2342 err := json.Unmarshal(b, &vnet)
2343 if err != nil {
2344 logger.Warn(ctx, "Unmarshal of VNET failed")
2345 continue
2346 }
2347 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302348 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302349 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2350 }
2351
2352 if vnet.DeleteInProgress {
2353 va.VnetsToDelete[vnet.Name] = true
2354 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2355 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302356 }
2357}
2358
2359// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2360// are used as the key to locate the service. If more than one service is on the
2361// same port (essentially a UNI of ONU), the services must be separated by different
2362// CVLANs
2363func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302364 logger.Debugw(ctx, "Get Service From Cvlan", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302365 // Fetch the device first to make sure the device exists
2366 dIntf, ok := va.DevicesDisc.Load(device)
2367 if !ok {
2368 return nil
2369 }
2370 d := dIntf.(*VoltDevice)
2371
2372 // If the port is NNI port, the services dont exist on it. The svc then
2373 // must be obtained from a different context and is not included here
2374 if port == d.NniPort {
2375 return nil
2376 }
2377
vinokuma926cb3e2023-03-29 11:41:06 +05302378 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302379 var service *VoltService
2380
2381 // This is an access port and the port should have all the associated
2382 // services which can be uniquely identified by the VLANs in the packet
2383 vnets, ok := va.VnetsByPort.Load(port)
2384
2385 if !ok {
2386 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2387 return nil
2388 }
2389 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2390 for _, vnet := range vnets.([]*VoltPortVnet) {
2391 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2392 switch vnet.VlanControl {
2393 case ONUCVlanOLTSVlan:
2394 service = vnet.MatchesPriority(priority)
2395 if vnet.MatchesCvlan(vlans) && service != nil {
2396 return service
2397 }
2398 case ONUCVlan,
2399 None:
2400 service = vnet.MatchesPriority(priority)
2401 // In case of DHCP Flow - cvlan == VlanNone
2402 // In case of HSIA Flow - cvlan == Svlan
2403 if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
2404 return service
2405 }
2406 case OLTCVlanOLTSVlan,
2407 OLTSVlan:
2408 service = vnet.MatchesPriority(priority)
2409 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2410 return service
2411 }
2412 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302413 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302414 }
2415 }
2416 return nil
2417}
2418
2419// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2420// are used as the key to locate the service. If more than one service is on the
2421// same port (essentially a UNI of ONU), the services must be separated by different
2422// CVLANs
2423func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2424 // Fetch the device first to make sure the device exists
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302425 logger.Debugw(ctx, "Get Vnet From Fields", log.Fields{"Device": device, "Port": port, "VLANs": vlans, "Priority": priority})
Naveen Sampath04696f72022-06-13 15:19:14 +05302426 dIntf, ok := va.DevicesDisc.Load(device)
2427 if !ok {
2428 return nil, nil
2429 }
2430 d := dIntf.(*VoltDevice)
2431
2432 // If the port is NNI port, the services dont exist on it. The svc then
2433 // must be obtained from a different context and is not included here
2434 if port == d.NniPort {
2435 return nil, nil
2436 }
2437
2438 //To return the matched service
2439 var service *VoltService
2440
2441 // This is an access port and the port should have all the associated
2442 // services which can be uniquely identified by the VLANs in the packet
2443 if vnets, ok := va.VnetsByPort.Load(port); ok {
2444 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2445 for _, vnet := range vnets.([]*VoltPortVnet) {
2446 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2447 switch vnet.VlanControl {
2448 case ONUCVlanOLTSVlan:
2449 service = vnet.MatchesPriority(priority)
2450 if vnet.MatchesCvlan(vlans) && service != nil {
2451 return vnet, service
2452 }
2453 case ONUCVlan,
2454 None:
2455 service = vnet.MatchesPriority(priority)
2456 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2457 return vnet, service
2458 }
2459 case OLTCVlanOLTSVlan,
2460 OLTSVlan:
2461 service = vnet.MatchesPriority(priority)
2462 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2463 return vnet, service
2464 }
2465 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302466 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302467 }
2468 }
2469 }
2470 return nil, nil
2471}
2472
2473// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2474// are used as the key to locate the service. If more than one service is on the
2475// same port (essentially a UNI of ONU), the services must be separated by different
2476// CVLANs
2477func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302478 logger.Debugw(ctx, "Get Vnet From Pkt", log.Fields{"Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +05302479 vlans := GetVlans(pkt)
2480 priority := GetPriority(pkt)
2481 return va.GetVnetFromFields(device, port, vlans, priority)
2482}
2483
2484// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302485func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302486 logger.Debugw(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302487 pushflow := func(key interface{}, value interface{}) bool {
2488 device := value.(*VoltDevice)
2489 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302490 logger.Warnw(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302491 return true
2492 }
2493 if device.State != controller.DeviceStateUP {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302494 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 +05302495 return true
2496 }
2497 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302498 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 +05302499 return true
2500 }
2501
2502 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2503 vnetList := vnetListIntf.(*util.ConcurrentMap)
2504 vnetList.Set(vnet.Name, true)
2505 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2506 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()})
2507 return true
2508 }
2509 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2510 err := ProcessIcmpv6McGroup(device.Name, false)
2511 if err != nil {
2512 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2513 return true
2514 }
2515 if portID, err := va.GetPortID(device.NniPort); err == nil {
2516 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2517 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2518 return true
2519 }
2520
vinokuma926cb3e2023-03-29 11:41:06 +05302521 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302522 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302523 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302524 if err != nil {
2525 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2526 return true
2527 }
2528 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2529
2530 // Pushing ARP Flow
2531 flow = BuildDSArpFlow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302532 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302533 if err != nil {
2534 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2535 return true
2536 }
2537 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2538
2539 vnetList := util.NewConcurrentMap()
2540 vnetList.Set(vnet.Name, true)
2541 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2542 }
2543 return true
2544 }
2545 va.DevicesDisc.Range(pushflow)
2546}
2547
2548// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302549func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302550 logger.Debugw(ctx, "PushDevFlowForDevice", log.Fields{"device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302551 err := ProcessIcmpv6McGroup(device.Name, false)
2552 if err != nil {
2553 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2554 return
2555 }
2556 pushicmpv6 := func(key, value interface{}) bool {
2557 vnet := value.(*VoltVnet)
2558 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2559 vnetList := vnetListIntf.(*util.ConcurrentMap)
2560 vnetList.Set(vnet.Name, true)
2561 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2562 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()})
2563 return true
2564 }
2565 nniPortID, err := va.GetPortID(device.NniPort)
2566 if err != nil {
2567 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2568 }
2569 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2570 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2571 return true
2572 }
2573 flow := BuildICMPv6Flow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302574 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302575 if err != nil {
2576 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2577 return true
2578 }
2579 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2580
2581 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302582 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302583 if err != nil {
2584 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2585 return true
2586 }
2587 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2588
2589 vnetList := util.NewConcurrentMap()
2590 vnetList.Set(vnet.Name, true)
2591 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2592 return true
2593 }
2594 va.VnetsByName.Range(pushicmpv6)
2595}
2596
2597// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302598func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302599 logger.Debugw(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302600 delflows := func(key interface{}, value interface{}) bool {
2601 device := value.(*VoltDevice)
2602
2603 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2604 vnetList := vnetListIntf.(*util.ConcurrentMap)
2605 vnetList.Remove(vnet.Name)
2606 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2607 if vnetList.Length() != 0 {
2608 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()})
2609 return true
2610 }
2611 }
2612 if portID, err := va.GetPortID(device.NniPort); err == nil {
2613 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2614 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2615 return true
2616 }
vinokuma926cb3e2023-03-29 11:41:06 +05302617 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302618 flow := BuildICMPv6Flow(portID, vnet)
2619 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302620 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302621 if err != nil {
2622 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2623 return true
2624 }
2625 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2626
vinokuma926cb3e2023-03-29 11:41:06 +05302627 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302628 flow = BuildDSArpFlow(portID, vnet)
2629 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302630 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302631 if err != nil {
2632 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2633 return true
2634 }
2635 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2636
2637 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2638 }
2639 return true
2640 }
2641 va.DevicesDisc.Range(delflows)
2642}
2643
2644// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302645func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302646 logger.Debugw(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302647 delicmpv6 := func(key, value interface{}) bool {
2648 vnet := value.(*VoltVnet)
2649 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2650 vnetList := vnetListIntf.(*util.ConcurrentMap)
2651 vnetList.Remove(vnet.Name)
2652 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2653 if vnetList.Length() != 0 {
2654 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()})
2655 return true
2656 }
2657 } else {
2658 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2659 return true
2660 }
2661 nniPortID, err := va.GetPortID(device.NniPort)
2662 if err != nil {
2663 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2664 }
2665 flow := BuildICMPv6Flow(nniPortID, vnet)
2666 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302667 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302668 if err != nil {
2669 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2670 return true
2671 }
2672
2673 flow = BuildDSArpFlow(nniPortID, vnet)
2674 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302675 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302676 if err != nil {
2677 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2678 return true
2679 }
2680
2681 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2682 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2683 return true
2684 }
2685 va.VnetsByName.Range(delicmpv6)
2686 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2687 err := ProcessIcmpv6McGroup(device.Name, true)
2688 if err != nil {
2689 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2690 return
2691 }
2692}
2693
2694// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302695func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302696 logger.Debugw(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302697 delflows := func(key interface{}, value interface{}) bool {
2698 device := value.(*VoltDevice)
2699 if device.SerialNum != deviceSerialNum {
2700 return true
2701 }
2702 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2703 vnetList := vnetListIntf.(*util.ConcurrentMap)
2704 vnetList.Remove(vnet.Name)
2705 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2706 if vnetList.Length() != 0 {
2707 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()})
2708 return true
2709 }
2710 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2711 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2712 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2713 // The step will be as follow:
2714 // 1. Deact Service
2715 // 2. Pod Reboot
2716 // 3. Pending Delete Service triggered
2717 // 4. Del Service Ind followed by DelVnet req from NB
2718 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2719 // hence the flow will not be cleared
2720 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2721 return true
2722 }
2723 if portID, err := va.GetPortID(device.NniPort); err == nil {
2724 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2725 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2726 return false
2727 }
2728 flow := BuildICMPv6Flow(portID, vnet)
2729 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302730 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302731 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2732 }
2733 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2734
2735 flow = BuildDSArpFlow(portID, vnet)
2736 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302737 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302738 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2739 }
2740 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2741 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2742 }
2743 return false
2744 }
2745 va.DevicesDisc.Range(delflows)
2746}
2747
2748// BuildICMPv6Flow to Build DS flow for ICMPv6
2749func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302750 logger.Debugw(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302751 flow := &of.VoltFlow{}
2752 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2753 subFlow := of.NewVoltSubFlow()
2754
2755 subFlow.SetICMPv6Match()
2756 subFlow.SetMatchVlan(vnet.SVlan)
2757 subFlow.SetInPort(inport)
2758 subFlow.SetPopVlan()
2759 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2760 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2761 subFlow.Priority = of.McFlowPriority
2762 var metadata uint64
2763 if vnet.VlanControl == None {
2764 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2765 } else {
2766 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2767 }
2768 subFlow.SetTableMetadata(metadata)
2769 metadata = uint64(vnet.setPbitRemarking())
2770
2771 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2772 subFlow.SetWriteMetadata(metadata)
2773 flow.SubFlows[subFlow.Cookie] = subFlow
2774 return flow
2775}
2776
vinokuma926cb3e2023-03-29 11:41:06 +05302777// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302778func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302779 logger.Debugw(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302780
2781 flow := &of.VoltFlow{}
2782 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2783 subFlow := of.NewVoltSubFlow()
2784
2785 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2786 subFlow.SetArpMatch()
2787 subFlow.SetMatchDstMac(BcastMAC)
2788 subFlow.SetMatchVlan(vnet.SVlan)
2789 subFlow.SetInPort(inport)
2790 subFlow.SetPopVlan()
2791 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2792
2793 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2794 subFlow.Priority = of.McFlowPriority
2795
2796 var metadata uint64
2797 if vnet.VlanControl == None {
2798 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2799 } else {
2800 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2801 }
2802 subFlow.SetTableMetadata(metadata)
2803 metadata = uint64(vnet.setPbitRemarking())
2804 subFlow.SetWriteMetadata(metadata)
2805
2806 flow.SubFlows[subFlow.Cookie] = subFlow
2807 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2808 return flow
2809}
2810
2811// setPbitRemarking to set Pbit remarking
2812func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302813 // Remarkable
2814 // Remarked Pbit Pbit
2815 // |-----------------------------| |------|
2816 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2817 // 000 000 000 000 000 000 000 000 00000000
2818
2819 // Eg:
2820 // For 6:3 & 7:1
2821 // 001 011 000 000 000 000 000 000 11000000
2822
2823 var remarkable uint8
2824 var remarked uint32
2825 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2826 remarkable = remarkable | 1<<refPbit
2827 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2828 }
2829 return remarked<<8 | uint32(remarkable)
2830}
2831
2832// ProcessIcmpv6McGroup to add icmpv6 multicast group
2833func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302834 logger.Info(ctx, "Creating ICMPv6 MC Group")
2835 va := GetApplication()
2836 vd := va.GetDevice(device)
2837 group := &of.Group{}
2838 group.GroupID = ICMPv6ArpGroupID
2839 group.Device = device
2840 if delete {
2841 if !vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302842 logger.Debug(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
Naveen Sampath04696f72022-06-13 15:19:14 +05302843 return nil //TODO
2844 }
2845 vd.icmpv6GroupAdded = false
2846 group.Command = of.GroupCommandDel
2847 group.ForceAction = true
2848 } else {
2849 if vd.icmpv6GroupAdded {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302850 logger.Debug(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
Naveen Sampath04696f72022-06-13 15:19:14 +05302851 return nil //TODO
2852 }
2853 vd.icmpv6GroupAdded = true
2854 group.Command = of.GroupCommandAdd
2855 receivers := GetApplication().GetIcmpv6Receivers(device)
2856 group.Buckets = append(group.Buckets, receivers...)
2857 }
2858 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2859 port, _ := GetApplication().GetNniPort(device)
2860 err := cntlr.GetController().GroupUpdate(port, device, group)
2861 return err
2862}
2863
vinokuma926cb3e2023-03-29 11:41:06 +05302864// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302865func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302866 logger.Debugw(ctx, "Is Vlan Matching", log.Fields{"cvlan": cvlan, "svlan": svlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302867 switch vpv.VlanControl {
2868 case ONUCVlanOLTSVlan,
2869 OLTCVlanOLTSVlan:
2870 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2871 return true
2872 }
2873 case ONUCVlan,
2874 OLTSVlan,
2875 None:
2876 if vpv.SVlan == svlan {
2877 return true
2878 }
2879 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302880 logger.Warnw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05302881 }
2882 return false
2883}
2884
vinokuma926cb3e2023-03-29 11:41:06 +05302885// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302886func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302887 logger.Debugw(ctx, "Push Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302888 for cookie := range flow.SubFlows {
2889 cookie := strconv.FormatUint(cookie, 10)
2890 fe := &FlowEvent{
2891 eType: EventTypeControlFlowAdded,
2892 cookie: cookie,
2893 eventData: vpv,
2894 }
2895 device.RegisterFlowAddEvent(cookie, fe)
2896 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302897 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302898}
2899
vinokuma926cb3e2023-03-29 11:41:06 +05302900// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302901func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302902 logger.Debugw(ctx, "Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05302903 sendFlowFailureInd := func(key, value interface{}) bool {
2904 //svc := value.(*VoltService)
2905 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2906 return true
2907 }
2908 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2909 vpv.services.Range(sendFlowFailureInd)
2910}
2911
vinokuma926cb3e2023-03-29 11:41:06 +05302912// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302913func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302914 logger.Debugw(ctx, "Remove Flows", log.Fields{"DeviceName": device.Name, "Flow port": flow.PortID})
Naveen Sampath04696f72022-06-13 15:19:14 +05302915 vpv.PendingFlowLock.Lock()
2916 defer vpv.PendingFlowLock.Unlock()
2917
2918 for cookie := range flow.SubFlows {
2919 cookie := strconv.FormatUint(cookie, 10)
2920 fe := &FlowEvent{
2921 eType: EventTypeControlFlowRemoved,
2922 device: device.Name,
2923 cookie: cookie,
2924 eventData: vpv,
2925 }
2926 device.RegisterFlowDelEvent(cookie, fe)
2927 vpv.PendingDeleteFlow[cookie] = true
2928 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302929 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302930}
2931
vinokuma926cb3e2023-03-29 11:41:06 +05302932// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302933func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302934 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 +05302935 vpv.PendingFlowLock.RLock()
2936 defer vpv.PendingFlowLock.RUnlock()
2937 if !vpv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302938 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 +05302939 return
2940 }
2941 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302942 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 +05302943 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302944 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2945 }
2946}
2947
vinokuma926cb3e2023-03-29 11:41:06 +05302948// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302949func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302950 vpv.PendingFlowLock.Lock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302951 logger.Debugw(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05302952
2953 delete(vpv.PendingDeleteFlow, cookie)
2954 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302955 vpv.CheckAndDeleteVpv(cntx)
2956 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302957}
2958
vinokuma926cb3e2023-03-29 11:41:06 +05302959// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302960func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302961 vpv.PendingFlowLock.Lock()
2962
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302963 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 +05302964
2965 sendFlowFailureInd := func(key, value interface{}) bool {
2966 svc := value.(*VoltService)
2967 svc.triggerServiceFailureInd(errorCode, errReason)
2968 return true
2969 }
2970 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2971 vpv.services.Range(sendFlowFailureInd)
2972
2973 if vpv.DeleteInProgress {
2974 delete(vpv.PendingDeleteFlow, cookie)
2975 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302976 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302977 } else {
2978 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302979 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302980 }
2981}
2982
vinokuma926cb3e2023-03-29 11:41:06 +05302983// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302984func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302985 logger.Debugw(ctx, "Remove Flows", log.Fields{"PortName": flow.PortName, "DeviceName": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302986 vv.VnetLock.Lock()
2987 defer vv.VnetLock.Unlock()
2988
2989 var flowMap map[string]bool
2990 var ok bool
2991
2992 for cookie := range flow.SubFlows {
2993 cookie := strconv.FormatUint(cookie, 10)
2994 fe := &FlowEvent{
2995 eType: EventTypeDeviceFlowRemoved,
2996 device: device.Name,
2997 cookie: cookie,
2998 eventData: vv,
2999 }
3000 device.RegisterFlowDelEvent(cookie, fe)
3001 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
3002 flowMap = make(map[string]bool)
3003 }
3004 flowMap[cookie] = true
3005 vv.PendingDeleteFlow[device.Name] = flowMap
3006 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303007 vv.WriteToDb(cntx)
3008 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05303009}
3010
vinokuma926cb3e2023-03-29 11:41:06 +05303011// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303012func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303013 logger.Debugw(ctx, "Check And Delete Vnet", log.Fields{"Device": device, "Vnet": vv.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05303014 if !vv.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303015 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 +05303016 return
3017 }
3018 vv.VnetPortLock.RLock()
3019 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
3020 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
3021 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303022 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05303023 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
3024 } else {
3025 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
3026 }
3027 vv.VnetPortLock.RUnlock()
3028}
3029
vinokuma926cb3e2023-03-29 11:41:06 +05303030// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303031func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303032 vv.VnetLock.Lock()
3033 defer vv.VnetLock.Unlock()
3034
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303035 logger.Debugw(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303036
3037 if _, ok := vv.PendingDeleteFlow[device]; ok {
3038 delete(vv.PendingDeleteFlow[device], cookie)
3039 }
3040
3041 //Check and update success for pending disable request
3042 if d := GetApplication().GetDevice(device); d != nil {
3043 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
3044 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303045 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303046 }
3047 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303048 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05303049}
3050
vinokuma926cb3e2023-03-29 11:41:06 +05303051// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303052func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303053 vv.VnetLock.Lock()
3054 defer vv.VnetLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303055 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 +05303056
3057 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3058 if _, ok := flowMap[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303059 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 +05303060
3061 if vv.DeleteInProgress {
3062 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303063 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303064 }
3065 return
3066 }
3067 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303068 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 +05303069}
3070
vinokuma926cb3e2023-03-29 11:41:06 +05303071// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303072func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303073 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3074 // When multiple Igmp-suported service enabled, comment "return false"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303075 logger.Debugw(ctx, "Igmp Flow Install Failure", log.Fields{"Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05303076
3077 sendFlowFailureInd := func(key, value interface{}) bool {
3078 svc := value.(*VoltService)
3079 if svc.IgmpEnabled {
3080 svc.triggerServiceFailureInd(errorCode, errReason)
3081 return false
3082 }
3083 return true
3084 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303085 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 +05303086 vpv.services.Range(sendFlowFailureInd)
3087}
3088
3089// GetMatchingMcastService to get matching multicast service
3090func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303091 logger.Debugw(ctx, "Get Matching Mcast Service", log.Fields{"Port": port, "Device": device, "Cvlan": cvlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05303092 var service *VoltService
3093 dIntf, ok := va.DevicesDisc.Load(device)
3094 if !ok {
3095 return nil
3096 }
3097 d := dIntf.(*VoltDevice)
3098
3099 // If the port is NNI port, the services dont exist on it. The svc then
3100 // must be obtained from a different context and is not included here
3101 if port == d.NniPort {
3102 return nil
3103 }
3104
3105 // This is an access port and the port should have all the associated
3106 // services which can be uniquely identified by the VLANs in the packet
3107 vnets, ok := va.VnetsByPort.Load(port)
3108
3109 if !ok {
3110 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3111 return nil
3112 }
3113 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3114 getMcastService := func(key, value interface{}) bool {
3115 srv := value.(*VoltService)
3116 if srv.IgmpEnabled {
3117 service = srv
3118
3119 //TODO: Current implementation supports only for single service with Igmp Enabled
3120 //FIX-ME: When multiple service suports Igmp, update of logic required
3121 return false
3122 }
3123 return true
3124 }
3125
3126 for _, vpv := range vnets.([]*VoltPortVnet) {
3127 if vpv.CVlan == cvlan {
3128 vpv.services.Range(getMcastService)
3129 if service != nil {
3130 break
3131 }
3132 }
3133 }
3134 return service
3135}
3136
vinokuma926cb3e2023-03-29 11:41:06 +05303137// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303138func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303139 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +05303140 vv.VnetLock.Lock()
3141 cookieList := []uint64{}
3142 flowMap := vv.PendingDeleteFlow[device]
3143
3144 for cookie := range flowMap {
3145 cookieList = append(cookieList, convertToUInt64(cookie))
3146 }
3147 vv.VnetLock.Unlock()
3148
3149 if len(cookieList) == 0 {
3150 return false
3151 }
3152
3153 for _, cookie := range cookieList {
3154 if vd := GetApplication().GetDevice(device); vd != nil {
3155 flow := &of.VoltFlow{}
3156 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3157 subFlow := of.NewVoltSubFlow()
3158 subFlow.Cookie = cookie
3159 flow.SubFlows[cookie] = subFlow
3160 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303161 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303162 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3163 }
3164 }
3165 }
3166 return true
3167}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303168
vinokuma926cb3e2023-03-29 11:41:06 +05303169// JSONMarshal wrapper function for json Marshal VoltVnet
3170func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303171 return json.Marshal(VoltVnet{
3172 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303173 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303174 VnetOper: VnetOper{
3175 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3176 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3177 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3178 },
3179 })
3180}
3181
vinokuma926cb3e2023-03-29 11:41:06 +05303182// JSONMarshal wrapper function for json Marshal VoltPortVnet
3183func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303184 return json.Marshal(VoltPortVnet{
3185 Device: vpv.Device,
3186 Port: vpv.Port,
3187 PonPort: vpv.PonPort,
3188 VnetName: vpv.VnetName,
3189 SVlan: vpv.SVlan,
3190 CVlan: vpv.CVlan,
3191 UniVlan: vpv.UniVlan,
3192 SVlanTpid: vpv.SVlanTpid,
3193 DhcpRelay: vpv.DhcpRelay,
3194 ArpRelay: vpv.ArpRelay,
3195 PppoeIa: vpv.PppoeIa,
3196 MacLearning: vpv.MacLearning,
3197 DhcpStatus: vpv.DhcpStatus,
3198 DhcpExpiryTime: vpv.DhcpExpiryTime,
3199 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3200 FlowsApplied: vpv.FlowsApplied,
3201 Ipv4Addr: vpv.Ipv4Addr,
3202 Ipv6Addr: vpv.Ipv6Addr,
3203 MacAddr: vpv.MacAddr,
3204 LearntMacAddr: vpv.LearntMacAddr,
3205 CircuitID: vpv.CircuitID,
3206 RemoteID: vpv.RemoteID,
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05303207 IsOption82Enabled: vpv.IsOption82Enabled,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303208 RelayState: vpv.RelayState,
3209 PPPoeState: vpv.PPPoeState,
3210 RelayStatev6: vpv.RelayStatev6,
3211 IgmpEnabled: vpv.IgmpEnabled,
3212 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3213 McastService: vpv.McastService,
3214 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3215 VlanControl: vpv.VlanControl,
3216 MvlanProfileName: vpv.MvlanProfileName,
3217 Version: vpv.Version,
3218 McastTechProfileID: vpv.McastTechProfileID,
3219 McastPbit: vpv.McastPbit,
3220 McastUsMeterID: vpv.McastUsMeterID,
3221 AllowTransparent: vpv.AllowTransparent,
3222 SchedID: vpv.SchedID,
3223 DHCPv6DUID: vpv.DHCPv6DUID,
3224 PendingDeleteFlow: vpv.PendingDeleteFlow,
3225 DeleteInProgress: vpv.DeleteInProgress,
3226 Blocked: vpv.Blocked,
3227 DhcpPbit: vpv.DhcpPbit,
3228 })
3229}
Tinoj Josephec742f62022-09-29 19:11:10 +05303230
3231func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05303232 logger.Debugw(ctx, "Is Service Activated", log.Fields{"Name": vpv.Port})
Tinoj Josephec742f62022-09-29 19:11:10 +05303233 isActivated := false
3234 vpv.services.Range(func(key, value interface{}) bool {
3235 svc := value.(*VoltService)
3236 if svc.IsActivated {
3237 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3238 isActivated = true
3239 return false //to exit loop
3240 }
3241 return true
3242 })
3243 return isActivated
3244}