blob: 2a9d4b251cf6bae218570ad10d3677b0211a438c [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"
22 "net"
vinokuma04dc9f82023-07-31 15:47:49 +053023 "reflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053024 "strconv"
25 "sync"
26 "time"
27
Akash Sonia8246972023-01-03 10:37:08 +053028 //errorCodes "voltha-go-controller/internal/pkg/errorcodes"
29
Naveen Sampath04696f72022-06-13 15:19:14 +053030 "github.com/google/gopacket"
31 "github.com/google/gopacket/layers"
32 "go.uber.org/atomic"
33
Akash Sonia8246972023-01-03 10:37:08 +053034 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053035 "voltha-go-controller/internal/pkg/controller"
36 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053037
38 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053039 "voltha-go-controller/internal/pkg/of"
40 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053041 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053042)
43
44const (
45 // ICMPv6ArpGroupID constant
46 ICMPv6ArpGroupID uint32 = 1
47
48 // Radisys vendor id constant
49 Radisys string = "Radisys"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053050
51 // DPU_MGMT_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053052 DpuMgmtTraffic string = "DPU_MGMT_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053053
54 // DPU_ANCP_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053055 DpuAncpTraffic string = "DPU_ANCP_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053056
57 // FTTB_SUBSCRIBER_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053058 FttbSubscriberTraffic string = "FTTB_SUBSCRIBER_TRAFFIC"
Naveen Sampath04696f72022-06-13 15:19:14 +053059)
60
61var (
62 //BroadcastMAC - Broadcast MAC Address
63 BroadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
64)
65
66// NonZeroMacAddress utility to identify if the MAC address is non-zero.
67// We use zero MAC address as an unset MAC address
68func NonZeroMacAddress(h net.HardwareAddr) bool {
69 for i := 0; i < 6; i++ {
70 if h[i] != 0 {
71 return true
72 }
73 }
74 return false
75}
76
77// VNET package manages the different virtual networks that are part of the
78// the network. In the case of VOLT, the networks can be single tagged or
79// double tagged networks. In addition, the networks may be used for unicast
80// and multicast traffic. The unicast traffic further has two models, the
81// 1:1 and N:1 model. In case of a 1:1 model, the outer tag is same for many
82// subscribers and the inner tag is unique to each subscriber for the same
83// outer tag. The N:1 uses the same inner and outer tags, or for that matter
84// a single tag that can also be shared by subscribers. The VNET implementation
85// manages all these possibilities and the associated configuration.
86
87const (
88 // PbitMatchNone constant
89 PbitMatchNone of.PbitType = 8
90 // PbitMatchAll constant
91 PbitMatchAll of.PbitType = 0xFF
92)
93
94// SVlan - Value of the outer tag if double tagged or the only tag if single
95// tagged
96// SVlanTpid - SVlan Tag Protocol Identifier
97// CVlan - Value of the inner tag. Set to VlanNone if single tagged
98// DhcpRelay - Set to true if the DHCP relay is enabled on the virtual network
99// MacLearning - Set to true if the flows should include MAC address
100// UsDhcpPbit - The pbit used for US DHCP packets
101// DsDhcpPbit - The pbit used for DS DHCP packets
102
103// VnetConfig structure
104type VnetConfig struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530105 CtrlPktPbitRemark map[of.PbitType]of.PbitType
Naveen Sampath04696f72022-06-13 15:19:14 +0530106 Name string
vinokuma926cb3e2023-03-29 11:41:06 +0530107 VnetType string
Naveen Sampath04696f72022-06-13 15:19:14 +0530108 Encapsulation string
vinokuma926cb3e2023-03-29 11:41:06 +0530109 DevicesList []string //List of serial number of devices on which this vnet is applied
Naveen Sampath04696f72022-06-13 15:19:14 +0530110 UsDhcpPbit []of.PbitType
111 DsDhcpPbit []of.PbitType
112 UsIGMPPbit []of.PbitType
113 DsIGMPPbit []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530114 ONTEtherTypeClassification int
115 MacLearning MacLearningType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530116 UsPonCTagPriority of.PbitType
117 UsPonSTagPriority of.PbitType
118 DsPonCTagPriority of.PbitType
119 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530120 SVlan of.VlanType
121 CVlan of.VlanType
122 UniVlan of.VlanType
123 SVlanTpid layers.EthernetType
124 VlanControl VlanControl
125 DhcpRelay bool
126 ArpLearning bool
127 AllowTransparent bool
128 PppoeIa bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530129}
130
131// VnetOper structure
132type VnetOper struct {
133 PendingDeleteFlow map[string]map[string]bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530134 AssociatedPorts map[string]bool `json:"-"`
vinokuma926cb3e2023-03-29 11:41:06 +0530135 PendingDeviceToDelete string
136 VnetLock sync.RWMutex `json:"-"`
137 VnetPortLock sync.RWMutex `json:"-"`
138 DeleteInProgress bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530139}
140
141// VoltVnet sructure
142type VoltVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530143 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530144 VnetConfig
145 VnetOper
Naveen Sampath04696f72022-06-13 15:19:14 +0530146}
147
148const (
149 // EncapsulationPPPoEIA constant
150 EncapsulationPPPoEIA string = "PPPoE-IA"
151 // EncapsulationPPPoE constant
152 EncapsulationPPPoE string = "PPPoE"
153 // EncapsulationIPoE constant
154 EncapsulationIPoE string = "IPoE"
155)
156
157// NewVoltVnet is constructor for the VNET structure
158func NewVoltVnet(cfg VnetConfig) *VoltVnet {
159 var vv VoltVnet
160 vv.VnetConfig = cfg
161 if vv.PendingDeleteFlow == nil {
162 vv.PendingDeleteFlow = make(map[string]map[string]bool)
163 }
164 vv.DeleteInProgress = false
165 if cfg.Encapsulation == EncapsulationPPPoEIA {
166 vv.PppoeIa = true
167 }
168 vv.AssociatedPorts = make(map[string]bool)
169 return &vv
170}
171
vinokuma926cb3e2023-03-29 11:41:06 +0530172// associatePortToVnet - associate a port to Vnet
Naveen Sampath04696f72022-06-13 15:19:14 +0530173func (vv *VoltVnet) associatePortToVnet(port string) {
174 vv.VnetPortLock.Lock()
175 if vv.AssociatedPorts == nil {
176 vv.AssociatedPorts = make(map[string]bool)
177 }
178 vv.AssociatedPorts[port] = true
179 vv.VnetPortLock.Unlock()
180}
181
vinokuma926cb3e2023-03-29 11:41:06 +0530182// disassociatePortFromVnet - disassociate a port from Vnet and return true if the association map is empty
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530183func (vv *VoltVnet) disassociatePortFromVnet(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530184 vv.VnetPortLock.Lock()
185 delete(vv.AssociatedPorts, port)
186 logger.Infow(ctx, "Disassociated Port from Vnet", log.Fields{"Device": device, "Port": port, "Vnet": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow, "AssociatedPorts": vv.AssociatedPorts, "DeleteFlag": vv.DeleteInProgress})
187 vv.VnetPortLock.Unlock()
188
189 if vv.DeleteInProgress {
190 if !vv.isAssociatedPortsPresent() {
191 if len(vv.PendingDeleteFlow[device]) == 0 {
192 logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vv.Name})
193 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530194 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530195 } else {
196 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow})
197 }
198 } else {
199 vv.VnetPortLock.RLock()
200 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts})
201 vv.VnetPortLock.RUnlock()
202 }
203 }
204}
205
206func (vv *VoltVnet) isAssociatedPortsPresent() bool {
207 vv.VnetPortLock.RLock()
208 defer vv.VnetPortLock.RUnlock()
209 return len(vv.AssociatedPorts) != 0
210}
211
212// WriteToDb commit the VNET to the database
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530213func (vv *VoltVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530214 if vv.DeleteInProgress {
215 logger.Warnw(ctx, "Skipping Redis Update for Vnet, Vnet delete in progress", log.Fields{"Vnet": vv.Name})
216 return
217 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530218 vv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530219}
220
vinokuma926cb3e2023-03-29 11:41:06 +0530221// ForceWriteToDb force commit a vnet to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530222func (vv *VoltVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530223 vv.VnetPortLock.RLock()
224 defer vv.VnetPortLock.RUnlock()
225 vv.Version = database.PresentVersionMap[database.VnetPath]
226 logger.Debugw(ctx, "Updating VNET....", log.Fields{"vnet": vv})
227 if b, err := json.Marshal(vv); err == nil {
Akash Sonia8246972023-01-03 10:37:08 +0530228 if err := db.PutVnet(cntx, vv.Name, string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530229 logger.Warnw(ctx, "Add Vnet to DB failed", log.Fields{"vnet name": vv.Name, "Error": err})
230 }
231 }
232}
233
234// VnetKey creates the key using the two VLAN tags
235// We append the two VLAN tags to create a single key
236func VnetKey(otag of.VlanType, itag of.VlanType, utag of.VlanType) string {
237 return strconv.Itoa(int(otag)) + "-" + strconv.Itoa(int(itag)) + "-" + strconv.Itoa(int(utag))
238}
239
240// GetVnet get VNET configuration related functionality associated with VOLT application
241func (va *VoltApplication) GetVnet(otag of.VlanType, itag of.VlanType, utag of.VlanType) *VoltVnet {
242 // When matching VNET, it is expected to match first just the outer
243 // tag, and then the combination to make sure there is no conflict
244 // for the new configuration.
245 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, of.VlanNone, utag)); ok {
246 return vnet.(*VoltVnet)
247 }
248 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, itag, utag)); ok {
249 return vnet.(*VoltVnet)
250 }
251 return nil
252}
253
254// The VNET may also be assigned name for easier references. For now,
255// the VNET is mainly identified by the two VLANs.
256
257// GetVnetByName to get vnet by name
258func (va *VoltApplication) GetVnetByName(name string) *VoltVnet {
259 if vnet, ok := va.VnetsByName.Load(name); ok {
260 return vnet.(*VoltVnet)
261 }
262 return nil
263}
264
265// storeVnetConfig to store vnet config
266func (va *VoltApplication) storeVnetConfig(cfg VnetConfig, vv *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530267 var vnetMap *util.ConcurrentMap
268
269 va.VnetsByTag.Store(VnetKey(cfg.SVlan, cfg.CVlan, cfg.UniVlan), vv)
270 va.VnetsByName.Store(cfg.Name, vv)
271
272 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vv.SVlan); !ok {
273 vnetMap = util.NewConcurrentMap()
274 } else {
275 vnetMap = vnetMapIntf.(*util.ConcurrentMap)
276 }
277 vnetMap.Set(vv, true)
278 va.VnetsBySvlan.Set(vv.SVlan, vnetMap)
279}
280
281// deleteVnetConfig to delete vnet config
282func (va *VoltApplication) deleteVnetConfig(vnet *VoltVnet) {
283 va.VnetsByTag.Delete(VnetKey(vnet.SVlan, vnet.CVlan, vnet.UniVlan))
284 va.VnetsByName.Delete(vnet.Name)
285
286 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vnet.SVlan); ok {
287 vnetMap := vnetMapIntf.(*util.ConcurrentMap)
288 vnetMap.Remove(vnet)
289 va.VnetsBySvlan.Set(vnet.SVlan, vnetMap)
290 }
291}
292
293// AddVnet to add a VNET to the list of VNETs configured.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530294func (va *VoltApplication) AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530295 AppMutex.VnetMutex.Lock()
296 var vv *VoltVnet
297 devicesToHandle := []string{}
298 vv = va.GetVnetByName(cfg.Name)
299 if vv != nil {
300 //Could be for another OLT or could be case of backup-restore
301 for _, serialNum := range cfg.DevicesList {
302 if isDeviceInList(serialNum, vv.DevicesList) {
303 //This is backup restore scenario, just update the profile
304 logger.Info(ctx, "Add Vnet : Profile Name already exists with OLT, update-the-profile")
305 continue
306 }
307 devicesToHandle = append(devicesToHandle, serialNum)
308 }
309 if len(devicesToHandle) == 0 {
Tinoj Joseph1d108322022-07-13 10:07:39 +0530310 logger.Debugw(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530311 AppMutex.VnetMutex.Unlock()
312 return nil
313 }
314 }
315
316 if vv == nil {
317 vv = NewVoltVnet(cfg)
318 if oper != nil {
319 vv.PendingDeleteFlow = oper.PendingDeleteFlow
320 vv.DeleteInProgress = oper.DeleteInProgress
321 vv.AssociatedPorts = oper.AssociatedPorts
322 vv.PendingDeviceToDelete = oper.PendingDeviceToDelete
323 }
324 devicesToHandle = append(devicesToHandle, cfg.DevicesList...)
325 } else {
326 vv.DevicesList = append(vv.DevicesList, devicesToHandle...)
327 }
328
329 va.storeVnetConfig(cfg, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530330 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530331
332 logger.Infow(ctx, "Added VNET TO DB", log.Fields{"cfg": cfg, "devicesToHandle": devicesToHandle})
333
334 //va.PushDevFlowForVlan(vv)
335 AppMutex.VnetMutex.Unlock()
336 return nil
337}
338
339// DelVnet to delete a VNET from the list of VNETs configured
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530340func (va *VoltApplication) DelVnet(cntx context.Context, name, deviceSerialNum string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530341 logger.Infow(ctx, "Deleting Vnet", log.Fields{"Vnet": name})
342 AppMutex.VnetMutex.Lock()
343 if vnetIntf, ok := va.VnetsByName.Load(name); ok {
344 vnet := vnetIntf.(*VoltVnet)
vinokuma926cb3e2023-03-29 11:41:06 +0530345 // Delete from mvp list
Naveen Sampath04696f72022-06-13 15:19:14 +0530346 vnet.DevicesList = util.RemoveFromSlice(vnet.DevicesList, deviceSerialNum)
347
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530348 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, deviceSerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +0530349 if len(vnet.DevicesList) == 0 {
350 vnet.DeleteInProgress = true
351 vnet.PendingDeviceToDelete = deviceSerialNum
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530352 vnet.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530353 vnet.VnetPortLock.RLock()
354 if len(vnet.PendingDeleteFlow) == 0 && !vnet.isAssociatedPortsPresent() {
355 logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
356 va.deleteVnetConfig(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530357 _ = db.DelVnet(cntx, vnet.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530358 } else {
359 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
360 }
361 vnet.VnetPortLock.RUnlock()
362 } else {
vinokuma926cb3e2023-03-29 11:41:06 +0530363 // Update the devicelist in db
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530364 vnet.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530365 }
366 }
vinokuma926cb3e2023-03-29 11:41:06 +0530367 // TODO: if no vnets are present on device remove icmpv6 group from device
Naveen Sampath04696f72022-06-13 15:19:14 +0530368 AppMutex.VnetMutex.Unlock()
369 return nil
370}
371
372// UpdateVnet to update the VNET with associated service count
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530373func (va *VoltApplication) UpdateVnet(cntx context.Context, vv *VoltVnet) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530374 va.storeVnetConfig(vv.VnetConfig, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530375 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530376 logger.Infow(ctx, "Updated VNET TO DB", log.Fields{"vv": vv.VnetConfig})
377 return nil
378}
379
380// ------------------------------------------------------------
381// Manifestation of a VNET on a port is handled below
382// ------------------------------------------------------------
383//
384// The VNET on a port handles everything that is done for a VNET
385// such as DHCP relay state machine, MAC addresses, IP addresses
386// learnt, so on.
387
388// DhcpStatus type
389type DhcpStatus uint8
390
391const (
392 // DhcpStatusNone constant
393 DhcpStatusNone DhcpStatus = 0
394 // DhcpStatusAcked constant
395 DhcpStatusAcked DhcpStatus = 1
396 // DhcpStatusNacked constant
397 DhcpStatusNacked DhcpStatus = 2
398 // EthTypeNone constant
399 EthTypeNone int = 0
400 // EthTypeIPoE constant
401 EthTypeIPoE int = 1
402 // EthTypePPPoE constant
403 EthTypePPPoE int = 2
404)
405
406// VoltPortVnet structure
407type VoltPortVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530408 PendingDeleteFlow map[string]bool
409 servicesCount *atomic.Uint64
410 services sync.Map
Naveen Sampath04696f72022-06-13 15:19:14 +0530411 Device string
412 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +0530413 VnetName string
vinokuma926cb3e2023-03-29 11:41:06 +0530414 VnetType string
415 MvlanProfileName string
416 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530417 DhcpExpiryTime time.Time
418 Dhcp6ExpiryTime time.Time
Naveen Sampath04696f72022-06-13 15:19:14 +0530419 Ipv4Addr net.IP
420 Ipv6Addr net.IP
421 MacAddr net.HardwareAddr
422 LearntMacAddr net.HardwareAddr
vinokuma926cb3e2023-03-29 11:41:06 +0530423 CircuitID []byte //Will not be used
424 RemoteID []byte //Will not be used
425 VpvLock sync.Mutex `json:"-"`
426 PendingFlowLock sync.RWMutex `json:"-"`
427 SchedID int
Naveen Sampath04696f72022-06-13 15:19:14 +0530428 ONTEtherTypeClassification int
vinokuma926cb3e2023-03-29 11:41:06 +0530429 MacLearning MacLearningType
430 PonPort uint32
431 McastUsMeterID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530432 McastTechProfileID uint16
433 McastPbit of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530434 SVlanTpid layers.EthernetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530435 DhcpPbit of.PbitType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530436 UsPonCTagPriority of.PbitType
437 UsPonSTagPriority of.PbitType
438 DsPonCTagPriority of.PbitType
439 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530440 SVlan of.VlanType
441 CVlan of.VlanType
442 UniVlan of.VlanType
443 VlanControl VlanControl
444 RelayState DhcpRelayState
445 DhcpStatus DhcpStatus
446 PPPoeState PppoeIaState
447 RelayStatev6 Dhcpv6RelayState
448 DHCPv6DUID [MaxLenDhcpv6DUID]byte
449 DhcpRelay bool
450 ArpRelay bool
451 PppoeIa bool
452 DeleteInProgress bool
453 Blocked bool
454 AllowTransparent bool
455 IgmpEnabled bool
456 IgmpFlowsApplied bool
457 McastService bool
458 FlowsApplied bool
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530459 IsOption82Enabled bool //Will not be used
Naveen Sampath04696f72022-06-13 15:19:14 +0530460}
461
vinokuma926cb3e2023-03-29 11:41:06 +0530462// VlanControl vlan control type
Naveen Sampath04696f72022-06-13 15:19:14 +0530463type VlanControl uint8
464
465const (
466 // None constant
467 // ONU and OLT will passthrough UNIVLAN as is to BNG
468 None VlanControl = iota
469
470 // ONUCVlanOLTSVlan constant
471 // Tagged traffic, ONU will replace UNIVLAN with CVLAN and OLT will add SVLAN
472 // Untagged traffic, ONU will add CVLAN and OLT will add SVLAN
473 ONUCVlanOLTSVlan
474
475 // OLTCVlanOLTSVlan constant
476 // Tagged traffic, ONU will passthrough UNIVLAN as is to OLT and
477 // OLT will replace UNIVLAN with CVLAN and add SVLAN
478 OLTCVlanOLTSVlan
479
480 // ONUCVlan constant
481 // Tagged traffic, ONU will replace UNIVLAN with CVLAN
482 // Untagged traffic, ONU will add CVLAN
483 ONUCVlan
484
485 // OLTSVlan constant
486 // UnTagged traffic, OLT will add the SVLAN
487 OLTSVlan
488)
489
490// NewVoltPortVnet is constructor for VoltPortVnet
491func NewVoltPortVnet(vnet *VoltVnet) *VoltPortVnet {
492 var vpv VoltPortVnet
493
494 vpv.VnetName = vnet.Name
495 vpv.SVlan = vnet.SVlan
496 vpv.CVlan = vnet.CVlan
497 vpv.UniVlan = vnet.UniVlan
498 vpv.SVlanTpid = vnet.SVlanTpid
499 vpv.DhcpRelay = vnet.DhcpRelay
500 vpv.DhcpStatus = DhcpStatusNone
501 vpv.PPPoeState = PppoeIaStateNone
502 vpv.ArpRelay = vnet.ArpLearning
503 vpv.PppoeIa = vnet.PppoeIa
504 vpv.VlanControl = vnet.VlanControl
505 vpv.ONTEtherTypeClassification = vnet.ONTEtherTypeClassification
506 vpv.AllowTransparent = vnet.AllowTransparent
507 vpv.FlowsApplied = false
508 vpv.IgmpEnabled = false
509 vpv.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
510 vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Naveen Sampath04696f72022-06-13 15:19:14 +0530511 vpv.servicesCount = atomic.NewUint64(0)
512 vpv.SchedID = 0
513 vpv.PendingDeleteFlow = make(map[string]bool)
514 vpv.DhcpPbit = vnet.UsDhcpPbit[0]
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530515 vpv.UsPonCTagPriority = vnet.UsPonCTagPriority
516 vpv.UsPonSTagPriority = vnet.UsPonSTagPriority
517 vpv.DsPonCTagPriority = vnet.UsPonCTagPriority
518 vpv.DsPonSTagPriority = vnet.UsPonSTagPriority
519
520 vpv.VnetType = vnet.VnetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530521 return &vpv
522}
523
524func (vpv *VoltPortVnet) setDevice(device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530525 if vpv.Device != device && vpv.Device != "" {
526 GetApplication().DisassociateVpvsFromDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530527 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530528 vpv.printAssociatedVPVs(false)
529 }
530
Tinoj Josephec742f62022-09-29 19:11:10 +0530531 logger.Infow(ctx, "Associating VPV and Device", log.Fields{"Device": device, "Port": vpv.Port, "SVlan": vpv.SVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530532
533 vpv.Device = device
534 GetApplication().AssociateVpvsToDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530535 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530536 vpv.printAssociatedVPVs(true)
537}
538
vinokuma926cb3e2023-03-29 11:41:06 +0530539// TODO - Nav - Temp
Naveen Sampath04696f72022-06-13 15:19:14 +0530540func (vpv *VoltPortVnet) printAssociatedVPVs(add bool) {
541 logger.Infow(ctx, "Start----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
542 if vMap := GetApplication().GetAssociatedVpvsForDevice(vpv.Device, vpv.SVlan); vMap != nil {
543 vMap.Range(func(key, value interface{}) bool {
544 vpvEntry := key.(*VoltPortVnet)
545 logger.Infow(ctx, "Associated VPVs", log.Fields{"SVlan": vpvEntry.SVlan, "CVlan": vpvEntry.CVlan, "UniVlan": vpvEntry.UniVlan})
546 return true
547 })
548 }
549 logger.Infow(ctx, "End----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
Naveen Sampath04696f72022-06-13 15:19:14 +0530550}
551
552// GetCircuitID : The interface to be satisfied by the VoltPortVnet to be a DHCP relay
553// session is implemented below. The main functions still remain in
554// the service.go file.
555func (vpv *VoltPortVnet) GetCircuitID() []byte {
556 return []byte(vpv.CircuitID)
557}
558
559// GetRemoteID to get remote id
560func (vpv *VoltPortVnet) GetRemoteID() []byte {
561 return []byte(vpv.RemoteID)
562}
563
564// GetDhcpState to get dhcp state
565func (vpv *VoltPortVnet) GetDhcpState() DhcpRelayState {
566 return vpv.RelayState
567}
568
569// SetDhcpState to set the dhcp state
570func (vpv *VoltPortVnet) SetDhcpState(state DhcpRelayState) {
571 vpv.RelayState = state
572}
573
574// GetPppoeIaState to get pppoeia state
575func (vpv *VoltPortVnet) GetPppoeIaState() PppoeIaState {
576 return vpv.PPPoeState
577}
578
579// SetPppoeIaState to set pppoeia state
580func (vpv *VoltPortVnet) SetPppoeIaState(state PppoeIaState) {
581 vpv.PPPoeState = state
582}
583
584// GetDhcpv6State to get dhcpv6 state
585func (vpv *VoltPortVnet) GetDhcpv6State() Dhcpv6RelayState {
586 return vpv.RelayStatev6
587}
588
589// SetDhcpv6State to set dhcpv6 state
590func (vpv *VoltPortVnet) SetDhcpv6State(state Dhcpv6RelayState) {
591 vpv.RelayStatev6 = state
592}
593
594// DhcpResultInd for dhcp result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530595func (vpv *VoltPortVnet) DhcpResultInd(cntx context.Context, res *layers.DHCPv4) {
596 vpv.ProcessDhcpResult(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530597}
598
599// Dhcpv6ResultInd for dhcpv6 result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530600func (vpv *VoltPortVnet) Dhcpv6ResultInd(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
601 vpv.ProcessDhcpv6Result(cntx, ipv6Addr, leaseTime)
Naveen Sampath04696f72022-06-13 15:19:14 +0530602}
603
604// GetNniVlans to get nni vlans
605func (vpv *VoltPortVnet) GetNniVlans() (uint16, uint16) {
606 switch vpv.VlanControl {
607 case ONUCVlanOLTSVlan,
608 OLTCVlanOLTSVlan:
609 return uint16(vpv.SVlan), uint16(vpv.CVlan)
610 case ONUCVlan,
611 None:
612 return uint16(vpv.SVlan), uint16(of.VlanNone)
613 case OLTSVlan:
614 return uint16(vpv.SVlan), uint16(of.VlanNone)
615 }
616 return uint16(of.VlanNone), uint16(of.VlanNone)
617}
618
619// GetService to get service
620func (vpv *VoltPortVnet) GetService(name string) (*VoltService, bool) {
621 service, ok := vpv.services.Load(name)
622 if ok {
623 return service.(*VoltService), ok
624 }
625 return nil, ok
626}
627
628// AddService to add service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530629func (vpv *VoltPortVnet) AddService(cntx context.Context, service *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530630 vpv.services.Store(service.Name, service)
631 vpv.servicesCount.Inc()
632 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()})
633}
634
635// DelService to delete service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530636func (vpv *VoltPortVnet) DelService(cntx context.Context, service *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530637 vpv.services.Delete(service.Name)
638 vpv.servicesCount.Dec()
639
640 // If the only Igmp Enabled service is removed, remove the Igmp trap flow along with it
641 if service.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530642 if err := vpv.DelIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530643 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530644 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
645 }
646
647 vpv.IgmpEnabled = false
648 }
649 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()})
650}
651
652// ProcessDhcpResult to process dhcp results
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530653func (vpv *VoltPortVnet) ProcessDhcpResult(cntx context.Context, res *layers.DHCPv4) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530654 msgType := DhcpMsgType(res)
655 if msgType == layers.DHCPMsgTypeAck {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530656 vpv.ProcessDhcpSuccess(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530657 } else if msgType == layers.DHCPMsgTypeNak {
658 vpv.DhcpStatus = DhcpStatusNacked
659 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530660 vpv.WriteToDb(cntx)
661}
662
663// RangeOnServices to call a function on all services on the vpv
664func (vpv *VoltPortVnet) RangeOnServices(cntx context.Context, callback func(cntx context.Context, key, value interface{}) bool) {
665 vpv.services.Range(func(key, value interface{}) bool {
666 return callback(cntx, key, value)
667 })
Naveen Sampath04696f72022-06-13 15:19:14 +0530668}
669
670// ProcessDhcpSuccess : Learn the IPv4 address allocated to the services and update the
671// the services with the same. This also calls for adding flows
672// for the services as the DHCP procedure is completed
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530673func (vpv *VoltPortVnet) ProcessDhcpSuccess(cntx context.Context, res *layers.DHCPv4) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530674 vpv.DhcpStatus = DhcpStatusAcked
675 vpv.Ipv4Addr, _ = GetIpv4Addr(res)
676 logger.Infow(ctx, "Received IPv4 Address", log.Fields{"IP Address": vpv.Ipv4Addr.String()})
677 logger.Infow(ctx, "Services Configured", log.Fields{"Count": vpv.servicesCount.Load()})
678
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530679 vpv.RangeOnServices(cntx, vpv.updateIPv4AndProvisionFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530680 vpv.ProcessDhcpv4Options(res)
681}
682
683// ProcessDhcpv4Options : Currently we process lease time and store the validity of the
684// IP address allocated.
685func (vpv *VoltPortVnet) ProcessDhcpv4Options(res *layers.DHCPv4) {
686 for _, o := range res.Options {
687 switch o.Type {
688 case layers.DHCPOptLeaseTime:
689 leasetime := GetIPv4LeaseTime(o)
690 vpv.DhcpExpiryTime = time.Now().Add((time.Duration(leasetime) * time.Second))
691 logger.Infow(ctx, "Lease Expiry Set", log.Fields{"Time": vpv.DhcpExpiryTime})
692 }
693 }
694}
695
696// ProcessDhcpv6Result : Read the IPv6 address allocated to the device and store it on the
697// VNET. The same IPv6 address is also passed to the services. When a
698// service is fetched all the associated information such as MAC address,
699// IPv4 address and IPv6 addresses can be provided.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530700func (vpv *VoltPortVnet) ProcessDhcpv6Result(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530701 // TODO: Status based hanlding of flows
702 vpv.Dhcp6ExpiryTime = time.Now().Add((time.Duration(leaseTime) * time.Second))
703 vpv.Ipv6Addr = ipv6Addr
704
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530705 vpv.RangeOnServices(cntx, vpv.updateIPv6AndProvisionFlows)
706 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530707}
708
709// AddSvcUsMeterToDevice to add service upstream meter info to device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530710func AddSvcUsMeterToDevice(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +0530711 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +0530712 logger.Infow(ctx, "Adding upstream meter profile to device", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530713 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
714 GetApplication().AddMeterToDevice(svc.Port, device.Name, svc.UsMeterID, 0)
715 return true
716 }
717 logger.Errorw(ctx, "Dropping US Meter request: Device not found", log.Fields{"Service": svc})
718 return false
719}
720
721// PushFlowsForPortVnet - triggers flow construction and push for provided VPV
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530722func (vpv *VoltPortVnet) PushFlowsForPortVnet(cntx context.Context, d *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530723 vp := d.GetPort(vpv.Port)
724
725 //Ignore if UNI port is not found or not UP
726 if vp == nil || vp.State != PortStateUp {
727 logger.Warnw(ctx, "Ignoring Vlan UP Ind for VPV: Port Not Found/Ready", log.Fields{"Port": vp})
728 return
729 }
730
Naveen Sampath04696f72022-06-13 15:19:14 +0530731 //Disable the flag so that flows can be pushed again
732 // vpv.IgmpFlowsApplied = false
733 // vpv.DsFlowsApplied = false
734 // vpv.UsFlowsApplied = false
735 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530736 vpv.PortUpInd(cntx, d, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530737 vpv.VpvLock.Unlock()
738}
739
740// PortUpInd : When a port transistions to UP state, the indication is passed
741// on to this module via the application. We read the VNET configuration
742// again here to apply the latest configuration if the configuration
743// changed. Thus, a reboot of ONT forces the new configuration to get
744// applied.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530745func (vpv *VoltPortVnet) PortUpInd(cntx context.Context, device *VoltDevice, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530746 if vpv.DeleteInProgress {
747 logger.Errorw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
748 return
749 }
750 vpv.setDevice(device.Name)
751 logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
752
753 nni, _ := GetApplication().GetNniPort(device.Name)
754 if nni == "" {
755 logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name})
756 return
757 }
758
Akash Sonia8246972023-01-03 10:37:08 +0530759 if nniPort := device.GetPort(nni); nniPort != nil {
760 //If NNI port is not mached to nb nni port dont send flows
761 devConfig := GetApplication().GetDeviceConfig(device.SerialNum)
762 if devConfig != nil {
Akash Soni53da2852023-03-15 00:31:31 +0530763 if devConfig.UplinkPort != strconv.Itoa(int(nniPort.ID)) {
764 logger.Errorw(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 +0530765 return
766 }
767 }
768 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530769
Naveen Sampath04696f72022-06-13 15:19:14 +0530770 if vpv.Blocked {
771 logger.Errorw(ctx, "VPV Bocked for Processing. Ignoring flow push request", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
772 return
773 }
774
775 if vpv.DhcpRelay || vpv.ArpRelay || vpv.PppoeIa {
776 // If MAC Learning is true if no MAC is configured, push DS/US DHCP, US HSIA flows without MAC.
777 // DS HSIA flows are installed after learning the MAC.
778 logger.Infow(ctx, "Port Up - Trap Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530779 // no HSIA flows for multicast service and DPU_MGMT Service
vinokuma926cb3e2023-03-29 11:41:06 +0530780 if !vpv.McastService && vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530781 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530782 }
vinokuma926cb3e2023-03-29 11:41:06 +0530783 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530784 vpv.RangeOnServices(cntx, AddMeterToDevice)
785 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530786 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530787 if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
788 logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530789 /*In case of DPU_MGMT_TRAFFIC, need to install both US and DS traffic */
vinokuma926cb3e2023-03-29 11:41:06 +0530790 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530791 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
792 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530793 // US & DS DHCP, US HSIA flows are already installed
794 // install only DS HSIA flow here.
795 // no HSIA flows for multicast service
Akash Soni53da2852023-03-15 00:31:31 +0530796 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530797 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530798 }
799 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530800 } else {
801 // DHCP relay is not configured. This implies that the service must use
802 // 1:1 and does not require MAC learning. In a completely uncommon but
803 // plausible case, the MAC address can be learnt from N:1 without DHCP
804 // relay by configuring any unknown MAC address to be reported. This
805 // however is not seen as a real use case.
806 logger.Infow(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
807 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530808 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530809 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530810 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530811 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530812 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530813 }
814 }
815
816 // Process IGMP proxy - install IGMP trap rules before DHCP trap rules
817 if vpv.IgmpEnabled {
818 logger.Infow(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530819 vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice)
820 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530821 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530822 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
823 }
824
825 if vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530826 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +0530827 }
828 }
829
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530830 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530831}
832
833// PortDownInd : When the port status changes to down, we delete all configured flows
834// The same indication is also passed to the services enqueued for them
835// to take appropriate actions
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530836func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool) {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530837 if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
838 logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
839 return
840 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530841 logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
842 log.Fields{"service count": vpv.servicesCount.Load()})
843
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530844 //vpv.RangeOnServices(cntx, DelAllFlows)
845 vpv.DelTrapFlows(cntx)
846 vpv.DelHsiaFlows(cntx)
847 vpv.WriteToDb(cntx)
848 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530849}
850
851// SetMacAddr : The MAC address is set when a MAC address is learnt through the
852// packets received from the network. Currently, DHCP packets are
853// only packets we learn the MAC address from
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530854func (vpv *VoltPortVnet) SetMacAddr(cntx context.Context, addr net.HardwareAddr) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530855 //Store Learnt MAC address and return if MACLearning is not enabled
856 vpv.LearntMacAddr = addr
857 if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
858 (NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
859 return
860 }
861
862 // Compare the two MAC addresses to see if it is same
863 // If they are same, we just return. If not, we perform
864 // actions to address the change in MAC address
865 //if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
866 if !util.MacAddrsMatch(vpv.MacAddr, addr) {
867 expectedPort := GetApplication().GetMacInPortMap(addr)
868 if expectedPort != "" && expectedPort != vpv.Port {
869 logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
870 log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
871 return
872 }
873 if NonZeroMacAddress(vpv.MacAddr) {
874 logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
875
876 // The newly learnt MAC address is different than earlier one.
877 // The existing MAC based HSIA flows need to be undone as the device
878 // may have been changed
879 // Atleast one HSIA flow should be present in adapter to retain the TP and GEM
880 // hence delete one after the other
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530881 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530882 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530883 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
884 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
885 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530886 GetApplication().DeleteMacInPortMap(vpv.MacAddr)
887 } else {
888 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530889 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
Naveen Sampath04696f72022-06-13 15:19:14 +0530890 logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
891 }
892 GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
893 } else {
894 logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
895 }
896
897 _, err := GetApplication().GetDeviceFromPort(vpv.Port)
898 if err != nil {
899 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
Akash Sonia8246972023-01-03 10:37:08 +0530900 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530901 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
902 return
903 }
904 // Ds Hsia flows has to be pushed
905 if vpv.FlowsApplied {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530906 // In case of DPU_MGMT_TRAFFIC install both US and DS Flows
vinokuma926cb3e2023-03-29 11:41:06 +0530907 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530908 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
909 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530910 // no HSIA flows for multicast service
911 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530912 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530913 }
914 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530915 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530916}
917
918// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
919func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
920 if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
921 return false
922 }
923 return true
924}
925
926// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
927func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
928 if len(cvlan) != 1 && !vpv.AllowTransparent {
929 return false
930 }
931 if vpv.CVlan != cvlan[0] {
932 return false
933 }
934 return true
935}
936
937// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
938func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +0530939 var service *VoltService
940 pbitFound := false
941 matchpbitsFunc := func(key, value interface{}) bool {
942 svc := value.(*VoltService)
943 for _, pbit := range svc.Pbits {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530944 if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530945 logger.Infow(ctx, "Pbit match found with service",
946 log.Fields{"Pbit": priority, "serviceName": svc.Name})
947 pbitFound = true
948 service = svc
949 return false //Returning false to stop the Range loop
950 }
951 }
952 return true
953 }
954 _ = pbitFound
955 vpv.services.Range(matchpbitsFunc)
956 return service
957}
958
959// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
960func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Naveen Sampath04696f72022-06-13 15:19:14 +0530961 dsPbit := uint8(0)
962 matchpbitsFunc := func(key, value interface{}) bool {
963 svc := value.(*VoltService)
964 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
965 logger.Infow(ctx, "Pbit match found with service",
966 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
967 dsPbit = uint8(remarkPbit)
968 return false //Returning false to stop the Range loop
969 }
970 // When no remarking info is available, remark the incoming pbit
971 // to highest pbit configured for the subscriber (across all subservices associated)
972 svcPbit := uint8(svc.Pbits[0])
973 if svcPbit > dsPbit {
974 dsPbit = svcPbit
975 }
976 return true
977 }
978 vpv.services.Range(matchpbitsFunc)
979 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
980 return dsPbit
981}
982
983// AddSvc adds a service on the VNET on a port. The addition is
984// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530985func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530986 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530987 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +0530988 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
989
990 // Learn the circuit-id and remote-id from the service
991 // TODO: There must be a better way of doing this. This
992 // may be explored
993 if svc.IgmpEnabled {
994 vpv.IgmpEnabled = true
995 }
996 // first time service activation MacLearning will have default value as None.
997 // to handle reciliency if anythng other then None we should retain it .
998 if svc.MacLearning == MacLearningNone {
999 if !vpv.DhcpRelay && !vpv.ArpRelay {
1000 svc.MacLearning = MacLearningNone
1001 } else if vpv.MacLearning == Learn {
1002 svc.MacLearning = Learn
1003 } else if vpv.MacLearning == ReLearn {
1004 svc.MacLearning = ReLearn
1005 }
1006 }
1007
vinokuma926cb3e2023-03-29 11:41:06 +05301008 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301009 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1010 svc.MacAddr = vpv.MacAddr
1011 } else if vpv.servicesCount.Load() == 1 {
1012 vpv.MacAddr = svc.MacAddr
1013 }
1014
1015 vpv.MacLearning = svc.MacLearning
1016 vpv.PonPort = svc.PonPort
1017 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301018 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301019 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301020 if svc.McastService {
1021 vpv.McastService = true
1022 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301023 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301024 vpv.McastPbit = svc.Pbits[0]
1025 vpv.McastUsMeterID = svc.UsMeterID
1026 vpv.SchedID = svc.SchedID
1027 }
1028 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1029 svc.AllowTransparent = vpv.AllowTransparent
1030 svc.SVlanTpid = vpv.SVlanTpid
1031
vinokuma926cb3e2023-03-29 11:41:06 +05301032 // Ensure configuring the mvlan profile only once
1033 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301034 if svc.MvlanProfileName != "" {
1035 if vpv.MvlanProfileName == "" {
1036 vpv.MvlanProfileName = svc.MvlanProfileName
1037 } else {
1038 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1039 }
1040 }
1041
Akash Sonia8246972023-01-03 10:37:08 +05301042 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301043 if err != nil {
1044 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301045 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1046 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301047 return
1048 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301049 if !svc.IsActivated {
1050 logger.Warn(ctx, "Not pushing Service Flows: Service Not activated")
1051 return
1052 }
Akash Sonia8246972023-01-03 10:37:08 +05301053
vinokuma926cb3e2023-03-29 11:41:06 +05301054 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301055 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1056
Akash Soni53da2852023-03-15 00:31:31 +05301057 if devConfig.UplinkPort != voltDevice.NniPort {
1058 logger.Errorw(ctx, "NNI port mismatch", log.Fields{"NB NNI Port": devConfig.UplinkPort, "SB NNI port": voltDevice.NniPort})
Akash Sonia8246972023-01-03 10:37:08 +05301059 return
1060 }
vinokuma926cb3e2023-03-29 11:41:06 +05301061 // Push Service Flows if DHCP relay is not configured
1062 // or already DHCP flows are configured for the VPV
1063 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301064 if vpv.FlowsApplied {
1065 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301066 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301067 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301068 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301069 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1070 }
1071 }
1072 }
1073
vinokuma926cb3e2023-03-29 11:41:06 +05301074 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301075 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1076 // service with Igmp Enabled needs to be installed
1077 if svc.IgmpEnabled && vpv.FlowsApplied {
1078 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301079 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301080 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301081 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1082 }
1083
1084 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301085 // For McastService, send Service Activated indication once IGMP US flow is pushed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301086 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +05301087 }
1088 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301089 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301090}
1091
1092// setLearntMAC to set learnt mac
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301093func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301094 svc := value.(*VoltService)
1095 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301096 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301097 return true
1098}
1099
1100// PostAccessConfigSuccessInd for posting access config success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301101func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301102 return true
1103}
1104
1105// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301106func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301107 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301108 logger.Infow(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301109 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301110 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301111
1112 return true
1113}
1114
1115// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301116func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301117 svc := value.(*VoltService)
1118 svc.SetIpv6Addr(vpv.Ipv6Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301119 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301120
1121 return true
1122}
1123
1124// AddUsHsiaFlows to add upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301125func AddUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301126 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301127 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301128 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1129 }
1130 return true
1131}
1132
1133// AddDsHsiaFlows to add downstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301134func AddDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301135 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301136 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301137 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1138 }
1139 return true
1140}
1141
1142// ClearFlagsInService to clear the flags used in service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301143func ClearFlagsInService(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301144 svc := value.(*VoltService)
1145 svc.ServiceLock.Lock()
1146 svc.IgmpFlowsApplied = false
1147 svc.DsDhcpFlowsApplied = false
1148 svc.DsHSIAFlowsApplied = false
1149 svc.Icmpv6FlowsApplied = false
1150 svc.UsHSIAFlowsApplied = false
1151 svc.UsDhcpFlowsApplied = false
1152 svc.PendingFlows = make(map[string]bool)
1153 svc.AssociatedFlows = make(map[string]bool)
1154 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301155 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301156 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1157 return true
1158}
1159
1160// DelDsHsiaFlows to delete hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301161func DelDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301162 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301163 if err := svc.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301164 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1165 }
1166 return true
1167}
1168
1169// DelUsHsiaFlows to delete upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301170func DelUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301171 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301172 if err := svc.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301173 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1174 }
1175 return true
1176}
1177
1178// ClearServiceCounters to clear the service counters
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301179func ClearServiceCounters(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301180 svc := value.(*VoltService)
1181 //Delete the per service counter too
1182 GetApplication().ServiceCounters.Delete(svc.Name)
1183 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301184 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301185 }
1186 return true
1187}
1188
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301189// AddMeterToDevice to add meter config to device, used in FTTB case
1190func AddMeterToDevice(cntx context.Context, key, value interface{}) bool {
1191 svc := value.(*VoltService)
Akash Soni53da2852023-03-15 00:31:31 +05301192 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301193 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1194 }
1195 return true
1196}
1197
vinokuma926cb3e2023-03-29 11:41:06 +05301198// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301199func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301200 if !vpv.FlowsApplied || vgcRebooted {
1201 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301202 if err := vpv.AddUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301203 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301204 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1205 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301206 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301207 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301208 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1209 }
1210 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1211 log.Fields{"port": vpv.Port})
1212 //vpv.updateICMPv6McGroup(true)
1213 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301214 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301215 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301216 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1217 }
1218 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301219 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301220 if err := vpv.AddUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301221 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301222 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1223 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301224 if err := vpv.AddDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301225 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301226 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1227 }
1228 }
1229 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301230 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301231 }
1232}
1233
vinokuma926cb3e2023-03-29 11:41:06 +05301234// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301235func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301236 // Delete HSIA & DHCP flows before deleting IGMP flows
1237 if vpv.FlowsApplied || vgcRebooted {
1238 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301239 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301240 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1241 "UniVlan": vpv.UniVlan, "Error": err})
1242 }
1243 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1244 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301245 if err := vpv.DelDsDhcpFlows(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 //vpv.updateICMPv6McGroup(false)
1250 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301251 if err := vpv.DelUsArpFlows(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 }
1255 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301256 if err := vpv.DelUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301257 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301258 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1259 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301260 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301261 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301262 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1263 }
1264 }
1265 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301266 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301267 }
Akash Sonia8246972023-01-03 10:37:08 +05301268 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301269 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1270 "UniVlan": vpv.UniVlan, "Error": err})
1271 }
1272}
1273
1274// DelHsiaFlows deletes the service flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301275func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301276 // no HSIA flows for multicast service
1277 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301278 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
1279 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301280 }
1281}
1282
vinokuma926cb3e2023-03-29 11:41:06 +05301283// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301284func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301285 //send flows deleted indication to submgr
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301286 vpv.RangeOnServices(cntx, ClearServiceCounters)
Naveen Sampath04696f72022-06-13 15:19:14 +05301287}
1288
1289// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301290func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301291 var vd *VoltDevice
1292 device := vpv.Device
1293
1294 if vd = GetApplication().GetDevice(device); vd != nil {
1295 if vd.State != controller.DeviceStateUP {
1296 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})
1297 return nil
1298 }
1299 } else {
1300 logger.Errorw(ctx, "US DHCP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1301 return errorCodes.ErrDeviceNotFound
1302 }
1303
1304 flows, err := vpv.BuildUsDhcpFlows()
1305 if err == nil {
1306 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301307 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301308 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301309 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301310 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1311 }
1312 } else {
1313 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301314 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301315 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301316 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301317 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301318 return nil
1319}
1320
1321// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301322func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301323 var vd *VoltDevice
1324 device := vpv.Device
1325
1326 if vd = GetApplication().GetDevice(device); vd != nil {
1327 if vd.State != controller.DeviceStateUP {
1328 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})
1329 return nil
1330 }
1331 } else {
1332 logger.Errorw(ctx, "DS DHCP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1333 return errorCodes.ErrDeviceNotFound
1334 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301335 if vd.GlobalDhcpFlowAdded {
1336 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301337 return nil
1338 }
1339
1340 flows, err := vpv.BuildDsDhcpFlows()
1341 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301342 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301343 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301344 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301345 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301346 }
1347 } else {
1348 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301349 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301350 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301351 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301352 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301353 if GetApplication().GetVendorID() != Radisys {
1354 vd.GlobalDhcpFlowAdded = true
1355 }
1356 return nil
1357}
1358
1359// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301360func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
1361 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301362 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301363 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1364 }
1365
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301366 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301367 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301368 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1369 }
1370}
1371
1372// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1373// Write the status of the VPV to the DB once the delete is scheduled
1374// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301375func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301376 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1377 if err != nil {
1378 return err
1379 }
1380
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301381 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301382 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301383 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301384 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1385 }
Akash Sonia8246972023-01-03 10:37:08 +05301386
Naveen Sampath04696f72022-06-13 15:19:14 +05301387 return nil
1388}
1389
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301390func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301391 flows, err := vpv.BuildUsDhcpFlows()
1392 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301393 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301394 }
1395 logger.Errorw(ctx, "US DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1396 return err
1397}
Naveen Sampath04696f72022-06-13 15:19:14 +05301398
1399// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1400// Write the status of the VPV to the DB once the delete is scheduled
1401// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301402func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301403 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1404 if err != nil {
1405 return err
1406 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301407 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301408 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301409 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301410 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1411 }
1412 /*
Akash Sonia8246972023-01-03 10:37:08 +05301413 err = vpv.delDsDhcp6Flows(device)
1414 if err != nil {
1415 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1416 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1417 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301418 return nil
1419}
1420
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301421func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301422 flows, err := vpv.BuildDsDhcpFlows()
1423 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301424 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301425 }
1426 logger.Errorw(ctx, "DS DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1427 return err
1428}
1429
1430/*
1431func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1432 flows, err := vpv.BuildDsDhcp6Flows()
1433 if err == nil {
1434 return vpv.RemoveFlows(device, flows)
1435 }
1436 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1437 return err
1438}*/
1439
1440// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301441func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301442 var vd *VoltDevice
1443 device := vpv.Device
1444 if vd = GetApplication().GetDevice(device); vd != nil {
1445 if vd.State != controller.DeviceStateUP {
1446 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})
1447 return nil
1448 }
1449 } else {
1450 logger.Errorw(ctx, "US ARP Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1451 return errorCodes.ErrDeviceNotFound
1452 }
1453
1454 flows, err := vpv.BuildUsArpFlows()
1455 if err == nil {
1456 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301457 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301458 return err1
1459 }
1460 } else {
1461 logger.Errorw(ctx, "US ARP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1462 return err
1463 }
1464 return nil
1465}
1466
1467// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1468// Write the status of the VPV to the DB once the delete is scheduled
1469// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301470func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301471 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1472 if err != nil {
1473 return err
1474 }
1475 flows, err := vpv.BuildUsArpFlows()
1476 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301477 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301478 }
1479 logger.Errorw(ctx, "US ARP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1480 return err
1481}
1482
1483// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301484func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301485 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1486
1487 var vd *VoltDevice
1488 device := vpv.Device
1489
1490 if vd = GetApplication().GetDevice(device); vd != nil {
1491 if vd.State != controller.DeviceStateUP {
1492 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})
1493 return nil
1494 }
1495 } else {
1496 logger.Errorw(ctx, "US PPPoE Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1497 return errorCodes.ErrDeviceNotFound
1498 }
1499
1500 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1501 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1502
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301503 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301504 return err1
1505 }
1506 } else {
1507 logger.Errorw(ctx, "US PPPoE Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1508 return err
1509 }
1510 return nil
1511}
1512
1513// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301514func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301515 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1516 var vd *VoltDevice
1517 device := vpv.Device
1518
1519 if vd = GetApplication().GetDevice(device); vd != nil {
1520 if vd.State != controller.DeviceStateUP {
1521 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})
1522 return nil
1523 }
1524 } else {
1525 logger.Errorw(ctx, "DS PPPoE Flow Push Failed- Device not found", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan, "UNIVlan": vpv.UniVlan, "device": device})
1526 return errorCodes.ErrDeviceNotFound
1527 }
1528
1529 flows, err := vpv.BuildDsPppoeFlows()
1530 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301531 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301532 return err1
1533 }
1534 } else {
1535 logger.Errorw(ctx, "DS PPPoE Flow Add Failed", log.Fields{"Reason": err.Error()})
1536 return err
1537 }
1538 return nil
1539}
1540
1541// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1542// Write the status of the VPV to the DB once the delete is scheduled
1543// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301544func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301545 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1546 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1547 if err != nil {
1548 return err
1549 }
1550 flows, err := vpv.BuildUsPppoeFlows()
1551 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301552 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301553 }
1554 logger.Errorw(ctx, "US PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1555 return err
1556}
1557
1558// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1559// Write the status of the VPV to the DB once the delete is scheduled
1560// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301561func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301562 logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1563 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1564 if err != nil {
1565 return err
1566 }
1567 flows, err := vpv.BuildDsPppoeFlows()
1568 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301569 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301570 }
1571 logger.Errorw(ctx, "DS PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1572 return err
1573}
1574
1575// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301576func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301577 if !vpv.IgmpFlowsApplied || vgcRebooted {
1578 if vpv.MvlanProfileName == "" {
1579 logger.Info(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
1580 return nil
1581 }
1582 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1583 if err != nil {
1584 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1585 return err
1586 } else if device.State != controller.DeviceStateUP {
1587 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})
1588 return nil
1589 }
1590 flows, err := vpv.BuildIgmpFlows()
1591 if err == nil {
1592 for cookie := range flows.SubFlows {
1593 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1594 cookie := strconv.FormatUint(cookie, 10)
1595 fe := &FlowEvent{
1596 eType: EventTypeUsIgmpFlowAdded,
1597 cookie: cookie,
1598 eventData: vpv,
1599 }
1600 vd.RegisterFlowAddEvent(cookie, fe)
1601 }
1602 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301603 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301604 return err1
1605 }
1606 } else {
1607 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1608 return err
1609 }
1610 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301611 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301612 }
1613 return nil
1614}
1615
1616// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1617// Write the status of the VPV to the DB once the delete is scheduled
1618// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301619func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301620 if vpv.IgmpFlowsApplied || vgcRebooted {
1621 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1622 if err != nil {
1623 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1624 return err
1625 }
1626 flows, err := vpv.BuildIgmpFlows()
1627 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301628 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301629 return err1
1630 }
1631 } else {
1632 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1633 return err
1634 }
1635 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301636 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301637 }
1638 return nil
1639}
1640
1641// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1642// The flows included by this function cover US only as the DS is
1643// created either automatically by the VOLTHA or at the device level
1644// earlier
1645func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
1646 flow := &of.VoltFlow{}
1647 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1648
1649 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
1650 subFlow := of.NewVoltSubFlow()
1651 subFlow.SetTableID(0)
1652
vinokuma926cb3e2023-03-29 11:41:06 +05301653 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301654 subFlow.SetMatchVlan(vpv.CVlan)
1655 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1656 subFlow.SetPcp(vpv.UsPonSTagPriority)
1657 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301658 } else {
1659 subFlow.SetMatchVlan(vpv.UniVlan)
1660 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301661 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301662 }
1663 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301664 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301665 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301666 uniport, err := GetApplication().GetPortID(vpv.Port)
1667 if err != nil {
1668 logger.Errorw(ctx, "Failed to fetch uni port from vpv", log.Fields{"error": err, "port": vpv.Port})
1669 return nil, err
1670 }
1671 subFlow.SetInPort(uniport)
1672 // PortName and PortID to be used for validation of port before flow pushing
1673 flow.PortID = uniport
1674 flow.PortName = vpv.Port
1675 subFlow.SetReportToController()
1676
1677 // Set techprofile, meterid of first service
1678 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301679 vs := value.(*VoltService)
1680 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301681 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301682 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301683 } else {
1684 writemetadata = uint64(vs.TechProfileID) << 32
1685 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301686 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301687 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301688 return false
1689 })
1690
Naveen Sampath04696f72022-06-13 15:19:14 +05301691 // metadata := uint64(uniport)
1692 // subFlow.SetWriteMetadata(metadata)
1693 allowTransparent := 0
1694 if vpv.AllowTransparent {
1695 allowTransparent = 1
1696 }
vinokuma926cb3e2023-03-29 11:41:06 +05301697 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301698 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1699 subFlow.SetTableMetadata(metadata)
1700 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301701 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1702 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1703 subFlow.Priority = of.DhcpFlowPriority
1704
1705 flow.SubFlows[subFlow.Cookie] = subFlow
1706 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1707 return flow, nil
1708}
1709
1710// BuildDsDhcpFlows to build the downstream dhcp flows
1711func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301712 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1713 flow := &of.VoltFlow{}
1714 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1715 subFlow := of.NewVoltSubFlow()
1716 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301717 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301718 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301719 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301720 }
1721 subFlow.SetUdpv4Match()
1722 subFlow.SrcPort = 67
1723 subFlow.DstPort = 68
1724 uniport, _ := GetApplication().GetPortID(vpv.Port)
1725 nni, err := GetApplication().GetNniPort(vpv.Device)
1726 if err != nil {
1727 return nil, err
1728 }
1729 nniport, err := GetApplication().GetPortID(nni)
1730 if err != nil {
1731 return nil, err
1732 }
1733 subFlow.SetInPort(nniport)
1734 // PortName and PortID to be used for validation of port before flow pushing
1735 flow.PortID = uniport
1736 flow.PortName = vpv.Port
1737 // metadata := uint64(uniport)
1738 // subFlow.SetWriteMetadata(metadata)
1739 allowTransparent := 0
1740 if vpv.AllowTransparent {
1741 allowTransparent = 1
1742 }
vinokuma926cb3e2023-03-29 11:41:06 +05301743 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301744 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1745 subFlow.SetTableMetadata(metadata)
1746 subFlow.Priority = of.DhcpFlowPriority
1747 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301748 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301749 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301750 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301751
1752 flow.SubFlows[subFlow.Cookie] = subFlow
1753 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1754
1755 return flow, nil
1756}
1757
1758// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1759// application.
1760func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
1761 flow := &of.VoltFlow{}
1762 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1763
1764 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
1765 subFlow := of.NewVoltSubFlow()
1766 subFlow.SetTableID(0)
1767
1768 subFlow.SetMatchVlan(vpv.UniVlan)
1769 subFlow.SetSetVlan(vpv.CVlan)
1770 subFlow.SetUdpv6Match()
1771 subFlow.SrcPort = 546
1772 subFlow.DstPort = 547
1773 uniport, err := GetApplication().GetPortID(vpv.Port)
1774 if err != nil {
1775 return nil, err
1776 }
1777 // Set techprofile, meterid of first service
1778 vpv.services.Range(func(key, value interface{}) bool {
1779 svc := value.(*VoltService)
1780 writemetadata := uint64(svc.TechProfileID) << 32
1781 subFlow.SetWriteMetadata(writemetadata)
1782 subFlow.SetMeterID(svc.UsMeterID)
1783 return false
1784 })
1785 subFlow.SetInPort(uniport)
1786 // PortName and PortID to be used for validation of port before flow pushing
1787 flow.PortID = uniport
1788 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301789 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301790 // metadata := uint64(uniport)
1791 // subFlow.SetWriteMetadata(metadata)
1792 allowTransparent := 0
1793 if vpv.AllowTransparent {
1794 allowTransparent = 1
1795 }
1796 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1797 subFlow.SetTableMetadata(metadata)
1798 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301799 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301800 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1801 subFlow.Priority = of.DhcpFlowPriority
1802
1803 flow.SubFlows[subFlow.Cookie] = subFlow
1804 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1805 return flow, nil
1806}
1807
1808// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1809// application.
1810func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1811 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1812
1813 flow := &of.VoltFlow{}
1814 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1815 subFlow := of.NewVoltSubFlow()
1816 subFlow.SetTableID(0)
1817
1818 vpv.setDsMatchVlan(subFlow)
1819 subFlow.SetUdpv6Match()
1820 subFlow.SrcPort = 547
1821 subFlow.DstPort = 547
1822 uniport, _ := GetApplication().GetPortID(vpv.Port)
1823 nni, err := GetApplication().GetNniPort(vpv.Device)
1824 if err != nil {
1825 return nil, err
1826 }
1827 nniport, err := GetApplication().GetPortID(nni)
1828 if err != nil {
1829 return nil, err
1830 }
1831 subFlow.SetInPort(nniport)
1832 // PortName and PortID to be used for validation of port before flow pushing
1833 flow.PortID = uniport
1834 flow.PortName = vpv.Port
1835 // metadata := uint64(uniport)
1836 // subFlow.SetWriteMetadata(metadata)
1837 allowTransparent := 0
1838 if vpv.AllowTransparent {
1839 allowTransparent = 1
1840 }
1841 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1842 subFlow.SetTableMetadata(metadata)
1843 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301844 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301845 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1846 subFlow.Priority = of.DhcpFlowPriority
1847
1848 flow.SubFlows[subFlow.Cookie] = subFlow
1849 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1850 return flow, nil
1851}
1852
1853// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1854// The flows included by this function cover US only as the DS is
1855// created either automatically by the VOLTHA or at the device level
1856// earlier
1857func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
1858 flow := &of.VoltFlow{}
1859 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1860
1861 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
1862 subFlow := of.NewVoltSubFlow()
1863 subFlow.SetTableID(0)
1864
1865 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1866 subFlow.SetMatchSrcMac(vpv.MacAddr)
1867 }
1868
1869 subFlow.SetMatchDstMac(BroadcastMAC)
1870 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1871 return nil, err
1872 }
1873 subFlow.SetArpMatch()
1874 uniport, err := GetApplication().GetPortID(vpv.Port)
1875 if err != nil {
1876 return nil, err
1877 }
1878 subFlow.SetInPort(uniport)
1879 // PortName and PortID to be used for validation of port before flow pushing
1880 flow.PortID = uniport
1881 flow.PortName = vpv.Port
1882 subFlow.SetReportToController()
1883 allowTransparent := 0
1884 if vpv.AllowTransparent {
1885 allowTransparent = 1
1886 }
1887 metadata := uint64(uniport)
1888 subFlow.SetWriteMetadata(metadata)
1889 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1890 subFlow.SetTableMetadata(metadata)
1891 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1892 subFlow.Priority = of.ArpFlowPriority
1893
1894 flow.SubFlows[subFlow.Cookie] = subFlow
1895 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1896 return flow, nil
1897}
1898
1899// setUsMatchVlan to set upstream match vlan
1900func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
1901 switch vpv.VlanControl {
1902 case None:
1903 flow.SetMatchVlan(vpv.SVlan)
1904 case ONUCVlanOLTSVlan:
1905 flow.SetMatchVlan(vpv.CVlan)
1906 case OLTCVlanOLTSVlan:
1907 flow.SetMatchVlan(vpv.UniVlan)
1908 //flow.SetSetVlan(vpv.CVlan)
1909 case ONUCVlan:
1910 flow.SetMatchVlan(vpv.SVlan)
1911 case OLTSVlan:
1912 flow.SetMatchVlan(vpv.UniVlan)
1913 //flow.SetSetVlan(vpv.SVlan)
1914 default:
1915 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1916 return errorCodes.ErrInvalidParamInRequest
1917 }
1918 return nil
1919}
1920
1921// BuildUsPppoeFlows to build upstream pppoe flows
1922func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301923 flow := &of.VoltFlow{}
1924 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1925 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
1926 subFlow := of.NewVoltSubFlow()
1927 subFlow.SetTableID(0)
1928
1929 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1930 subFlow.SetMatchSrcMac(vpv.MacAddr)
1931 }
1932
1933 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1934 return nil, err
1935 }
1936 subFlow.SetPppoeDiscoveryMatch()
1937 uniport, err := GetApplication().GetPortID(vpv.Port)
1938 if err != nil {
1939 return nil, err
1940 }
1941 subFlow.SetInPort(uniport)
1942 subFlow.SetReportToController()
1943 // PortName and PortID to be used for validation of port before flow pushing
1944 flow.PortID = uniport
1945 flow.PortName = vpv.Port
1946
1947 allowTransparent := 0
1948 if vpv.AllowTransparent {
1949 allowTransparent = 1
1950 }
1951 metadata := uint64(uniport)
1952 subFlow.SetWriteMetadata(metadata)
1953
1954 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1955 subFlow.SetTableMetadata(metadata)
1956
vinokuma926cb3e2023-03-29 11:41:06 +05301957 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301958 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
1959 subFlow.Priority = of.PppoeFlowPriority
1960
1961 flow.SubFlows[subFlow.Cookie] = subFlow
1962 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1963 return flow, nil
1964}
1965
1966// BuildDsPppoeFlows to build downstream pppoe flows
1967func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301968 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1969 flow := &of.VoltFlow{}
1970 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1971 subFlow := of.NewVoltSubFlow()
1972 subFlow.SetTableID(0)
1973
1974 vpv.setDsMatchVlan(subFlow)
1975 subFlow.SetPppoeDiscoveryMatch()
1976
1977 if NonZeroMacAddress(vpv.MacAddr) {
1978 subFlow.SetMatchDstMac(vpv.MacAddr)
1979 }
1980
1981 uniport, _ := GetApplication().GetPortID(vpv.Port)
1982 nni, err := GetApplication().GetNniPort(vpv.Device)
1983 if err != nil {
1984 return nil, err
1985 }
1986 nniport, err := GetApplication().GetPortID(nni)
1987 if err != nil {
1988 return nil, err
1989 }
1990 subFlow.SetInPort(nniport)
1991 // PortName and PortID to be used for validation of port before flow pushing
1992 flow.PortID = uniport
1993 flow.PortName = vpv.Port
1994 metadata := uint64(uniport)
1995 subFlow.SetWriteMetadata(metadata)
1996 allowTransparent := 0
1997 if vpv.AllowTransparent {
1998 allowTransparent = 1
1999 }
2000 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2001 subFlow.SetTableMetadata(metadata)
2002 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302003 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302004 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2005 subFlow.Priority = of.PppoeFlowPriority
2006
2007 flow.SubFlows[subFlow.Cookie] = subFlow
2008 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2009 return flow, nil
2010}
2011
2012// setDsMatchVlan to set downstream match vlan
2013func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
2014 switch vpv.VlanControl {
2015 case None:
2016 flow.SetMatchVlan(vpv.SVlan)
2017 case ONUCVlanOLTSVlan,
2018 OLTCVlanOLTSVlan,
2019 ONUCVlan,
2020 OLTSVlan:
2021 flow.SetMatchVlan(vpv.SVlan)
2022 default:
2023 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2024 }
2025}
2026
2027// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2028// in the US direction.
2029func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2030 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2031 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2032 if mvp == nil {
2033 return nil, errors.New("Mvlan Profile configured not found")
2034 }
2035 mvlan := mvp.GetUsMatchVlan()
2036 flow := &of.VoltFlow{}
2037 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2038 subFlow := of.NewVoltSubFlow()
2039 subFlow.SetTableID(0)
2040
Akash Sonia8246972023-01-03 10:37:08 +05302041 subFlow.SetMatchVlan(vpv.UniVlan)
2042 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302043
2044 uniport, err := GetApplication().GetPortID(vpv.Port)
2045 if err != nil {
2046 return nil, err
2047 }
2048 subFlow.SetInPort(uniport)
2049 // PortName and PortID to be used for validation of port before flow pushing
2050 flow.PortID = uniport
2051 flow.PortName = vpv.Port
2052
2053 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2054 subFlow.SetMatchSrcMac(vpv.MacAddr)
2055 }
2056 logger.Infow(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302057 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302058
2059 if vpv.McastService {
2060 metadata := uint64(vpv.McastUsMeterID)
2061 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2062 subFlow.SetMatchPbit(vpv.McastPbit)
2063 subFlow.SetMeterID(vpv.McastUsMeterID)
2064 subFlow.SetWriteMetadata(metadata)
2065 } else {
2066 // Set techprofile, meterid of first service
2067 vpv.services.Range(func(key, value interface{}) bool {
2068 svc := value.(*VoltService)
2069 writemetadata := uint64(svc.TechProfileID) << 32
2070 subFlow.SetWriteMetadata(writemetadata)
2071 subFlow.SetMeterID(svc.UsMeterID)
2072 return false
2073 })
2074 }
2075
2076 allowTransparent := 0
2077 if vpv.AllowTransparent {
2078 allowTransparent = 1
2079 }
2080 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2081 subFlow.SetTableMetadata(metadata)
2082 subFlow.SetIgmpMatch()
2083 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302084 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302085 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2086 subFlow.Priority = of.IgmpFlowPriority
2087
2088 flow.SubFlows[subFlow.Cookie] = subFlow
2089 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2090 return flow, nil
2091}
2092
2093// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302094func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302095 if vpv.DeleteInProgress {
2096 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2097 return
2098 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302099 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302100}
2101
vinokuma926cb3e2023-03-29 11:41:06 +05302102// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302103func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302104 vpv.PendingFlowLock.RLock()
2105 defer vpv.PendingFlowLock.RUnlock()
2106 vpv.Version = database.PresentVersionMap[database.VpvPath]
2107 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302108 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 +05302109 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2110 "UniVlan": vpv.UniVlan, "Error": err})
2111 }
2112 }
2113}
2114
2115// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302116func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302117 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 +05302118 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302119}
2120
2121// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302122func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
2123 vpv.RangeOnServices(cntx, ClearFlagsInService)
Naveen Sampath04696f72022-06-13 15:19:14 +05302124}
2125
2126// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302127func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302128 vpv.PendingFlowLock.Lock()
2129 vpv.FlowsApplied = false
2130 vpv.IgmpFlowsApplied = false
2131 vpv.PendingDeleteFlow = make(map[string]bool)
2132 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302133 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302134 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2135 log.Fields{"device": vpv.Device, "port": vpv.Port,
2136 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2137}
2138
2139// CreateVpvFromString to create vpv from string
2140func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
2141 var vpv VoltPortVnet
2142 if err := json.Unmarshal(b, &vpv); err == nil {
2143 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2144 if !ok {
2145 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2146 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2147 }
2148 vpv.servicesCount = atomic.NewUint64(0)
2149 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2150 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2151 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2152 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2153 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2154 vnet.associatePortToVnet(vpv.Port)
2155 }
2156
2157 if vpv.DeleteInProgress {
2158 va.VoltPortVnetsToDelete[&vpv] = true
2159 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2160 }
2161 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2162 }
2163}
2164
2165// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302166func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302167 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302168 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302169 for hash, vpv := range vpvs {
2170 b, ok := vpv.Value.([]byte)
2171 if !ok {
2172 logger.Warn(ctx, "The value type is not []byte")
2173 continue
2174 }
2175 va.CreateVpvFromString(b, hash)
2176 }
2177}
2178
2179// GetVnetByPort : VNET related functionality of VOLT Application here on.
2180// Get the VNET from a port. The port identity is passed as device and port identities in string.
2181// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2182// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2183func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
2184 if _, ok := va.VnetsByPort.Load(port); !ok {
2185 return nil
2186 }
2187 vpvs, _ := va.VnetsByPort.Load(port)
2188 for _, vpv := range vpvs.([]*VoltPortVnet) {
2189 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2190 return vpv
2191 }
2192 }
2193 return nil
2194}
2195
2196// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302197func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302198 // The VNET is not on the port and is to be added
2199 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2200 vpv := NewVoltPortVnet(vvnet)
2201 vpv.MacLearning = vvnet.MacLearning
2202 vpv.Port = port
2203 vvnet.associatePortToVnet(port)
2204 if _, ok := va.VnetsByPort.Load(port); !ok {
2205 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2206 }
2207 vpvsIntf, _ := va.VnetsByPort.Load(port)
2208 vpvs := vpvsIntf.([]*VoltPortVnet)
2209 vpvs = append(vpvs, vpv)
2210 va.VnetsByPort.Store(port, vpvs)
2211 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2212
2213 vpv.VpvLock.Lock()
2214 defer vpv.VpvLock.Unlock()
2215
2216 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302217 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302218
Tinoj Josephec742f62022-09-29 19:11:10 +05302219 if !vs.IsActivated {
2220 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2221 // Process the PORT UP if the port is already up
2222 d, err := va.GetDeviceFromPort(port)
2223 if err == nil {
2224 vpv.setDevice(d.Name)
2225 }
2226 vpv.WriteToDb(cntx)
2227 return vpv
2228 }
2229
Naveen Sampath04696f72022-06-13 15:19:14 +05302230 // Process the PORT UP if the port is already up
2231 d, err := va.GetDeviceFromPort(port)
2232 if err == nil {
2233 vpv.setDevice(d.Name)
2234 p := d.GetPort(port)
2235 if p != nil {
Akash Soni024eb8e2023-04-28 16:25:09 +05302236 logger.Infow(ctx, "Checking UNI port state", log.Fields{"State": p.State})
2237 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
2238 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302239 }
2240 }
2241 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302242 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302243 return vpv
2244}
2245
2246// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302247func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05302248 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302249 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2250
vinokuma926cb3e2023-03-29 11:41:06 +05302251 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302252 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2253
vinokuma926cb3e2023-03-29 11:41:06 +05302254 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302255 va.DeleteMacInPortMap(vpv.MacAddr)
2256
vinokuma926cb3e2023-03-29 11:41:06 +05302257 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302258 vpvsIntf, ok := va.VnetsByPort.Load(port)
2259 if !ok {
2260 return
2261 }
2262 vpvs := vpvsIntf.([]*VoltPortVnet)
2263 for i, lvpv := range vpvs {
vinokuma04dc9f82023-07-31 15:47:49 +05302264 if reflect.DeepEqual(lvpv, vpv) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302265 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2266 "UNIVLAN": vpv.UniVlan})
2267
2268 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2269
2270 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302271 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302272
2273 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302274 vpv.DelTrapFlows(cntx)
2275 vpv.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302276 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2277 vpv.PendingFlowLock.RLock()
2278 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302279 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302280 }
2281 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302282 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302283 }
2284 vpv.PendingFlowLock.RUnlock()
2285 return
2286 }
2287 }
2288}
2289
2290// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302291func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302292 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302293 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302294 for _, net := range vnets {
2295 b, ok := net.Value.([]byte)
2296 if !ok {
2297 logger.Warn(ctx, "The value type is not []byte")
2298 continue
2299 }
2300 var vnet VoltVnet
2301 err := json.Unmarshal(b, &vnet)
2302 if err != nil {
2303 logger.Warn(ctx, "Unmarshal of VNET failed")
2304 continue
2305 }
2306 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302307 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302308 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2309 }
2310
2311 if vnet.DeleteInProgress {
2312 va.VnetsToDelete[vnet.Name] = true
2313 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2314 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302315 }
2316}
2317
2318// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2319// are used as the key to locate the service. If more than one service is on the
2320// same port (essentially a UNI of ONU), the services must be separated by different
2321// CVLANs
2322func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
2323 // Fetch the device first to make sure the device exists
2324 dIntf, ok := va.DevicesDisc.Load(device)
2325 if !ok {
2326 return nil
2327 }
2328 d := dIntf.(*VoltDevice)
2329
2330 // If the port is NNI port, the services dont exist on it. The svc then
2331 // must be obtained from a different context and is not included here
2332 if port == d.NniPort {
2333 return nil
2334 }
2335
vinokuma926cb3e2023-03-29 11:41:06 +05302336 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302337 var service *VoltService
2338
2339 // This is an access port and the port should have all the associated
2340 // services which can be uniquely identified by the VLANs in the packet
2341 vnets, ok := va.VnetsByPort.Load(port)
2342
2343 if !ok {
2344 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2345 return nil
2346 }
2347 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2348 for _, vnet := range vnets.([]*VoltPortVnet) {
2349 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2350 switch vnet.VlanControl {
2351 case ONUCVlanOLTSVlan:
2352 service = vnet.MatchesPriority(priority)
2353 if vnet.MatchesCvlan(vlans) && service != nil {
2354 return service
2355 }
2356 case ONUCVlan,
2357 None:
2358 service = vnet.MatchesPriority(priority)
2359 // In case of DHCP Flow - cvlan == VlanNone
2360 // In case of HSIA Flow - cvlan == Svlan
2361 if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
2362 return service
2363 }
2364 case OLTCVlanOLTSVlan,
2365 OLTSVlan:
2366 service = vnet.MatchesPriority(priority)
2367 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2368 return service
2369 }
2370 default:
2371 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2372 }
2373 }
2374 return nil
2375}
2376
2377// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2378// are used as the key to locate the service. If more than one service is on the
2379// same port (essentially a UNI of ONU), the services must be separated by different
2380// CVLANs
2381func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2382 // Fetch the device first to make sure the device exists
2383 dIntf, ok := va.DevicesDisc.Load(device)
2384 if !ok {
2385 return nil, nil
2386 }
2387 d := dIntf.(*VoltDevice)
2388
2389 // If the port is NNI port, the services dont exist on it. The svc then
2390 // must be obtained from a different context and is not included here
2391 if port == d.NniPort {
2392 return nil, nil
2393 }
2394
2395 //To return the matched service
2396 var service *VoltService
2397
2398 // This is an access port and the port should have all the associated
2399 // services which can be uniquely identified by the VLANs in the packet
2400 if vnets, ok := va.VnetsByPort.Load(port); ok {
2401 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2402 for _, vnet := range vnets.([]*VoltPortVnet) {
2403 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2404 switch vnet.VlanControl {
2405 case ONUCVlanOLTSVlan:
2406 service = vnet.MatchesPriority(priority)
2407 if vnet.MatchesCvlan(vlans) && service != nil {
2408 return vnet, service
2409 }
2410 case ONUCVlan,
2411 None:
2412 service = vnet.MatchesPriority(priority)
2413 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2414 return vnet, service
2415 }
2416 case OLTCVlanOLTSVlan,
2417 OLTSVlan:
2418 service = vnet.MatchesPriority(priority)
2419 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2420 return vnet, service
2421 }
2422 default:
2423 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2424 }
2425 }
2426 }
2427 return nil, nil
2428}
2429
2430// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2431// are used as the key to locate the service. If more than one service is on the
2432// same port (essentially a UNI of ONU), the services must be separated by different
2433// CVLANs
2434func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
2435 vlans := GetVlans(pkt)
2436 priority := GetPriority(pkt)
2437 return va.GetVnetFromFields(device, port, vlans, priority)
2438}
2439
2440// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302441func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302442 logger.Infow(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2443 pushflow := func(key interface{}, value interface{}) bool {
2444 device := value.(*VoltDevice)
2445 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302446 logger.Infow(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302447 return true
2448 }
2449 if device.State != controller.DeviceStateUP {
2450 logger.Errorw(ctx, "Push Dev Flows Failed - Device state DOWN", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan, "device": device})
2451 return true
2452 }
2453 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2454 logger.Errorw(ctx, "Push Dev Flows Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2455 return true
2456 }
2457
2458 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2459 vnetList := vnetListIntf.(*util.ConcurrentMap)
2460 vnetList.Set(vnet.Name, true)
2461 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2462 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()})
2463 return true
2464 }
2465 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2466 err := ProcessIcmpv6McGroup(device.Name, false)
2467 if err != nil {
2468 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2469 return true
2470 }
2471 if portID, err := va.GetPortID(device.NniPort); err == nil {
2472 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2473 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2474 return true
2475 }
2476
vinokuma926cb3e2023-03-29 11:41:06 +05302477 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302478 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302479 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302480 if err != nil {
2481 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2482 return true
2483 }
2484 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2485
2486 // Pushing ARP Flow
2487 flow = BuildDSArpFlow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302488 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302489 if err != nil {
2490 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2491 return true
2492 }
2493 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2494
2495 vnetList := util.NewConcurrentMap()
2496 vnetList.Set(vnet.Name, true)
2497 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2498 }
2499 return true
2500 }
2501 va.DevicesDisc.Range(pushflow)
2502}
2503
2504// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302505func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302506 logger.Infow(ctx, "PushDevFlowForDevice", log.Fields{"device": device})
2507
2508 logger.Debugw(ctx, "Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2509 err := ProcessIcmpv6McGroup(device.Name, false)
2510 if err != nil {
2511 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2512 return
2513 }
2514 pushicmpv6 := func(key, value interface{}) bool {
2515 vnet := value.(*VoltVnet)
2516 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2517 vnetList := vnetListIntf.(*util.ConcurrentMap)
2518 vnetList.Set(vnet.Name, true)
2519 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2520 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()})
2521 return true
2522 }
2523 nniPortID, err := va.GetPortID(device.NniPort)
2524 if err != nil {
2525 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2526 }
2527 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2528 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2529 return true
2530 }
2531 flow := BuildICMPv6Flow(nniPortID, 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 ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2535 return true
2536 }
2537 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2538
2539 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302540 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302541 if err != nil {
2542 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2543 return true
2544 }
2545 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2546
2547 vnetList := util.NewConcurrentMap()
2548 vnetList.Set(vnet.Name, true)
2549 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2550 return true
2551 }
2552 va.VnetsByName.Range(pushicmpv6)
2553}
2554
2555// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302556func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302557 logger.Infow(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2558 delflows := func(key interface{}, value interface{}) bool {
2559 device := value.(*VoltDevice)
2560
2561 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2562 vnetList := vnetListIntf.(*util.ConcurrentMap)
2563 vnetList.Remove(vnet.Name)
2564 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2565 if vnetList.Length() != 0 {
2566 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()})
2567 return true
2568 }
2569 }
2570 if portID, err := va.GetPortID(device.NniPort); err == nil {
2571 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2572 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2573 return true
2574 }
vinokuma926cb3e2023-03-29 11:41:06 +05302575 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302576 flow := BuildICMPv6Flow(portID, vnet)
2577 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302578 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302579 if err != nil {
2580 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2581 return true
2582 }
2583 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2584
vinokuma926cb3e2023-03-29 11:41:06 +05302585 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302586 flow = BuildDSArpFlow(portID, vnet)
2587 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302588 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302589 if err != nil {
2590 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2591 return true
2592 }
2593 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2594
2595 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2596 }
2597 return true
2598 }
2599 va.DevicesDisc.Range(delflows)
2600}
2601
2602// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302603func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302604 logger.Infow(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
2605 delicmpv6 := func(key, value interface{}) bool {
2606 vnet := value.(*VoltVnet)
2607 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2608 vnetList := vnetListIntf.(*util.ConcurrentMap)
2609 vnetList.Remove(vnet.Name)
2610 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2611 if vnetList.Length() != 0 {
2612 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()})
2613 return true
2614 }
2615 } else {
2616 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2617 return true
2618 }
2619 nniPortID, err := va.GetPortID(device.NniPort)
2620 if err != nil {
2621 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2622 }
2623 flow := BuildICMPv6Flow(nniPortID, vnet)
2624 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302625 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302626 if err != nil {
2627 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2628 return true
2629 }
2630
2631 flow = BuildDSArpFlow(nniPortID, vnet)
2632 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302633 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302634 if err != nil {
2635 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2636 return true
2637 }
2638
2639 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2640 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2641 return true
2642 }
2643 va.VnetsByName.Range(delicmpv6)
2644 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2645 err := ProcessIcmpv6McGroup(device.Name, true)
2646 if err != nil {
2647 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2648 return
2649 }
2650}
2651
2652// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302653func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302654 logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2655 delflows := func(key interface{}, value interface{}) bool {
2656 device := value.(*VoltDevice)
2657 if device.SerialNum != deviceSerialNum {
2658 return true
2659 }
2660 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2661 vnetList := vnetListIntf.(*util.ConcurrentMap)
2662 vnetList.Remove(vnet.Name)
2663 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2664 if vnetList.Length() != 0 {
2665 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()})
2666 return true
2667 }
2668 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2669 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2670 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2671 // The step will be as follow:
2672 // 1. Deact Service
2673 // 2. Pod Reboot
2674 // 3. Pending Delete Service triggered
2675 // 4. Del Service Ind followed by DelVnet req from NB
2676 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2677 // hence the flow will not be cleared
2678 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2679 return true
2680 }
2681 if portID, err := va.GetPortID(device.NniPort); err == nil {
2682 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2683 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2684 return false
2685 }
2686 flow := BuildICMPv6Flow(portID, vnet)
2687 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302688 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302689 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2690 }
2691 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2692
2693 flow = BuildDSArpFlow(portID, vnet)
2694 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302695 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302696 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2697 }
2698 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2699 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2700 }
2701 return false
2702 }
2703 va.DevicesDisc.Range(delflows)
2704}
2705
2706// BuildICMPv6Flow to Build DS flow for ICMPv6
2707func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302708 logger.Infow(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302709 flow := &of.VoltFlow{}
2710 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2711 subFlow := of.NewVoltSubFlow()
2712
2713 subFlow.SetICMPv6Match()
2714 subFlow.SetMatchVlan(vnet.SVlan)
2715 subFlow.SetInPort(inport)
2716 subFlow.SetPopVlan()
2717 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2718 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2719 subFlow.Priority = of.McFlowPriority
2720 var metadata uint64
2721 if vnet.VlanControl == None {
2722 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2723 } else {
2724 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2725 }
2726 subFlow.SetTableMetadata(metadata)
2727 metadata = uint64(vnet.setPbitRemarking())
2728
2729 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2730 subFlow.SetWriteMetadata(metadata)
2731 flow.SubFlows[subFlow.Cookie] = subFlow
2732 return flow
2733}
2734
vinokuma926cb3e2023-03-29 11:41:06 +05302735// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302736func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302737 logger.Infow(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302738
2739 flow := &of.VoltFlow{}
2740 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2741 subFlow := of.NewVoltSubFlow()
2742
2743 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2744 subFlow.SetArpMatch()
2745 subFlow.SetMatchDstMac(BcastMAC)
2746 subFlow.SetMatchVlan(vnet.SVlan)
2747 subFlow.SetInPort(inport)
2748 subFlow.SetPopVlan()
2749 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2750
2751 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2752 subFlow.Priority = of.McFlowPriority
2753
2754 var metadata uint64
2755 if vnet.VlanControl == None {
2756 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2757 } else {
2758 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2759 }
2760 subFlow.SetTableMetadata(metadata)
2761 metadata = uint64(vnet.setPbitRemarking())
2762 subFlow.SetWriteMetadata(metadata)
2763
2764 flow.SubFlows[subFlow.Cookie] = subFlow
2765 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2766 return flow
2767}
2768
2769// setPbitRemarking to set Pbit remarking
2770func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302771 // Remarkable
2772 // Remarked Pbit Pbit
2773 // |-----------------------------| |------|
2774 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2775 // 000 000 000 000 000 000 000 000 00000000
2776
2777 // Eg:
2778 // For 6:3 & 7:1
2779 // 001 011 000 000 000 000 000 000 11000000
2780
2781 var remarkable uint8
2782 var remarked uint32
2783 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2784 remarkable = remarkable | 1<<refPbit
2785 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2786 }
2787 return remarked<<8 | uint32(remarkable)
2788}
2789
2790// ProcessIcmpv6McGroup to add icmpv6 multicast group
2791func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302792 logger.Info(ctx, "Creating ICMPv6 MC Group")
2793 va := GetApplication()
2794 vd := va.GetDevice(device)
2795 group := &of.Group{}
2796 group.GroupID = ICMPv6ArpGroupID
2797 group.Device = device
2798 if delete {
2799 if !vd.icmpv6GroupAdded {
2800 logger.Info(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
2801 return nil //TODO
2802 }
2803 vd.icmpv6GroupAdded = false
2804 group.Command = of.GroupCommandDel
2805 group.ForceAction = true
2806 } else {
2807 if vd.icmpv6GroupAdded {
2808 logger.Info(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
2809 return nil //TODO
2810 }
2811 vd.icmpv6GroupAdded = true
2812 group.Command = of.GroupCommandAdd
2813 receivers := GetApplication().GetIcmpv6Receivers(device)
2814 group.Buckets = append(group.Buckets, receivers...)
2815 }
2816 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2817 port, _ := GetApplication().GetNniPort(device)
2818 err := cntlr.GetController().GroupUpdate(port, device, group)
2819 return err
2820}
2821
vinokuma926cb3e2023-03-29 11:41:06 +05302822// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302823func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05302824 switch vpv.VlanControl {
2825 case ONUCVlanOLTSVlan,
2826 OLTCVlanOLTSVlan:
2827 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2828 return true
2829 }
2830 case ONUCVlan,
2831 OLTSVlan,
2832 None:
2833 if vpv.SVlan == svlan {
2834 return true
2835 }
2836 default:
2837 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2838 }
2839 return false
2840}
2841
vinokuma926cb3e2023-03-29 11:41:06 +05302842// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302843func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302844 for cookie := range flow.SubFlows {
2845 cookie := strconv.FormatUint(cookie, 10)
2846 fe := &FlowEvent{
2847 eType: EventTypeControlFlowAdded,
2848 cookie: cookie,
2849 eventData: vpv,
2850 }
2851 device.RegisterFlowAddEvent(cookie, fe)
2852 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302853 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302854}
2855
vinokuma926cb3e2023-03-29 11:41:06 +05302856// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302857func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302858 sendFlowFailureInd := func(key, value interface{}) bool {
2859 //svc := value.(*VoltService)
2860 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2861 return true
2862 }
2863 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2864 vpv.services.Range(sendFlowFailureInd)
2865}
2866
vinokuma926cb3e2023-03-29 11:41:06 +05302867// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302868func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302869 vpv.PendingFlowLock.Lock()
2870 defer vpv.PendingFlowLock.Unlock()
2871
2872 for cookie := range flow.SubFlows {
2873 cookie := strconv.FormatUint(cookie, 10)
2874 fe := &FlowEvent{
2875 eType: EventTypeControlFlowRemoved,
2876 device: device.Name,
2877 cookie: cookie,
2878 eventData: vpv,
2879 }
2880 device.RegisterFlowDelEvent(cookie, fe)
2881 vpv.PendingDeleteFlow[cookie] = true
2882 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302883 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302884}
2885
vinokuma926cb3e2023-03-29 11:41:06 +05302886// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302887func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302888 vpv.PendingFlowLock.RLock()
2889 defer vpv.PendingFlowLock.RUnlock()
2890 if !vpv.DeleteInProgress {
2891 return
2892 }
2893 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
2894 logger.Infow(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 +05302895 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302896 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2897 }
2898}
2899
vinokuma926cb3e2023-03-29 11:41:06 +05302900// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302901func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302902 vpv.PendingFlowLock.Lock()
2903 logger.Infow(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
2904
2905 delete(vpv.PendingDeleteFlow, cookie)
2906 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302907 vpv.CheckAndDeleteVpv(cntx)
2908 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302909}
2910
vinokuma926cb3e2023-03-29 11:41:06 +05302911// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302912func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302913 vpv.PendingFlowLock.Lock()
2914
2915 logger.Errorw(ctx, "VPV Flow Remove Failure Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
2916
2917 sendFlowFailureInd := func(key, value interface{}) bool {
2918 svc := value.(*VoltService)
2919 svc.triggerServiceFailureInd(errorCode, errReason)
2920 return true
2921 }
2922 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2923 vpv.services.Range(sendFlowFailureInd)
2924
2925 if vpv.DeleteInProgress {
2926 delete(vpv.PendingDeleteFlow, cookie)
2927 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302928 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302929 } else {
2930 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302931 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302932 }
2933}
2934
vinokuma926cb3e2023-03-29 11:41:06 +05302935// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302936func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302937 vv.VnetLock.Lock()
2938 defer vv.VnetLock.Unlock()
2939
2940 var flowMap map[string]bool
2941 var ok bool
2942
2943 for cookie := range flow.SubFlows {
2944 cookie := strconv.FormatUint(cookie, 10)
2945 fe := &FlowEvent{
2946 eType: EventTypeDeviceFlowRemoved,
2947 device: device.Name,
2948 cookie: cookie,
2949 eventData: vv,
2950 }
2951 device.RegisterFlowDelEvent(cookie, fe)
2952 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
2953 flowMap = make(map[string]bool)
2954 }
2955 flowMap[cookie] = true
2956 vv.PendingDeleteFlow[device.Name] = flowMap
2957 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302958 vv.WriteToDb(cntx)
2959 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302960}
2961
vinokuma926cb3e2023-03-29 11:41:06 +05302962// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302963func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302964 if !vv.DeleteInProgress {
2965 return
2966 }
2967 vv.VnetPortLock.RLock()
2968 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
2969 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
2970 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302971 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05302972 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
2973 } else {
2974 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
2975 }
2976 vv.VnetPortLock.RUnlock()
2977}
2978
vinokuma926cb3e2023-03-29 11:41:06 +05302979// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302980func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302981 vv.VnetLock.Lock()
2982 defer vv.VnetLock.Unlock()
2983
2984 logger.Infow(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
2985
2986 if _, ok := vv.PendingDeleteFlow[device]; ok {
2987 delete(vv.PendingDeleteFlow[device], cookie)
2988 }
2989
2990 //Check and update success for pending disable request
2991 if d := GetApplication().GetDevice(device); d != nil {
2992 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
2993 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302994 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302995 }
2996 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302997 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302998}
2999
vinokuma926cb3e2023-03-29 11:41:06 +05303000// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303001func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303002 vv.VnetLock.Lock()
3003 defer vv.VnetLock.Unlock()
3004
3005 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3006 if _, ok := flowMap[cookie]; ok {
3007 logger.Errorw(ctx, "Device Flow Remove Failure Notification", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
3008
3009 if vv.DeleteInProgress {
3010 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303011 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303012 }
3013 return
3014 }
3015 }
3016 logger.Errorw(ctx, "Device Flow Remove Failure Notification for Unknown cookie", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3017}
3018
vinokuma926cb3e2023-03-29 11:41:06 +05303019// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303020func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303021 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3022 // When multiple Igmp-suported service enabled, comment "return false"
Naveen Sampath04696f72022-06-13 15:19:14 +05303023
3024 sendFlowFailureInd := func(key, value interface{}) bool {
3025 svc := value.(*VoltService)
3026 if svc.IgmpEnabled {
3027 svc.triggerServiceFailureInd(errorCode, errReason)
3028 return false
3029 }
3030 return true
3031 }
3032 logger.Errorw(ctx, "US IGMP Flow Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3033 vpv.services.Range(sendFlowFailureInd)
3034}
3035
3036// GetMatchingMcastService to get matching multicast service
3037func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +05303038 var service *VoltService
3039 dIntf, ok := va.DevicesDisc.Load(device)
3040 if !ok {
3041 return nil
3042 }
3043 d := dIntf.(*VoltDevice)
3044
3045 // If the port is NNI port, the services dont exist on it. The svc then
3046 // must be obtained from a different context and is not included here
3047 if port == d.NniPort {
3048 return nil
3049 }
3050
3051 // This is an access port and the port should have all the associated
3052 // services which can be uniquely identified by the VLANs in the packet
3053 vnets, ok := va.VnetsByPort.Load(port)
3054
3055 if !ok {
3056 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3057 return nil
3058 }
3059 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3060 getMcastService := func(key, value interface{}) bool {
3061 srv := value.(*VoltService)
3062 if srv.IgmpEnabled {
3063 service = srv
3064
3065 //TODO: Current implementation supports only for single service with Igmp Enabled
3066 //FIX-ME: When multiple service suports Igmp, update of logic required
3067 return false
3068 }
3069 return true
3070 }
3071
3072 for _, vpv := range vnets.([]*VoltPortVnet) {
3073 if vpv.CVlan == cvlan {
3074 vpv.services.Range(getMcastService)
3075 if service != nil {
3076 break
3077 }
3078 }
3079 }
3080 return service
3081}
3082
vinokuma926cb3e2023-03-29 11:41:06 +05303083// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303084func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05303085 vv.VnetLock.Lock()
3086 cookieList := []uint64{}
3087 flowMap := vv.PendingDeleteFlow[device]
3088
3089 for cookie := range flowMap {
3090 cookieList = append(cookieList, convertToUInt64(cookie))
3091 }
3092 vv.VnetLock.Unlock()
3093
3094 if len(cookieList) == 0 {
3095 return false
3096 }
3097
3098 for _, cookie := range cookieList {
3099 if vd := GetApplication().GetDevice(device); vd != nil {
3100 flow := &of.VoltFlow{}
3101 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3102 subFlow := of.NewVoltSubFlow()
3103 subFlow.Cookie = cookie
3104 flow.SubFlows[cookie] = subFlow
3105 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303106 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303107 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3108 }
3109 }
3110 }
3111 return true
3112}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303113
vinokuma926cb3e2023-03-29 11:41:06 +05303114// JSONMarshal wrapper function for json Marshal VoltVnet
3115func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303116 return json.Marshal(VoltVnet{
3117 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303118 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303119 VnetOper: VnetOper{
3120 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3121 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3122 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3123 },
3124 })
3125}
3126
vinokuma926cb3e2023-03-29 11:41:06 +05303127// JSONMarshal wrapper function for json Marshal VoltPortVnet
3128func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303129 return json.Marshal(VoltPortVnet{
3130 Device: vpv.Device,
3131 Port: vpv.Port,
3132 PonPort: vpv.PonPort,
3133 VnetName: vpv.VnetName,
3134 SVlan: vpv.SVlan,
3135 CVlan: vpv.CVlan,
3136 UniVlan: vpv.UniVlan,
3137 SVlanTpid: vpv.SVlanTpid,
3138 DhcpRelay: vpv.DhcpRelay,
3139 ArpRelay: vpv.ArpRelay,
3140 PppoeIa: vpv.PppoeIa,
3141 MacLearning: vpv.MacLearning,
3142 DhcpStatus: vpv.DhcpStatus,
3143 DhcpExpiryTime: vpv.DhcpExpiryTime,
3144 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3145 FlowsApplied: vpv.FlowsApplied,
3146 Ipv4Addr: vpv.Ipv4Addr,
3147 Ipv6Addr: vpv.Ipv6Addr,
3148 MacAddr: vpv.MacAddr,
3149 LearntMacAddr: vpv.LearntMacAddr,
3150 CircuitID: vpv.CircuitID,
3151 RemoteID: vpv.RemoteID,
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05303152 IsOption82Enabled: vpv.IsOption82Enabled,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303153 RelayState: vpv.RelayState,
3154 PPPoeState: vpv.PPPoeState,
3155 RelayStatev6: vpv.RelayStatev6,
3156 IgmpEnabled: vpv.IgmpEnabled,
3157 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3158 McastService: vpv.McastService,
3159 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3160 VlanControl: vpv.VlanControl,
3161 MvlanProfileName: vpv.MvlanProfileName,
3162 Version: vpv.Version,
3163 McastTechProfileID: vpv.McastTechProfileID,
3164 McastPbit: vpv.McastPbit,
3165 McastUsMeterID: vpv.McastUsMeterID,
3166 AllowTransparent: vpv.AllowTransparent,
3167 SchedID: vpv.SchedID,
3168 DHCPv6DUID: vpv.DHCPv6DUID,
3169 PendingDeleteFlow: vpv.PendingDeleteFlow,
3170 DeleteInProgress: vpv.DeleteInProgress,
3171 Blocked: vpv.Blocked,
3172 DhcpPbit: vpv.DhcpPbit,
3173 })
3174}
Tinoj Josephec742f62022-09-29 19:11:10 +05303175
3176func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
3177 isActivated := false
3178 vpv.services.Range(func(key, value interface{}) bool {
3179 svc := value.(*VoltService)
3180 if svc.IsActivated {
3181 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3182 isActivated = true
3183 return false //to exit loop
3184 }
3185 return true
3186 })
3187 return isActivated
3188}