blob: c8e51d4dd7c916fddf5e9620546669274311cc41 [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"
Naveen Sampath04696f72022-06-13 15:19:14 +053023 "strconv"
24 "sync"
25 "time"
26
Akash Sonia8246972023-01-03 10:37:08 +053027 //errorCodes "voltha-go-controller/internal/pkg/errorcodes"
28
Naveen Sampath04696f72022-06-13 15:19:14 +053029 "github.com/google/gopacket"
30 "github.com/google/gopacket/layers"
31 "go.uber.org/atomic"
32
Akash Sonia8246972023-01-03 10:37:08 +053033 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053034 "voltha-go-controller/internal/pkg/controller"
35 cntlr "voltha-go-controller/internal/pkg/controller"
Akash Sonia8246972023-01-03 10:37:08 +053036
37 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053038 "voltha-go-controller/internal/pkg/of"
39 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053040 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053041)
42
43const (
44 // ICMPv6ArpGroupID constant
45 ICMPv6ArpGroupID uint32 = 1
46
47 // Radisys vendor id constant
48 Radisys string = "Radisys"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053049
50 // DPU_MGMT_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053051 DpuMgmtTraffic string = "DPU_MGMT_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053052
53 // DPU_ANCP_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053054 DpuAncpTraffic string = "DPU_ANCP_TRAFFIC"
Tinoj Joseph50d722c2022-12-06 22:53:22 +053055
56 // FTTB_SUBSCRIBER_TRAFFIC serviceType, vnetType constant
vinokuma926cb3e2023-03-29 11:41:06 +053057 FttbSubscriberTraffic string = "FTTB_SUBSCRIBER_TRAFFIC"
Naveen Sampath04696f72022-06-13 15:19:14 +053058)
59
60var (
61 //BroadcastMAC - Broadcast MAC Address
62 BroadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
63)
64
65// NonZeroMacAddress utility to identify if the MAC address is non-zero.
66// We use zero MAC address as an unset MAC address
67func NonZeroMacAddress(h net.HardwareAddr) bool {
68 for i := 0; i < 6; i++ {
69 if h[i] != 0 {
70 return true
71 }
72 }
73 return false
74}
75
76// VNET package manages the different virtual networks that are part of the
77// the network. In the case of VOLT, the networks can be single tagged or
78// double tagged networks. In addition, the networks may be used for unicast
79// and multicast traffic. The unicast traffic further has two models, the
80// 1:1 and N:1 model. In case of a 1:1 model, the outer tag is same for many
81// subscribers and the inner tag is unique to each subscriber for the same
82// outer tag. The N:1 uses the same inner and outer tags, or for that matter
83// a single tag that can also be shared by subscribers. The VNET implementation
84// manages all these possibilities and the associated configuration.
85
86const (
87 // PbitMatchNone constant
88 PbitMatchNone of.PbitType = 8
89 // PbitMatchAll constant
90 PbitMatchAll of.PbitType = 0xFF
91)
92
93// SVlan - Value of the outer tag if double tagged or the only tag if single
94// tagged
95// SVlanTpid - SVlan Tag Protocol Identifier
96// CVlan - Value of the inner tag. Set to VlanNone if single tagged
97// DhcpRelay - Set to true if the DHCP relay is enabled on the virtual network
98// MacLearning - Set to true if the flows should include MAC address
99// UsDhcpPbit - The pbit used for US DHCP packets
100// DsDhcpPbit - The pbit used for DS DHCP packets
101
102// VnetConfig structure
103type VnetConfig struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530104 CtrlPktPbitRemark map[of.PbitType]of.PbitType
Naveen Sampath04696f72022-06-13 15:19:14 +0530105 Name string
vinokuma926cb3e2023-03-29 11:41:06 +0530106 VnetType string
Naveen Sampath04696f72022-06-13 15:19:14 +0530107 Encapsulation string
vinokuma926cb3e2023-03-29 11:41:06 +0530108 DevicesList []string //List of serial number of devices on which this vnet is applied
Naveen Sampath04696f72022-06-13 15:19:14 +0530109 UsDhcpPbit []of.PbitType
110 DsDhcpPbit []of.PbitType
111 UsIGMPPbit []of.PbitType
112 DsIGMPPbit []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530113 ONTEtherTypeClassification int
114 MacLearning MacLearningType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530115 UsPonCTagPriority of.PbitType
116 UsPonSTagPriority of.PbitType
117 DsPonCTagPriority of.PbitType
118 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530119 SVlan of.VlanType
120 CVlan of.VlanType
121 UniVlan of.VlanType
122 SVlanTpid layers.EthernetType
123 VlanControl VlanControl
124 DhcpRelay bool
125 ArpLearning bool
126 AllowTransparent bool
127 PppoeIa bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530128}
129
130// VnetOper structure
131type VnetOper struct {
132 PendingDeleteFlow map[string]map[string]bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530133 AssociatedPorts map[string]bool `json:"-"`
vinokuma926cb3e2023-03-29 11:41:06 +0530134 PendingDeviceToDelete string
135 VnetLock sync.RWMutex `json:"-"`
136 VnetPortLock sync.RWMutex `json:"-"`
137 DeleteInProgress bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530138}
139
140// VoltVnet sructure
141type VoltVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530142 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530143 VnetConfig
144 VnetOper
Naveen Sampath04696f72022-06-13 15:19:14 +0530145}
146
147const (
148 // EncapsulationPPPoEIA constant
149 EncapsulationPPPoEIA string = "PPPoE-IA"
150 // EncapsulationPPPoE constant
151 EncapsulationPPPoE string = "PPPoE"
152 // EncapsulationIPoE constant
153 EncapsulationIPoE string = "IPoE"
154)
155
156// NewVoltVnet is constructor for the VNET structure
157func NewVoltVnet(cfg VnetConfig) *VoltVnet {
158 var vv VoltVnet
159 vv.VnetConfig = cfg
160 if vv.PendingDeleteFlow == nil {
161 vv.PendingDeleteFlow = make(map[string]map[string]bool)
162 }
163 vv.DeleteInProgress = false
164 if cfg.Encapsulation == EncapsulationPPPoEIA {
165 vv.PppoeIa = true
166 }
167 vv.AssociatedPorts = make(map[string]bool)
168 return &vv
169}
170
vinokuma926cb3e2023-03-29 11:41:06 +0530171// associatePortToVnet - associate a port to Vnet
Naveen Sampath04696f72022-06-13 15:19:14 +0530172func (vv *VoltVnet) associatePortToVnet(port string) {
173 vv.VnetPortLock.Lock()
174 if vv.AssociatedPorts == nil {
175 vv.AssociatedPorts = make(map[string]bool)
176 }
177 vv.AssociatedPorts[port] = true
178 vv.VnetPortLock.Unlock()
179}
180
vinokuma926cb3e2023-03-29 11:41:06 +0530181// disassociatePortFromVnet - disassociate a port from Vnet and return true if the association map is empty
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530182func (vv *VoltVnet) disassociatePortFromVnet(cntx context.Context, device string, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530183 vv.VnetPortLock.Lock()
184 delete(vv.AssociatedPorts, port)
185 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})
186 vv.VnetPortLock.Unlock()
187
188 if vv.DeleteInProgress {
189 if !vv.isAssociatedPortsPresent() {
190 if len(vv.PendingDeleteFlow[device]) == 0 {
191 logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vv.Name})
192 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530193 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530194 } else {
195 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "PendingDeleteFlow": vv.PendingDeleteFlow})
196 }
197 } else {
198 vv.VnetPortLock.RLock()
199 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts})
200 vv.VnetPortLock.RUnlock()
201 }
202 }
203}
204
205func (vv *VoltVnet) isAssociatedPortsPresent() bool {
206 vv.VnetPortLock.RLock()
207 defer vv.VnetPortLock.RUnlock()
208 return len(vv.AssociatedPorts) != 0
209}
210
211// WriteToDb commit the VNET to the database
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530212func (vv *VoltVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530213 if vv.DeleteInProgress {
214 logger.Warnw(ctx, "Skipping Redis Update for Vnet, Vnet delete in progress", log.Fields{"Vnet": vv.Name})
215 return
216 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530217 vv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530218}
219
vinokuma926cb3e2023-03-29 11:41:06 +0530220// ForceWriteToDb force commit a vnet to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530221func (vv *VoltVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530222 vv.VnetPortLock.RLock()
223 defer vv.VnetPortLock.RUnlock()
224 vv.Version = database.PresentVersionMap[database.VnetPath]
225 logger.Debugw(ctx, "Updating VNET....", log.Fields{"vnet": vv})
226 if b, err := json.Marshal(vv); err == nil {
Akash Sonia8246972023-01-03 10:37:08 +0530227 if err := db.PutVnet(cntx, vv.Name, string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530228 logger.Warnw(ctx, "Add Vnet to DB failed", log.Fields{"vnet name": vv.Name, "Error": err})
229 }
230 }
231}
232
233// VnetKey creates the key using the two VLAN tags
234// We append the two VLAN tags to create a single key
235func VnetKey(otag of.VlanType, itag of.VlanType, utag of.VlanType) string {
236 return strconv.Itoa(int(otag)) + "-" + strconv.Itoa(int(itag)) + "-" + strconv.Itoa(int(utag))
237}
238
239// GetVnet get VNET configuration related functionality associated with VOLT application
240func (va *VoltApplication) GetVnet(otag of.VlanType, itag of.VlanType, utag of.VlanType) *VoltVnet {
241 // When matching VNET, it is expected to match first just the outer
242 // tag, and then the combination to make sure there is no conflict
243 // for the new configuration.
244 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, of.VlanNone, utag)); ok {
245 return vnet.(*VoltVnet)
246 }
247 if vnet, ok := va.VnetsByTag.Load(VnetKey(otag, itag, utag)); ok {
248 return vnet.(*VoltVnet)
249 }
250 return nil
251}
252
253// The VNET may also be assigned name for easier references. For now,
254// the VNET is mainly identified by the two VLANs.
255
256// GetVnetByName to get vnet by name
257func (va *VoltApplication) GetVnetByName(name string) *VoltVnet {
258 if vnet, ok := va.VnetsByName.Load(name); ok {
259 return vnet.(*VoltVnet)
260 }
261 return nil
262}
263
264// storeVnetConfig to store vnet config
265func (va *VoltApplication) storeVnetConfig(cfg VnetConfig, vv *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530266 var vnetMap *util.ConcurrentMap
267
268 va.VnetsByTag.Store(VnetKey(cfg.SVlan, cfg.CVlan, cfg.UniVlan), vv)
269 va.VnetsByName.Store(cfg.Name, vv)
270
271 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vv.SVlan); !ok {
272 vnetMap = util.NewConcurrentMap()
273 } else {
274 vnetMap = vnetMapIntf.(*util.ConcurrentMap)
275 }
276 vnetMap.Set(vv, true)
277 va.VnetsBySvlan.Set(vv.SVlan, vnetMap)
278}
279
280// deleteVnetConfig to delete vnet config
281func (va *VoltApplication) deleteVnetConfig(vnet *VoltVnet) {
282 va.VnetsByTag.Delete(VnetKey(vnet.SVlan, vnet.CVlan, vnet.UniVlan))
283 va.VnetsByName.Delete(vnet.Name)
284
285 if vnetMapIntf, ok := va.VnetsBySvlan.Get(vnet.SVlan); ok {
286 vnetMap := vnetMapIntf.(*util.ConcurrentMap)
287 vnetMap.Remove(vnet)
288 va.VnetsBySvlan.Set(vnet.SVlan, vnetMap)
289 }
290}
291
292// AddVnet to add a VNET to the list of VNETs configured.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530293func (va *VoltApplication) AddVnet(cntx context.Context, cfg VnetConfig, oper *VnetOper) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530294 AppMutex.VnetMutex.Lock()
295 var vv *VoltVnet
296 devicesToHandle := []string{}
297 vv = va.GetVnetByName(cfg.Name)
298 if vv != nil {
299 //Could be for another OLT or could be case of backup-restore
300 for _, serialNum := range cfg.DevicesList {
301 if isDeviceInList(serialNum, vv.DevicesList) {
302 //This is backup restore scenario, just update the profile
303 logger.Info(ctx, "Add Vnet : Profile Name already exists with OLT, update-the-profile")
304 continue
305 }
306 devicesToHandle = append(devicesToHandle, serialNum)
307 }
308 if len(devicesToHandle) == 0 {
Tinoj Joseph1d108322022-07-13 10:07:39 +0530309 logger.Debugw(ctx, "Ignoring Duplicate VNET by name ", log.Fields{"Vnet": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530310 AppMutex.VnetMutex.Unlock()
311 return nil
312 }
313 }
314
315 if vv == nil {
316 vv = NewVoltVnet(cfg)
317 if oper != nil {
318 vv.PendingDeleteFlow = oper.PendingDeleteFlow
319 vv.DeleteInProgress = oper.DeleteInProgress
320 vv.AssociatedPorts = oper.AssociatedPorts
321 vv.PendingDeviceToDelete = oper.PendingDeviceToDelete
322 }
323 devicesToHandle = append(devicesToHandle, cfg.DevicesList...)
324 } else {
325 vv.DevicesList = append(vv.DevicesList, devicesToHandle...)
326 }
327
328 va.storeVnetConfig(cfg, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530329 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530330
331 logger.Infow(ctx, "Added VNET TO DB", log.Fields{"cfg": cfg, "devicesToHandle": devicesToHandle})
332
333 //va.PushDevFlowForVlan(vv)
334 AppMutex.VnetMutex.Unlock()
335 return nil
336}
337
338// DelVnet to delete a VNET from the list of VNETs configured
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530339func (va *VoltApplication) DelVnet(cntx context.Context, name, deviceSerialNum string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530340 logger.Infow(ctx, "Deleting Vnet", log.Fields{"Vnet": name})
341 AppMutex.VnetMutex.Lock()
342 if vnetIntf, ok := va.VnetsByName.Load(name); ok {
343 vnet := vnetIntf.(*VoltVnet)
vinokuma926cb3e2023-03-29 11:41:06 +0530344 // Delete from mvp list
Naveen Sampath04696f72022-06-13 15:19:14 +0530345 vnet.DevicesList = util.RemoveFromSlice(vnet.DevicesList, deviceSerialNum)
346
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530347 va.DeleteDevFlowForVlanFromDevice(cntx, vnet, deviceSerialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +0530348 if len(vnet.DevicesList) == 0 {
349 vnet.DeleteInProgress = true
350 vnet.PendingDeviceToDelete = deviceSerialNum
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530351 vnet.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530352 vnet.VnetPortLock.RLock()
353 if len(vnet.PendingDeleteFlow) == 0 && !vnet.isAssociatedPortsPresent() {
354 logger.Warnw(ctx, "Deleting Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
355 va.deleteVnetConfig(vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530356 _ = db.DelVnet(cntx, vnet.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530357 } else {
358 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vnet.Name, "AssociatedPorts": vnet.AssociatedPorts, "PendingDelFlows": vnet.PendingDeleteFlow})
359 }
360 vnet.VnetPortLock.RUnlock()
361 } else {
vinokuma926cb3e2023-03-29 11:41:06 +0530362 // Update the devicelist in db
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530363 vnet.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530364 }
365 }
vinokuma926cb3e2023-03-29 11:41:06 +0530366 // TODO: if no vnets are present on device remove icmpv6 group from device
Naveen Sampath04696f72022-06-13 15:19:14 +0530367 AppMutex.VnetMutex.Unlock()
368 return nil
369}
370
371// UpdateVnet to update the VNET with associated service count
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530372func (va *VoltApplication) UpdateVnet(cntx context.Context, vv *VoltVnet) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530373 va.storeVnetConfig(vv.VnetConfig, vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530374 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530375 logger.Infow(ctx, "Updated VNET TO DB", log.Fields{"vv": vv.VnetConfig})
376 return nil
377}
378
379// ------------------------------------------------------------
380// Manifestation of a VNET on a port is handled below
381// ------------------------------------------------------------
382//
383// The VNET on a port handles everything that is done for a VNET
384// such as DHCP relay state machine, MAC addresses, IP addresses
385// learnt, so on.
386
387// DhcpStatus type
388type DhcpStatus uint8
389
390const (
391 // DhcpStatusNone constant
392 DhcpStatusNone DhcpStatus = 0
393 // DhcpStatusAcked constant
394 DhcpStatusAcked DhcpStatus = 1
395 // DhcpStatusNacked constant
396 DhcpStatusNacked DhcpStatus = 2
397 // EthTypeNone constant
398 EthTypeNone int = 0
399 // EthTypeIPoE constant
400 EthTypeIPoE int = 1
401 // EthTypePPPoE constant
402 EthTypePPPoE int = 2
403)
404
405// VoltPortVnet structure
406type VoltPortVnet struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530407 PendingDeleteFlow map[string]bool
408 servicesCount *atomic.Uint64
409 services sync.Map
Naveen Sampath04696f72022-06-13 15:19:14 +0530410 Device string
411 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +0530412 VnetName string
vinokuma926cb3e2023-03-29 11:41:06 +0530413 VnetType string
414 MvlanProfileName string
415 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +0530416 DhcpExpiryTime time.Time
417 Dhcp6ExpiryTime time.Time
Naveen Sampath04696f72022-06-13 15:19:14 +0530418 Ipv4Addr net.IP
419 Ipv6Addr net.IP
420 MacAddr net.HardwareAddr
421 LearntMacAddr net.HardwareAddr
vinokuma926cb3e2023-03-29 11:41:06 +0530422 CircuitID []byte //Will not be used
423 RemoteID []byte //Will not be used
424 VpvLock sync.Mutex `json:"-"`
425 PendingFlowLock sync.RWMutex `json:"-"`
426 SchedID int
Naveen Sampath04696f72022-06-13 15:19:14 +0530427 ONTEtherTypeClassification int
vinokuma926cb3e2023-03-29 11:41:06 +0530428 MacLearning MacLearningType
429 PonPort uint32
430 McastUsMeterID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530431 McastTechProfileID uint16
432 McastPbit of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530433 SVlanTpid layers.EthernetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530434 DhcpPbit of.PbitType
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530435 UsPonCTagPriority of.PbitType
436 UsPonSTagPriority of.PbitType
437 DsPonCTagPriority of.PbitType
438 DsPonSTagPriority of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530439 SVlan of.VlanType
440 CVlan of.VlanType
441 UniVlan of.VlanType
442 VlanControl VlanControl
443 RelayState DhcpRelayState
444 DhcpStatus DhcpStatus
445 PPPoeState PppoeIaState
446 RelayStatev6 Dhcpv6RelayState
447 DHCPv6DUID [MaxLenDhcpv6DUID]byte
448 DhcpRelay bool
449 ArpRelay bool
450 PppoeIa bool
451 DeleteInProgress bool
452 Blocked bool
453 AllowTransparent bool
454 IgmpEnabled bool
455 IgmpFlowsApplied bool
456 McastService bool
457 FlowsApplied bool
458 IsOption82Disabled bool //Will not be used
Naveen Sampath04696f72022-06-13 15:19:14 +0530459}
460
vinokuma926cb3e2023-03-29 11:41:06 +0530461// VlanControl vlan control type
Naveen Sampath04696f72022-06-13 15:19:14 +0530462type VlanControl uint8
463
464const (
465 // None constant
466 // ONU and OLT will passthrough UNIVLAN as is to BNG
467 None VlanControl = iota
468
469 // ONUCVlanOLTSVlan constant
470 // Tagged traffic, ONU will replace UNIVLAN with CVLAN and OLT will add SVLAN
471 // Untagged traffic, ONU will add CVLAN and OLT will add SVLAN
472 ONUCVlanOLTSVlan
473
474 // OLTCVlanOLTSVlan constant
475 // Tagged traffic, ONU will passthrough UNIVLAN as is to OLT and
476 // OLT will replace UNIVLAN with CVLAN and add SVLAN
477 OLTCVlanOLTSVlan
478
479 // ONUCVlan constant
480 // Tagged traffic, ONU will replace UNIVLAN with CVLAN
481 // Untagged traffic, ONU will add CVLAN
482 ONUCVlan
483
484 // OLTSVlan constant
485 // UnTagged traffic, OLT will add the SVLAN
486 OLTSVlan
487)
488
489// NewVoltPortVnet is constructor for VoltPortVnet
490func NewVoltPortVnet(vnet *VoltVnet) *VoltPortVnet {
491 var vpv VoltPortVnet
492
493 vpv.VnetName = vnet.Name
494 vpv.SVlan = vnet.SVlan
495 vpv.CVlan = vnet.CVlan
496 vpv.UniVlan = vnet.UniVlan
497 vpv.SVlanTpid = vnet.SVlanTpid
498 vpv.DhcpRelay = vnet.DhcpRelay
499 vpv.DhcpStatus = DhcpStatusNone
500 vpv.PPPoeState = PppoeIaStateNone
501 vpv.ArpRelay = vnet.ArpLearning
502 vpv.PppoeIa = vnet.PppoeIa
503 vpv.VlanControl = vnet.VlanControl
504 vpv.ONTEtherTypeClassification = vnet.ONTEtherTypeClassification
505 vpv.AllowTransparent = vnet.AllowTransparent
506 vpv.FlowsApplied = false
507 vpv.IgmpEnabled = false
508 vpv.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
509 vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Naveen Sampath04696f72022-06-13 15:19:14 +0530510 vpv.servicesCount = atomic.NewUint64(0)
511 vpv.SchedID = 0
512 vpv.PendingDeleteFlow = make(map[string]bool)
513 vpv.DhcpPbit = vnet.UsDhcpPbit[0]
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530514 vpv.UsPonCTagPriority = vnet.UsPonCTagPriority
515 vpv.UsPonSTagPriority = vnet.UsPonSTagPriority
516 vpv.DsPonCTagPriority = vnet.UsPonCTagPriority
517 vpv.DsPonSTagPriority = vnet.UsPonSTagPriority
518
519 vpv.VnetType = vnet.VnetType
Naveen Sampath04696f72022-06-13 15:19:14 +0530520 return &vpv
521}
522
523func (vpv *VoltPortVnet) setDevice(device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530524 if vpv.Device != device && vpv.Device != "" {
525 GetApplication().DisassociateVpvsFromDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530526 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530527 vpv.printAssociatedVPVs(false)
528 }
529
Tinoj Josephec742f62022-09-29 19:11:10 +0530530 logger.Infow(ctx, "Associating VPV and Device", log.Fields{"Device": device, "Port": vpv.Port, "SVlan": vpv.SVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +0530531
532 vpv.Device = device
533 GetApplication().AssociateVpvsToDevice(device, vpv)
vinokuma926cb3e2023-03-29 11:41:06 +0530534 // TEMP:
Naveen Sampath04696f72022-06-13 15:19:14 +0530535 vpv.printAssociatedVPVs(true)
536}
537
vinokuma926cb3e2023-03-29 11:41:06 +0530538// TODO - Nav - Temp
Naveen Sampath04696f72022-06-13 15:19:14 +0530539func (vpv *VoltPortVnet) printAssociatedVPVs(add bool) {
540 logger.Infow(ctx, "Start----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
541 if vMap := GetApplication().GetAssociatedVpvsForDevice(vpv.Device, vpv.SVlan); vMap != nil {
542 vMap.Range(func(key, value interface{}) bool {
543 vpvEntry := key.(*VoltPortVnet)
544 logger.Infow(ctx, "Associated VPVs", log.Fields{"SVlan": vpvEntry.SVlan, "CVlan": vpvEntry.CVlan, "UniVlan": vpvEntry.UniVlan})
545 return true
546 })
547 }
548 logger.Infow(ctx, "End----Printing all associated VPV", log.Fields{"Device": vpv.Device, "Add": add})
Naveen Sampath04696f72022-06-13 15:19:14 +0530549}
550
551// GetCircuitID : The interface to be satisfied by the VoltPortVnet to be a DHCP relay
552// session is implemented below. The main functions still remain in
553// the service.go file.
554func (vpv *VoltPortVnet) GetCircuitID() []byte {
555 return []byte(vpv.CircuitID)
556}
557
558// GetRemoteID to get remote id
559func (vpv *VoltPortVnet) GetRemoteID() []byte {
560 return []byte(vpv.RemoteID)
561}
562
563// GetDhcpState to get dhcp state
564func (vpv *VoltPortVnet) GetDhcpState() DhcpRelayState {
565 return vpv.RelayState
566}
567
568// SetDhcpState to set the dhcp state
569func (vpv *VoltPortVnet) SetDhcpState(state DhcpRelayState) {
570 vpv.RelayState = state
571}
572
573// GetPppoeIaState to get pppoeia state
574func (vpv *VoltPortVnet) GetPppoeIaState() PppoeIaState {
575 return vpv.PPPoeState
576}
577
578// SetPppoeIaState to set pppoeia state
579func (vpv *VoltPortVnet) SetPppoeIaState(state PppoeIaState) {
580 vpv.PPPoeState = state
581}
582
583// GetDhcpv6State to get dhcpv6 state
584func (vpv *VoltPortVnet) GetDhcpv6State() Dhcpv6RelayState {
585 return vpv.RelayStatev6
586}
587
588// SetDhcpv6State to set dhcpv6 state
589func (vpv *VoltPortVnet) SetDhcpv6State(state Dhcpv6RelayState) {
590 vpv.RelayStatev6 = state
591}
592
593// DhcpResultInd for dhcp result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530594func (vpv *VoltPortVnet) DhcpResultInd(cntx context.Context, res *layers.DHCPv4) {
595 vpv.ProcessDhcpResult(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530596}
597
598// Dhcpv6ResultInd for dhcpv6 result indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530599func (vpv *VoltPortVnet) Dhcpv6ResultInd(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
600 vpv.ProcessDhcpv6Result(cntx, ipv6Addr, leaseTime)
Naveen Sampath04696f72022-06-13 15:19:14 +0530601}
602
603// GetNniVlans to get nni vlans
604func (vpv *VoltPortVnet) GetNniVlans() (uint16, uint16) {
605 switch vpv.VlanControl {
606 case ONUCVlanOLTSVlan,
607 OLTCVlanOLTSVlan:
608 return uint16(vpv.SVlan), uint16(vpv.CVlan)
609 case ONUCVlan,
610 None:
611 return uint16(vpv.SVlan), uint16(of.VlanNone)
612 case OLTSVlan:
613 return uint16(vpv.SVlan), uint16(of.VlanNone)
614 }
615 return uint16(of.VlanNone), uint16(of.VlanNone)
616}
617
618// GetService to get service
619func (vpv *VoltPortVnet) GetService(name string) (*VoltService, bool) {
620 service, ok := vpv.services.Load(name)
621 if ok {
622 return service.(*VoltService), ok
623 }
624 return nil, ok
625}
626
627// AddService to add service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530628func (vpv *VoltPortVnet) AddService(cntx context.Context, service *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530629 vpv.services.Store(service.Name, service)
630 vpv.servicesCount.Inc()
631 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()})
632}
633
634// DelService to delete service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530635func (vpv *VoltPortVnet) DelService(cntx context.Context, service *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530636 vpv.services.Delete(service.Name)
637 vpv.servicesCount.Dec()
638
639 // If the only Igmp Enabled service is removed, remove the Igmp trap flow along with it
640 if service.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530641 if err := vpv.DelIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530642 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530643 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
644 }
645
646 vpv.IgmpEnabled = false
647 }
648 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()})
649}
650
651// ProcessDhcpResult to process dhcp results
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530652func (vpv *VoltPortVnet) ProcessDhcpResult(cntx context.Context, res *layers.DHCPv4) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530653 msgType := DhcpMsgType(res)
654 if msgType == layers.DHCPMsgTypeAck {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530655 vpv.ProcessDhcpSuccess(cntx, res)
Naveen Sampath04696f72022-06-13 15:19:14 +0530656 } else if msgType == layers.DHCPMsgTypeNak {
657 vpv.DhcpStatus = DhcpStatusNacked
658 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530659 vpv.WriteToDb(cntx)
660}
661
662// RangeOnServices to call a function on all services on the vpv
663func (vpv *VoltPortVnet) RangeOnServices(cntx context.Context, callback func(cntx context.Context, key, value interface{}) bool) {
664 vpv.services.Range(func(key, value interface{}) bool {
665 return callback(cntx, key, value)
666 })
Naveen Sampath04696f72022-06-13 15:19:14 +0530667}
668
669// ProcessDhcpSuccess : Learn the IPv4 address allocated to the services and update the
670// the services with the same. This also calls for adding flows
671// for the services as the DHCP procedure is completed
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530672func (vpv *VoltPortVnet) ProcessDhcpSuccess(cntx context.Context, res *layers.DHCPv4) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530673 vpv.DhcpStatus = DhcpStatusAcked
674 vpv.Ipv4Addr, _ = GetIpv4Addr(res)
675 logger.Infow(ctx, "Received IPv4 Address", log.Fields{"IP Address": vpv.Ipv4Addr.String()})
676 logger.Infow(ctx, "Services Configured", log.Fields{"Count": vpv.servicesCount.Load()})
677
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530678 vpv.RangeOnServices(cntx, vpv.updateIPv4AndProvisionFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530679 vpv.ProcessDhcpv4Options(res)
680}
681
682// ProcessDhcpv4Options : Currently we process lease time and store the validity of the
683// IP address allocated.
684func (vpv *VoltPortVnet) ProcessDhcpv4Options(res *layers.DHCPv4) {
685 for _, o := range res.Options {
686 switch o.Type {
687 case layers.DHCPOptLeaseTime:
688 leasetime := GetIPv4LeaseTime(o)
689 vpv.DhcpExpiryTime = time.Now().Add((time.Duration(leasetime) * time.Second))
690 logger.Infow(ctx, "Lease Expiry Set", log.Fields{"Time": vpv.DhcpExpiryTime})
691 }
692 }
693}
694
695// ProcessDhcpv6Result : Read the IPv6 address allocated to the device and store it on the
696// VNET. The same IPv6 address is also passed to the services. When a
697// service is fetched all the associated information such as MAC address,
698// IPv4 address and IPv6 addresses can be provided.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530699func (vpv *VoltPortVnet) ProcessDhcpv6Result(cntx context.Context, ipv6Addr net.IP, leaseTime uint32) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530700 // TODO: Status based hanlding of flows
701 vpv.Dhcp6ExpiryTime = time.Now().Add((time.Duration(leaseTime) * time.Second))
702 vpv.Ipv6Addr = ipv6Addr
703
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530704 vpv.RangeOnServices(cntx, vpv.updateIPv6AndProvisionFlows)
705 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530706}
707
708// AddSvcUsMeterToDevice to add service upstream meter info to device
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530709func AddSvcUsMeterToDevice(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +0530710 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +0530711 logger.Infow(ctx, "Adding upstream meter profile to device", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530712 if device, _ := GetApplication().GetDeviceFromPort(svc.Port); device != nil {
713 GetApplication().AddMeterToDevice(svc.Port, device.Name, svc.UsMeterID, 0)
714 return true
715 }
716 logger.Errorw(ctx, "Dropping US Meter request: Device not found", log.Fields{"Service": svc})
717 return false
718}
719
720// PushFlowsForPortVnet - triggers flow construction and push for provided VPV
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530721func (vpv *VoltPortVnet) PushFlowsForPortVnet(cntx context.Context, d *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530722 vp := d.GetPort(vpv.Port)
723
724 //Ignore if UNI port is not found or not UP
725 if vp == nil || vp.State != PortStateUp {
726 logger.Warnw(ctx, "Ignoring Vlan UP Ind for VPV: Port Not Found/Ready", log.Fields{"Port": vp})
727 return
728 }
729
730 if vpv.PonPort != 0xFF && vpv.PonPort != vp.PonPort {
731 logger.Errorw(ctx, "UNI port discovered on wrong PON Port. Dropping Flow Configuration for VPV", log.Fields{"Device": d.Name, "Port": vpv.Port, "DetectedPon": vp.PonPort, "ExpectedPon": vpv.PonPort, "Vnet": vpv.VnetName})
732 return
733 }
734
735 //Disable the flag so that flows can be pushed again
736 // vpv.IgmpFlowsApplied = false
737 // vpv.DsFlowsApplied = false
738 // vpv.UsFlowsApplied = false
739 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530740 vpv.PortUpInd(cntx, d, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530741 vpv.VpvLock.Unlock()
742}
743
744// PortUpInd : When a port transistions to UP state, the indication is passed
745// on to this module via the application. We read the VNET configuration
746// again here to apply the latest configuration if the configuration
747// changed. Thus, a reboot of ONT forces the new configuration to get
748// applied.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530749func (vpv *VoltPortVnet) PortUpInd(cntx context.Context, device *VoltDevice, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530750 if vpv.DeleteInProgress {
751 logger.Errorw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
752 return
753 }
754 vpv.setDevice(device.Name)
755 logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
756
757 nni, _ := GetApplication().GetNniPort(device.Name)
758 if nni == "" {
759 logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name})
760 return
761 }
762
Akash Sonia8246972023-01-03 10:37:08 +0530763 if nniPort := device.GetPort(nni); nniPort != nil {
764 //If NNI port is not mached to nb nni port dont send flows
765 devConfig := GetApplication().GetDeviceConfig(device.SerialNum)
766 if devConfig != nil {
Akash Soni53da2852023-03-15 00:31:31 +0530767 if devConfig.UplinkPort != strconv.Itoa(int(nniPort.ID)) {
768 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 +0530769 return
770 }
771 }
772 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530773
Naveen Sampath04696f72022-06-13 15:19:14 +0530774 if vpv.Blocked {
775 logger.Errorw(ctx, "VPV Bocked for Processing. Ignoring flow push request", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
776 return
777 }
778
779 if vpv.DhcpRelay || vpv.ArpRelay || vpv.PppoeIa {
780 // If MAC Learning is true if no MAC is configured, push DS/US DHCP, US HSIA flows without MAC.
781 // DS HSIA flows are installed after learning the MAC.
782 logger.Infow(ctx, "Port Up - Trap Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530783 // no HSIA flows for multicast service and DPU_MGMT Service
vinokuma926cb3e2023-03-29 11:41:06 +0530784 if !vpv.McastService && vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530785 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530786 }
vinokuma926cb3e2023-03-29 11:41:06 +0530787 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530788 vpv.RangeOnServices(cntx, AddMeterToDevice)
789 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530790 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530791 if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
792 logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530793 /*In case of DPU_MGMT_TRAFFIC, need to install both US and DS traffic */
vinokuma926cb3e2023-03-29 11:41:06 +0530794 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530795 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
796 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530797 // US & DS DHCP, US HSIA flows are already installed
798 // install only DS HSIA flow here.
799 // no HSIA flows for multicast service
Akash Soni53da2852023-03-15 00:31:31 +0530800 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530801 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530802 }
803 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530804 } else {
805 // DHCP relay is not configured. This implies that the service must use
806 // 1:1 and does not require MAC learning. In a completely uncommon but
807 // plausible case, the MAC address can be learnt from N:1 without DHCP
808 // relay by configuring any unknown MAC address to be reported. This
809 // however is not seen as a real use case.
810 logger.Infow(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
811 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530812 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530813 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530814 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530815 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530816 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530817 }
818 }
819
820 // Process IGMP proxy - install IGMP trap rules before DHCP trap rules
821 if vpv.IgmpEnabled {
822 logger.Infow(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530823 vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice)
824 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530825 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530826 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
827 }
828
829 if vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530830 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +0530831 }
832 }
833
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530834 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530835}
836
837// PortDownInd : When the port status changes to down, we delete all configured flows
838// The same indication is also passed to the services enqueued for them
839// to take appropriate actions
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530840func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool) {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530841 if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
842 logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
843 return
844 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530845 logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
846 log.Fields{"service count": vpv.servicesCount.Load()})
847
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530848 //vpv.RangeOnServices(cntx, DelAllFlows)
849 vpv.DelTrapFlows(cntx)
850 vpv.DelHsiaFlows(cntx)
851 vpv.WriteToDb(cntx)
852 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530853}
854
855// SetMacAddr : The MAC address is set when a MAC address is learnt through the
856// packets received from the network. Currently, DHCP packets are
857// only packets we learn the MAC address from
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530858func (vpv *VoltPortVnet) SetMacAddr(cntx context.Context, addr net.HardwareAddr) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530859 //Store Learnt MAC address and return if MACLearning is not enabled
860 vpv.LearntMacAddr = addr
861 if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
862 (NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
863 return
864 }
865
866 // Compare the two MAC addresses to see if it is same
867 // If they are same, we just return. If not, we perform
868 // actions to address the change in MAC address
869 //if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
870 if !util.MacAddrsMatch(vpv.MacAddr, addr) {
871 expectedPort := GetApplication().GetMacInPortMap(addr)
872 if expectedPort != "" && expectedPort != vpv.Port {
873 logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
874 log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
875 return
876 }
877 if NonZeroMacAddress(vpv.MacAddr) {
878 logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
879
880 // The newly learnt MAC address is different than earlier one.
881 // The existing MAC based HSIA flows need to be undone as the device
882 // may have been changed
883 // Atleast one HSIA flow should be present in adapter to retain the TP and GEM
884 // hence delete one after the other
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530885 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530886 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530887 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
888 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
889 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530890 GetApplication().DeleteMacInPortMap(vpv.MacAddr)
891 } else {
892 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530893 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
Naveen Sampath04696f72022-06-13 15:19:14 +0530894 logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
895 }
896 GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
897 } else {
898 logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
899 }
900
901 _, err := GetApplication().GetDeviceFromPort(vpv.Port)
902 if err != nil {
903 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
Akash Sonia8246972023-01-03 10:37:08 +0530904 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530905 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
906 return
907 }
908 // Ds Hsia flows has to be pushed
909 if vpv.FlowsApplied {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530910 // In case of DPU_MGMT_TRAFFIC install both US and DS Flows
vinokuma926cb3e2023-03-29 11:41:06 +0530911 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530912 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
913 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530914 // no HSIA flows for multicast service
915 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530916 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530917 }
918 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530919 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530920}
921
922// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
923func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
924 if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
925 return false
926 }
927 return true
928}
929
930// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
931func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
932 if len(cvlan) != 1 && !vpv.AllowTransparent {
933 return false
934 }
935 if vpv.CVlan != cvlan[0] {
936 return false
937 }
938 return true
939}
940
941// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
942func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +0530943 var service *VoltService
944 pbitFound := false
945 matchpbitsFunc := func(key, value interface{}) bool {
946 svc := value.(*VoltService)
947 for _, pbit := range svc.Pbits {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530948 if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530949 logger.Infow(ctx, "Pbit match found with service",
950 log.Fields{"Pbit": priority, "serviceName": svc.Name})
951 pbitFound = true
952 service = svc
953 return false //Returning false to stop the Range loop
954 }
955 }
956 return true
957 }
958 _ = pbitFound
959 vpv.services.Range(matchpbitsFunc)
960 return service
961}
962
963// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
964func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Naveen Sampath04696f72022-06-13 15:19:14 +0530965 dsPbit := uint8(0)
966 matchpbitsFunc := func(key, value interface{}) bool {
967 svc := value.(*VoltService)
968 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
969 logger.Infow(ctx, "Pbit match found with service",
970 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
971 dsPbit = uint8(remarkPbit)
972 return false //Returning false to stop the Range loop
973 }
974 // When no remarking info is available, remark the incoming pbit
975 // to highest pbit configured for the subscriber (across all subservices associated)
976 svcPbit := uint8(svc.Pbits[0])
977 if svcPbit > dsPbit {
978 dsPbit = svcPbit
979 }
980 return true
981 }
982 vpv.services.Range(matchpbitsFunc)
983 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
984 return dsPbit
985}
986
987// AddSvc adds a service on the VNET on a port. The addition is
988// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530989func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530990 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530991 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +0530992 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
993
994 // Learn the circuit-id and remote-id from the service
995 // TODO: There must be a better way of doing this. This
996 // may be explored
997 if svc.IgmpEnabled {
998 vpv.IgmpEnabled = true
999 }
1000 // first time service activation MacLearning will have default value as None.
1001 // to handle reciliency if anythng other then None we should retain it .
1002 if svc.MacLearning == MacLearningNone {
1003 if !vpv.DhcpRelay && !vpv.ArpRelay {
1004 svc.MacLearning = MacLearningNone
1005 } else if vpv.MacLearning == Learn {
1006 svc.MacLearning = Learn
1007 } else if vpv.MacLearning == ReLearn {
1008 svc.MacLearning = ReLearn
1009 }
1010 }
1011
vinokuma926cb3e2023-03-29 11:41:06 +05301012 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301013 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1014 svc.MacAddr = vpv.MacAddr
1015 } else if vpv.servicesCount.Load() == 1 {
1016 vpv.MacAddr = svc.MacAddr
1017 }
1018
1019 vpv.MacLearning = svc.MacLearning
1020 vpv.PonPort = svc.PonPort
1021 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301022 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301023 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301024 if svc.McastService {
1025 vpv.McastService = true
1026 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301027 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301028 vpv.McastPbit = svc.Pbits[0]
1029 vpv.McastUsMeterID = svc.UsMeterID
1030 vpv.SchedID = svc.SchedID
1031 }
1032 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1033 svc.AllowTransparent = vpv.AllowTransparent
1034 svc.SVlanTpid = vpv.SVlanTpid
1035
vinokuma926cb3e2023-03-29 11:41:06 +05301036 // Ensure configuring the mvlan profile only once
1037 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301038 if svc.MvlanProfileName != "" {
1039 if vpv.MvlanProfileName == "" {
1040 vpv.MvlanProfileName = svc.MvlanProfileName
1041 } else {
1042 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1043 }
1044 }
1045
Akash Sonia8246972023-01-03 10:37:08 +05301046 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301047 if err != nil {
1048 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301049 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1050 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301051 return
1052 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301053 if !svc.IsActivated {
1054 logger.Warn(ctx, "Not pushing Service Flows: Service Not activated")
1055 return
1056 }
Akash Sonia8246972023-01-03 10:37:08 +05301057
vinokuma926cb3e2023-03-29 11:41:06 +05301058 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301059 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1060
Akash Soni53da2852023-03-15 00:31:31 +05301061 if devConfig.UplinkPort != voltDevice.NniPort {
1062 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 +05301063 return
1064 }
vinokuma926cb3e2023-03-29 11:41:06 +05301065 // Push Service Flows if DHCP relay is not configured
1066 // or already DHCP flows are configured for the VPV
1067 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301068 if vpv.FlowsApplied {
1069 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301070 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301071 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301072 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301073 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1074 }
1075 }
1076 }
1077
vinokuma926cb3e2023-03-29 11:41:06 +05301078 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301079 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1080 // service with Igmp Enabled needs to be installed
1081 if svc.IgmpEnabled && vpv.FlowsApplied {
1082 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301083 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301084 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301085 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1086 }
1087
1088 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301089 // For McastService, send Service Activated indication once IGMP US flow is pushed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301090 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +05301091 }
1092 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301093 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301094}
1095
1096// setLearntMAC to set learnt mac
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301097func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301098 svc := value.(*VoltService)
1099 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301100 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301101 return true
1102}
1103
1104// PostAccessConfigSuccessInd for posting access config success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301105func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301106 return true
1107}
1108
1109// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301110func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301111 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301112 logger.Infow(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301113 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301114 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301115
1116 return true
1117}
1118
1119// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301120func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301121 svc := value.(*VoltService)
1122 svc.SetIpv6Addr(vpv.Ipv6Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301123 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301124
1125 return true
1126}
1127
1128// AddUsHsiaFlows to add upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129func AddUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301130 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301131 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301132 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1133 }
1134 return true
1135}
1136
1137// AddDsHsiaFlows to add downstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301138func AddDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301139 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301140 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301141 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1142 }
1143 return true
1144}
1145
1146// ClearFlagsInService to clear the flags used in service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301147func ClearFlagsInService(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301148 svc := value.(*VoltService)
1149 svc.ServiceLock.Lock()
1150 svc.IgmpFlowsApplied = false
1151 svc.DsDhcpFlowsApplied = false
1152 svc.DsHSIAFlowsApplied = false
1153 svc.Icmpv6FlowsApplied = false
1154 svc.UsHSIAFlowsApplied = false
1155 svc.UsDhcpFlowsApplied = false
1156 svc.PendingFlows = make(map[string]bool)
1157 svc.AssociatedFlows = make(map[string]bool)
1158 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301159 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301160 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1161 return true
1162}
1163
1164// DelDsHsiaFlows to delete hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301165func DelDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301166 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301167 if err := svc.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301168 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1169 }
1170 return true
1171}
1172
1173// DelUsHsiaFlows to delete upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301174func DelUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301175 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301176 if err := svc.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301177 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1178 }
1179 return true
1180}
1181
1182// ClearServiceCounters to clear the service counters
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301183func ClearServiceCounters(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301184 svc := value.(*VoltService)
1185 //Delete the per service counter too
1186 GetApplication().ServiceCounters.Delete(svc.Name)
1187 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301188 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301189 }
1190 return true
1191}
1192
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301193// AddMeterToDevice to add meter config to device, used in FTTB case
1194func AddMeterToDevice(cntx context.Context, key, value interface{}) bool {
1195 svc := value.(*VoltService)
Akash Soni53da2852023-03-15 00:31:31 +05301196 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301197 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1198 }
1199 return true
1200}
1201
vinokuma926cb3e2023-03-29 11:41:06 +05301202// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301203func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301204 if !vpv.FlowsApplied || vgcRebooted {
1205 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301206 if err := vpv.AddUsDhcpFlows(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 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301210 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301211 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301212 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1213 }
1214 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1215 log.Fields{"port": vpv.Port})
1216 //vpv.updateICMPv6McGroup(true)
1217 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301218 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301219 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301220 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1221 }
1222 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301223 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301224 if err := vpv.AddUsPppoeFlows(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 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301228 if err := vpv.AddDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301229 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301230 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1231 }
1232 }
1233 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301234 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 }
1236}
1237
vinokuma926cb3e2023-03-29 11:41:06 +05301238// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301239func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301240 // Delete HSIA & DHCP flows before deleting IGMP flows
1241 if vpv.FlowsApplied || vgcRebooted {
1242 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301243 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301244 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1245 "UniVlan": vpv.UniVlan, "Error": err})
1246 }
1247 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1248 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301249 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301250 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301251 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1252 }
1253 //vpv.updateICMPv6McGroup(false)
1254 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301255 if err := vpv.DelUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301256 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301257 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1258 }
1259 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301260 if err := vpv.DelUsPppoeFlows(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 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301264 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301265 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301266 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1267 }
1268 }
1269 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301270 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301271 }
Akash Sonia8246972023-01-03 10:37:08 +05301272 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301273 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1274 "UniVlan": vpv.UniVlan, "Error": err})
1275 }
1276}
1277
1278// DelHsiaFlows deletes the service flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301279func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301280 // no HSIA flows for multicast service
1281 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301282 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
1283 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301284 }
1285}
1286
vinokuma926cb3e2023-03-29 11:41:06 +05301287// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301288func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301289 //send flows deleted indication to submgr
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301290 vpv.RangeOnServices(cntx, ClearServiceCounters)
Naveen Sampath04696f72022-06-13 15:19:14 +05301291}
1292
1293// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301294func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301295 var vd *VoltDevice
1296 device := vpv.Device
1297
1298 if vd = GetApplication().GetDevice(device); vd != nil {
1299 if vd.State != controller.DeviceStateUP {
1300 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})
1301 return nil
1302 }
1303 } else {
1304 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})
1305 return errorCodes.ErrDeviceNotFound
1306 }
1307
1308 flows, err := vpv.BuildUsDhcpFlows()
1309 if err == nil {
1310 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301311 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301312 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301313 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301314 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1315 }
1316 } else {
1317 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301318 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301319 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301320 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301321 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301322 return nil
1323}
1324
1325// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301326func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301327 var vd *VoltDevice
1328 device := vpv.Device
1329
1330 if vd = GetApplication().GetDevice(device); vd != nil {
1331 if vd.State != controller.DeviceStateUP {
1332 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})
1333 return nil
1334 }
1335 } else {
1336 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})
1337 return errorCodes.ErrDeviceNotFound
1338 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301339 if vd.GlobalDhcpFlowAdded {
1340 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301341 return nil
1342 }
1343
1344 flows, err := vpv.BuildDsDhcpFlows()
1345 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301346 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301347 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301348 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301349 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301350 }
1351 } else {
1352 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301353 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301354 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301355 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301356 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301357 if GetApplication().GetVendorID() != Radisys {
1358 vd.GlobalDhcpFlowAdded = true
1359 }
1360 return nil
1361}
1362
1363// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301364func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
1365 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301366 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301367 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1368 }
1369
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301370 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301371 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301372 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1373 }
1374}
1375
1376// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1377// Write the status of the VPV to the DB once the delete is scheduled
1378// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301379func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301380 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1381 if err != nil {
1382 return err
1383 }
1384
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301385 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301386 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301387 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301388 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1389 }
Akash Sonia8246972023-01-03 10:37:08 +05301390
Naveen Sampath04696f72022-06-13 15:19:14 +05301391 return nil
1392}
1393
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301394func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301395 flows, err := vpv.BuildUsDhcpFlows()
1396 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301397 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301398 }
1399 logger.Errorw(ctx, "US DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1400 return err
1401}
Naveen Sampath04696f72022-06-13 15:19:14 +05301402
1403// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1404// Write the status of the VPV to the DB once the delete is scheduled
1405// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301406func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301407 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1408 if err != nil {
1409 return err
1410 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301411 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301412 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301413 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301414 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1415 }
1416 /*
Akash Sonia8246972023-01-03 10:37:08 +05301417 err = vpv.delDsDhcp6Flows(device)
1418 if err != nil {
1419 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1420 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1421 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301422 return nil
1423}
1424
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301425func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301426 flows, err := vpv.BuildDsDhcpFlows()
1427 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301428 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301429 }
1430 logger.Errorw(ctx, "DS DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1431 return err
1432}
1433
1434/*
1435func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1436 flows, err := vpv.BuildDsDhcp6Flows()
1437 if err == nil {
1438 return vpv.RemoveFlows(device, flows)
1439 }
1440 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1441 return err
1442}*/
1443
1444// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301445func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301446 var vd *VoltDevice
1447 device := vpv.Device
1448 if vd = GetApplication().GetDevice(device); vd != nil {
1449 if vd.State != controller.DeviceStateUP {
1450 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})
1451 return nil
1452 }
1453 } else {
1454 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})
1455 return errorCodes.ErrDeviceNotFound
1456 }
1457
1458 flows, err := vpv.BuildUsArpFlows()
1459 if err == nil {
1460 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301461 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301462 return err1
1463 }
1464 } else {
1465 logger.Errorw(ctx, "US ARP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1466 return err
1467 }
1468 return nil
1469}
1470
1471// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1472// Write the status of the VPV to the DB once the delete is scheduled
1473// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301474func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301475 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1476 if err != nil {
1477 return err
1478 }
1479 flows, err := vpv.BuildUsArpFlows()
1480 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301481 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301482 }
1483 logger.Errorw(ctx, "US ARP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1484 return err
1485}
1486
1487// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301488func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301489 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1490
1491 var vd *VoltDevice
1492 device := vpv.Device
1493
1494 if vd = GetApplication().GetDevice(device); vd != nil {
1495 if vd.State != controller.DeviceStateUP {
1496 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})
1497 return nil
1498 }
1499 } else {
1500 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})
1501 return errorCodes.ErrDeviceNotFound
1502 }
1503
1504 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1505 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1506
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301507 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301508 return err1
1509 }
1510 } else {
1511 logger.Errorw(ctx, "US PPPoE Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1512 return err
1513 }
1514 return nil
1515}
1516
1517// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301518func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301519 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1520 var vd *VoltDevice
1521 device := vpv.Device
1522
1523 if vd = GetApplication().GetDevice(device); vd != nil {
1524 if vd.State != controller.DeviceStateUP {
1525 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})
1526 return nil
1527 }
1528 } else {
1529 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})
1530 return errorCodes.ErrDeviceNotFound
1531 }
1532
1533 flows, err := vpv.BuildDsPppoeFlows()
1534 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301535 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301536 return err1
1537 }
1538 } else {
1539 logger.Errorw(ctx, "DS PPPoE Flow Add Failed", log.Fields{"Reason": err.Error()})
1540 return err
1541 }
1542 return nil
1543}
1544
1545// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1546// Write the status of the VPV to the DB once the delete is scheduled
1547// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301548func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301549 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1550 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1551 if err != nil {
1552 return err
1553 }
1554 flows, err := vpv.BuildUsPppoeFlows()
1555 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301556 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301557 }
1558 logger.Errorw(ctx, "US PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1559 return err
1560}
1561
1562// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1563// Write the status of the VPV to the DB once the delete is scheduled
1564// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301565func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301566 logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1567 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1568 if err != nil {
1569 return err
1570 }
1571 flows, err := vpv.BuildDsPppoeFlows()
1572 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301573 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301574 }
1575 logger.Errorw(ctx, "DS PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1576 return err
1577}
1578
1579// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301580func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301581 if !vpv.IgmpFlowsApplied || vgcRebooted {
1582 if vpv.MvlanProfileName == "" {
1583 logger.Info(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
1584 return nil
1585 }
1586 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1587 if err != nil {
1588 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1589 return err
1590 } else if device.State != controller.DeviceStateUP {
1591 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})
1592 return nil
1593 }
1594 flows, err := vpv.BuildIgmpFlows()
1595 if err == nil {
1596 for cookie := range flows.SubFlows {
1597 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1598 cookie := strconv.FormatUint(cookie, 10)
1599 fe := &FlowEvent{
1600 eType: EventTypeUsIgmpFlowAdded,
1601 cookie: cookie,
1602 eventData: vpv,
1603 }
1604 vd.RegisterFlowAddEvent(cookie, fe)
1605 }
1606 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301607 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301608 return err1
1609 }
1610 } else {
1611 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1612 return err
1613 }
1614 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301615 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301616 }
1617 return nil
1618}
1619
1620// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1621// Write the status of the VPV to the DB once the delete is scheduled
1622// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301623func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301624 if vpv.IgmpFlowsApplied || vgcRebooted {
1625 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1626 if err != nil {
1627 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1628 return err
1629 }
1630 flows, err := vpv.BuildIgmpFlows()
1631 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301632 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301633 return err1
1634 }
1635 } else {
1636 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1637 return err
1638 }
1639 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301640 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301641 }
1642 return nil
1643}
1644
1645// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1646// The flows included by this function cover US only as the DS is
1647// created either automatically by the VOLTHA or at the device level
1648// earlier
1649func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
1650 flow := &of.VoltFlow{}
1651 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1652
1653 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
1654 subFlow := of.NewVoltSubFlow()
1655 subFlow.SetTableID(0)
1656
vinokuma926cb3e2023-03-29 11:41:06 +05301657 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301658 subFlow.SetMatchVlan(vpv.CVlan)
1659 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1660 subFlow.SetPcp(vpv.UsPonSTagPriority)
1661 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301662 } else {
1663 subFlow.SetMatchVlan(vpv.UniVlan)
1664 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301665 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301666 }
1667 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301668 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301669 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301670 uniport, err := GetApplication().GetPortID(vpv.Port)
1671 if err != nil {
1672 logger.Errorw(ctx, "Failed to fetch uni port from vpv", log.Fields{"error": err, "port": vpv.Port})
1673 return nil, err
1674 }
1675 subFlow.SetInPort(uniport)
1676 // PortName and PortID to be used for validation of port before flow pushing
1677 flow.PortID = uniport
1678 flow.PortName = vpv.Port
1679 subFlow.SetReportToController()
1680
1681 // Set techprofile, meterid of first service
1682 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301683 vs := value.(*VoltService)
1684 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301685 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301686 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301687 } else {
1688 writemetadata = uint64(vs.TechProfileID) << 32
1689 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301690 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301691 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301692 return false
1693 })
1694
Naveen Sampath04696f72022-06-13 15:19:14 +05301695 // metadata := uint64(uniport)
1696 // subFlow.SetWriteMetadata(metadata)
1697 allowTransparent := 0
1698 if vpv.AllowTransparent {
1699 allowTransparent = 1
1700 }
vinokuma926cb3e2023-03-29 11:41:06 +05301701 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301702 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1703 subFlow.SetTableMetadata(metadata)
1704 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301705 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1706 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1707 subFlow.Priority = of.DhcpFlowPriority
1708
1709 flow.SubFlows[subFlow.Cookie] = subFlow
1710 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1711 return flow, nil
1712}
1713
1714// BuildDsDhcpFlows to build the downstream dhcp flows
1715func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301716 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1717 flow := &of.VoltFlow{}
1718 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1719 subFlow := of.NewVoltSubFlow()
1720 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301721 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301722 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301723 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301724 }
1725 subFlow.SetUdpv4Match()
1726 subFlow.SrcPort = 67
1727 subFlow.DstPort = 68
1728 uniport, _ := GetApplication().GetPortID(vpv.Port)
1729 nni, err := GetApplication().GetNniPort(vpv.Device)
1730 if err != nil {
1731 return nil, err
1732 }
1733 nniport, err := GetApplication().GetPortID(nni)
1734 if err != nil {
1735 return nil, err
1736 }
1737 subFlow.SetInPort(nniport)
1738 // PortName and PortID to be used for validation of port before flow pushing
1739 flow.PortID = uniport
1740 flow.PortName = vpv.Port
1741 // metadata := uint64(uniport)
1742 // subFlow.SetWriteMetadata(metadata)
1743 allowTransparent := 0
1744 if vpv.AllowTransparent {
1745 allowTransparent = 1
1746 }
vinokuma926cb3e2023-03-29 11:41:06 +05301747 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301748 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1749 subFlow.SetTableMetadata(metadata)
1750 subFlow.Priority = of.DhcpFlowPriority
1751 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301752 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301753 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301754 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301755
1756 flow.SubFlows[subFlow.Cookie] = subFlow
1757 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1758
1759 return flow, nil
1760}
1761
1762// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1763// application.
1764func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
1765 flow := &of.VoltFlow{}
1766 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1767
1768 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
1769 subFlow := of.NewVoltSubFlow()
1770 subFlow.SetTableID(0)
1771
1772 subFlow.SetMatchVlan(vpv.UniVlan)
1773 subFlow.SetSetVlan(vpv.CVlan)
1774 subFlow.SetUdpv6Match()
1775 subFlow.SrcPort = 546
1776 subFlow.DstPort = 547
1777 uniport, err := GetApplication().GetPortID(vpv.Port)
1778 if err != nil {
1779 return nil, err
1780 }
1781 // Set techprofile, meterid of first service
1782 vpv.services.Range(func(key, value interface{}) bool {
1783 svc := value.(*VoltService)
1784 writemetadata := uint64(svc.TechProfileID) << 32
1785 subFlow.SetWriteMetadata(writemetadata)
1786 subFlow.SetMeterID(svc.UsMeterID)
1787 return false
1788 })
1789 subFlow.SetInPort(uniport)
1790 // PortName and PortID to be used for validation of port before flow pushing
1791 flow.PortID = uniport
1792 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301793 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301794 // metadata := uint64(uniport)
1795 // subFlow.SetWriteMetadata(metadata)
1796 allowTransparent := 0
1797 if vpv.AllowTransparent {
1798 allowTransparent = 1
1799 }
1800 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1801 subFlow.SetTableMetadata(metadata)
1802 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301803 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301804 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1805 subFlow.Priority = of.DhcpFlowPriority
1806
1807 flow.SubFlows[subFlow.Cookie] = subFlow
1808 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1809 return flow, nil
1810}
1811
1812// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1813// application.
1814func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1815 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1816
1817 flow := &of.VoltFlow{}
1818 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1819 subFlow := of.NewVoltSubFlow()
1820 subFlow.SetTableID(0)
1821
1822 vpv.setDsMatchVlan(subFlow)
1823 subFlow.SetUdpv6Match()
1824 subFlow.SrcPort = 547
1825 subFlow.DstPort = 547
1826 uniport, _ := GetApplication().GetPortID(vpv.Port)
1827 nni, err := GetApplication().GetNniPort(vpv.Device)
1828 if err != nil {
1829 return nil, err
1830 }
1831 nniport, err := GetApplication().GetPortID(nni)
1832 if err != nil {
1833 return nil, err
1834 }
1835 subFlow.SetInPort(nniport)
1836 // PortName and PortID to be used for validation of port before flow pushing
1837 flow.PortID = uniport
1838 flow.PortName = vpv.Port
1839 // metadata := uint64(uniport)
1840 // subFlow.SetWriteMetadata(metadata)
1841 allowTransparent := 0
1842 if vpv.AllowTransparent {
1843 allowTransparent = 1
1844 }
1845 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1846 subFlow.SetTableMetadata(metadata)
1847 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301848 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301849 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1850 subFlow.Priority = of.DhcpFlowPriority
1851
1852 flow.SubFlows[subFlow.Cookie] = subFlow
1853 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1854 return flow, nil
1855}
1856
1857// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1858// The flows included by this function cover US only as the DS is
1859// created either automatically by the VOLTHA or at the device level
1860// earlier
1861func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
1862 flow := &of.VoltFlow{}
1863 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1864
1865 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
1866 subFlow := of.NewVoltSubFlow()
1867 subFlow.SetTableID(0)
1868
1869 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1870 subFlow.SetMatchSrcMac(vpv.MacAddr)
1871 }
1872
1873 subFlow.SetMatchDstMac(BroadcastMAC)
1874 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1875 return nil, err
1876 }
1877 subFlow.SetArpMatch()
1878 uniport, err := GetApplication().GetPortID(vpv.Port)
1879 if err != nil {
1880 return nil, err
1881 }
1882 subFlow.SetInPort(uniport)
1883 // PortName and PortID to be used for validation of port before flow pushing
1884 flow.PortID = uniport
1885 flow.PortName = vpv.Port
1886 subFlow.SetReportToController()
1887 allowTransparent := 0
1888 if vpv.AllowTransparent {
1889 allowTransparent = 1
1890 }
1891 metadata := uint64(uniport)
1892 subFlow.SetWriteMetadata(metadata)
1893 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1894 subFlow.SetTableMetadata(metadata)
1895 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1896 subFlow.Priority = of.ArpFlowPriority
1897
1898 flow.SubFlows[subFlow.Cookie] = subFlow
1899 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1900 return flow, nil
1901}
1902
1903// setUsMatchVlan to set upstream match vlan
1904func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
1905 switch vpv.VlanControl {
1906 case None:
1907 flow.SetMatchVlan(vpv.SVlan)
1908 case ONUCVlanOLTSVlan:
1909 flow.SetMatchVlan(vpv.CVlan)
1910 case OLTCVlanOLTSVlan:
1911 flow.SetMatchVlan(vpv.UniVlan)
1912 //flow.SetSetVlan(vpv.CVlan)
1913 case ONUCVlan:
1914 flow.SetMatchVlan(vpv.SVlan)
1915 case OLTSVlan:
1916 flow.SetMatchVlan(vpv.UniVlan)
1917 //flow.SetSetVlan(vpv.SVlan)
1918 default:
1919 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1920 return errorCodes.ErrInvalidParamInRequest
1921 }
1922 return nil
1923}
1924
1925// BuildUsPppoeFlows to build upstream pppoe flows
1926func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301927 flow := &of.VoltFlow{}
1928 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1929 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
1930 subFlow := of.NewVoltSubFlow()
1931 subFlow.SetTableID(0)
1932
1933 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1934 subFlow.SetMatchSrcMac(vpv.MacAddr)
1935 }
1936
1937 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1938 return nil, err
1939 }
1940 subFlow.SetPppoeDiscoveryMatch()
1941 uniport, err := GetApplication().GetPortID(vpv.Port)
1942 if err != nil {
1943 return nil, err
1944 }
1945 subFlow.SetInPort(uniport)
1946 subFlow.SetReportToController()
1947 // PortName and PortID to be used for validation of port before flow pushing
1948 flow.PortID = uniport
1949 flow.PortName = vpv.Port
1950
1951 allowTransparent := 0
1952 if vpv.AllowTransparent {
1953 allowTransparent = 1
1954 }
1955 metadata := uint64(uniport)
1956 subFlow.SetWriteMetadata(metadata)
1957
1958 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1959 subFlow.SetTableMetadata(metadata)
1960
vinokuma926cb3e2023-03-29 11:41:06 +05301961 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301962 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
1963 subFlow.Priority = of.PppoeFlowPriority
1964
1965 flow.SubFlows[subFlow.Cookie] = subFlow
1966 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1967 return flow, nil
1968}
1969
1970// BuildDsPppoeFlows to build downstream pppoe flows
1971func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301972 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1973 flow := &of.VoltFlow{}
1974 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1975 subFlow := of.NewVoltSubFlow()
1976 subFlow.SetTableID(0)
1977
1978 vpv.setDsMatchVlan(subFlow)
1979 subFlow.SetPppoeDiscoveryMatch()
1980
1981 if NonZeroMacAddress(vpv.MacAddr) {
1982 subFlow.SetMatchDstMac(vpv.MacAddr)
1983 }
1984
1985 uniport, _ := GetApplication().GetPortID(vpv.Port)
1986 nni, err := GetApplication().GetNniPort(vpv.Device)
1987 if err != nil {
1988 return nil, err
1989 }
1990 nniport, err := GetApplication().GetPortID(nni)
1991 if err != nil {
1992 return nil, err
1993 }
1994 subFlow.SetInPort(nniport)
1995 // PortName and PortID to be used for validation of port before flow pushing
1996 flow.PortID = uniport
1997 flow.PortName = vpv.Port
1998 metadata := uint64(uniport)
1999 subFlow.SetWriteMetadata(metadata)
2000 allowTransparent := 0
2001 if vpv.AllowTransparent {
2002 allowTransparent = 1
2003 }
2004 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2005 subFlow.SetTableMetadata(metadata)
2006 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302007 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302008 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2009 subFlow.Priority = of.PppoeFlowPriority
2010
2011 flow.SubFlows[subFlow.Cookie] = subFlow
2012 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2013 return flow, nil
2014}
2015
2016// setDsMatchVlan to set downstream match vlan
2017func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
2018 switch vpv.VlanControl {
2019 case None:
2020 flow.SetMatchVlan(vpv.SVlan)
2021 case ONUCVlanOLTSVlan,
2022 OLTCVlanOLTSVlan,
2023 ONUCVlan,
2024 OLTSVlan:
2025 flow.SetMatchVlan(vpv.SVlan)
2026 default:
2027 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2028 }
2029}
2030
2031// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2032// in the US direction.
2033func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2034 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2035 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2036 if mvp == nil {
2037 return nil, errors.New("Mvlan Profile configured not found")
2038 }
2039 mvlan := mvp.GetUsMatchVlan()
2040 flow := &of.VoltFlow{}
2041 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2042 subFlow := of.NewVoltSubFlow()
2043 subFlow.SetTableID(0)
2044
Akash Sonia8246972023-01-03 10:37:08 +05302045 subFlow.SetMatchVlan(vpv.UniVlan)
2046 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302047
2048 uniport, err := GetApplication().GetPortID(vpv.Port)
2049 if err != nil {
2050 return nil, err
2051 }
2052 subFlow.SetInPort(uniport)
2053 // PortName and PortID to be used for validation of port before flow pushing
2054 flow.PortID = uniport
2055 flow.PortName = vpv.Port
2056
2057 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2058 subFlow.SetMatchSrcMac(vpv.MacAddr)
2059 }
2060 logger.Infow(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302061 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302062
2063 if vpv.McastService {
2064 metadata := uint64(vpv.McastUsMeterID)
2065 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2066 subFlow.SetMatchPbit(vpv.McastPbit)
2067 subFlow.SetMeterID(vpv.McastUsMeterID)
2068 subFlow.SetWriteMetadata(metadata)
2069 } else {
2070 // Set techprofile, meterid of first service
2071 vpv.services.Range(func(key, value interface{}) bool {
2072 svc := value.(*VoltService)
2073 writemetadata := uint64(svc.TechProfileID) << 32
2074 subFlow.SetWriteMetadata(writemetadata)
2075 subFlow.SetMeterID(svc.UsMeterID)
2076 return false
2077 })
2078 }
2079
2080 allowTransparent := 0
2081 if vpv.AllowTransparent {
2082 allowTransparent = 1
2083 }
2084 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2085 subFlow.SetTableMetadata(metadata)
2086 subFlow.SetIgmpMatch()
2087 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302088 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302089 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2090 subFlow.Priority = of.IgmpFlowPriority
2091
2092 flow.SubFlows[subFlow.Cookie] = subFlow
2093 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2094 return flow, nil
2095}
2096
2097// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302098func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302099 if vpv.DeleteInProgress {
2100 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2101 return
2102 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302103 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302104}
2105
vinokuma926cb3e2023-03-29 11:41:06 +05302106// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302107func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302108 vpv.PendingFlowLock.RLock()
2109 defer vpv.PendingFlowLock.RUnlock()
2110 vpv.Version = database.PresentVersionMap[database.VpvPath]
2111 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302112 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 +05302113 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2114 "UniVlan": vpv.UniVlan, "Error": err})
2115 }
2116 }
2117}
2118
2119// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302120func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302121 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 +05302122 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302123}
2124
2125// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302126func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
2127 vpv.RangeOnServices(cntx, ClearFlagsInService)
Naveen Sampath04696f72022-06-13 15:19:14 +05302128}
2129
2130// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302131func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302132 vpv.PendingFlowLock.Lock()
2133 vpv.FlowsApplied = false
2134 vpv.IgmpFlowsApplied = false
2135 vpv.PendingDeleteFlow = make(map[string]bool)
2136 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302137 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302138 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2139 log.Fields{"device": vpv.Device, "port": vpv.Port,
2140 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2141}
2142
2143// CreateVpvFromString to create vpv from string
2144func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
2145 var vpv VoltPortVnet
2146 if err := json.Unmarshal(b, &vpv); err == nil {
2147 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2148 if !ok {
2149 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2150 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2151 }
2152 vpv.servicesCount = atomic.NewUint64(0)
2153 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2154 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2155 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2156 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2157 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2158 vnet.associatePortToVnet(vpv.Port)
2159 }
2160
2161 if vpv.DeleteInProgress {
2162 va.VoltPortVnetsToDelete[&vpv] = true
2163 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2164 }
2165 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2166 }
2167}
2168
2169// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302170func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302171 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302172 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302173 for hash, vpv := range vpvs {
2174 b, ok := vpv.Value.([]byte)
2175 if !ok {
2176 logger.Warn(ctx, "The value type is not []byte")
2177 continue
2178 }
2179 va.CreateVpvFromString(b, hash)
2180 }
2181}
2182
2183// GetVnetByPort : VNET related functionality of VOLT Application here on.
2184// Get the VNET from a port. The port identity is passed as device and port identities in string.
2185// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2186// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2187func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
2188 if _, ok := va.VnetsByPort.Load(port); !ok {
2189 return nil
2190 }
2191 vpvs, _ := va.VnetsByPort.Load(port)
2192 for _, vpv := range vpvs.([]*VoltPortVnet) {
2193 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2194 return vpv
2195 }
2196 }
2197 return nil
2198}
2199
2200// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302201func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302202 // The VNET is not on the port and is to be added
2203 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2204 vpv := NewVoltPortVnet(vvnet)
2205 vpv.MacLearning = vvnet.MacLearning
2206 vpv.Port = port
2207 vvnet.associatePortToVnet(port)
2208 if _, ok := va.VnetsByPort.Load(port); !ok {
2209 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2210 }
2211 vpvsIntf, _ := va.VnetsByPort.Load(port)
2212 vpvs := vpvsIntf.([]*VoltPortVnet)
2213 vpvs = append(vpvs, vpv)
2214 va.VnetsByPort.Store(port, vpvs)
2215 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2216
2217 vpv.VpvLock.Lock()
2218 defer vpv.VpvLock.Unlock()
2219
2220 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302221 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302222
Tinoj Josephec742f62022-09-29 19:11:10 +05302223 if !vs.IsActivated {
2224 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2225 // Process the PORT UP if the port is already up
2226 d, err := va.GetDeviceFromPort(port)
2227 if err == nil {
2228 vpv.setDevice(d.Name)
2229 }
2230 vpv.WriteToDb(cntx)
2231 return vpv
2232 }
2233
Naveen Sampath04696f72022-06-13 15:19:14 +05302234 // Process the PORT UP if the port is already up
2235 d, err := va.GetDeviceFromPort(port)
2236 if err == nil {
2237 vpv.setDevice(d.Name)
2238 p := d.GetPort(port)
2239 if p != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302240 if vs.PonPort != 0xFF && vs.PonPort != p.PonPort {
2241 logger.Errorw(ctx, "UNI port discovered on wrong PON Port. Dropping Flow Push for VPV", log.Fields{"Device": d.Name, "Port": port, "DetectedPon": p.PonPort, "ExpectedPon": vs.PonPort, "Vnet": vpv.VnetName})
2242 } else {
2243 logger.Infow(ctx, "Checking UNI port state", log.Fields{"State": p.State})
2244 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302245 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302246 }
2247 }
2248 }
2249 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302250 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302251 return vpv
2252}
2253
2254// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302255func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05302256 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302257 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2258
vinokuma926cb3e2023-03-29 11:41:06 +05302259 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302260 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2261
vinokuma926cb3e2023-03-29 11:41:06 +05302262 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302263 va.DeleteMacInPortMap(vpv.MacAddr)
2264
vinokuma926cb3e2023-03-29 11:41:06 +05302265 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302266 vpvsIntf, ok := va.VnetsByPort.Load(port)
2267 if !ok {
2268 return
2269 }
2270 vpvs := vpvsIntf.([]*VoltPortVnet)
2271 for i, lvpv := range vpvs {
2272 if lvpv == vpv {
2273 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2274 "UNIVLAN": vpv.UniVlan})
2275
2276 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2277
2278 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302279 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302280
2281 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302282 vpv.DelTrapFlows(cntx)
2283 vpv.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302284 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2285 vpv.PendingFlowLock.RLock()
2286 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302287 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302288 }
2289 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302290 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302291 }
2292 vpv.PendingFlowLock.RUnlock()
2293 return
2294 }
2295 }
2296}
2297
2298// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302299func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302300 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302301 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302302 for _, net := range vnets {
2303 b, ok := net.Value.([]byte)
2304 if !ok {
2305 logger.Warn(ctx, "The value type is not []byte")
2306 continue
2307 }
2308 var vnet VoltVnet
2309 err := json.Unmarshal(b, &vnet)
2310 if err != nil {
2311 logger.Warn(ctx, "Unmarshal of VNET failed")
2312 continue
2313 }
2314 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302315 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302316 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2317 }
2318
2319 if vnet.DeleteInProgress {
2320 va.VnetsToDelete[vnet.Name] = true
2321 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2322 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302323 }
2324}
2325
2326// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2327// are used as the key to locate the service. If more than one service is on the
2328// same port (essentially a UNI of ONU), the services must be separated by different
2329// CVLANs
2330func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
2331 // Fetch the device first to make sure the device exists
2332 dIntf, ok := va.DevicesDisc.Load(device)
2333 if !ok {
2334 return nil
2335 }
2336 d := dIntf.(*VoltDevice)
2337
2338 // If the port is NNI port, the services dont exist on it. The svc then
2339 // must be obtained from a different context and is not included here
2340 if port == d.NniPort {
2341 return nil
2342 }
2343
vinokuma926cb3e2023-03-29 11:41:06 +05302344 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302345 var service *VoltService
2346
2347 // This is an access port and the port should have all the associated
2348 // services which can be uniquely identified by the VLANs in the packet
2349 vnets, ok := va.VnetsByPort.Load(port)
2350
2351 if !ok {
2352 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2353 return nil
2354 }
2355 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2356 for _, vnet := range vnets.([]*VoltPortVnet) {
2357 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2358 switch vnet.VlanControl {
2359 case ONUCVlanOLTSVlan:
2360 service = vnet.MatchesPriority(priority)
2361 if vnet.MatchesCvlan(vlans) && service != nil {
2362 return service
2363 }
2364 case ONUCVlan,
2365 None:
2366 service = vnet.MatchesPriority(priority)
2367 // In case of DHCP Flow - cvlan == VlanNone
2368 // In case of HSIA Flow - cvlan == Svlan
2369 if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
2370 return service
2371 }
2372 case OLTCVlanOLTSVlan,
2373 OLTSVlan:
2374 service = vnet.MatchesPriority(priority)
2375 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2376 return service
2377 }
2378 default:
2379 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2380 }
2381 }
2382 return nil
2383}
2384
2385// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2386// are used as the key to locate the service. If more than one service is on the
2387// same port (essentially a UNI of ONU), the services must be separated by different
2388// CVLANs
2389func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2390 // Fetch the device first to make sure the device exists
2391 dIntf, ok := va.DevicesDisc.Load(device)
2392 if !ok {
2393 return nil, nil
2394 }
2395 d := dIntf.(*VoltDevice)
2396
2397 // If the port is NNI port, the services dont exist on it. The svc then
2398 // must be obtained from a different context and is not included here
2399 if port == d.NniPort {
2400 return nil, nil
2401 }
2402
2403 //To return the matched service
2404 var service *VoltService
2405
2406 // This is an access port and the port should have all the associated
2407 // services which can be uniquely identified by the VLANs in the packet
2408 if vnets, ok := va.VnetsByPort.Load(port); ok {
2409 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2410 for _, vnet := range vnets.([]*VoltPortVnet) {
2411 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2412 switch vnet.VlanControl {
2413 case ONUCVlanOLTSVlan:
2414 service = vnet.MatchesPriority(priority)
2415 if vnet.MatchesCvlan(vlans) && service != nil {
2416 return vnet, service
2417 }
2418 case ONUCVlan,
2419 None:
2420 service = vnet.MatchesPriority(priority)
2421 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2422 return vnet, service
2423 }
2424 case OLTCVlanOLTSVlan,
2425 OLTSVlan:
2426 service = vnet.MatchesPriority(priority)
2427 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2428 return vnet, service
2429 }
2430 default:
2431 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2432 }
2433 }
2434 }
2435 return nil, nil
2436}
2437
2438// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2439// are used as the key to locate the service. If more than one service is on the
2440// same port (essentially a UNI of ONU), the services must be separated by different
2441// CVLANs
2442func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
2443 vlans := GetVlans(pkt)
2444 priority := GetPriority(pkt)
2445 return va.GetVnetFromFields(device, port, vlans, priority)
2446}
2447
2448// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302449func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302450 logger.Infow(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2451 pushflow := func(key interface{}, value interface{}) bool {
2452 device := value.(*VoltDevice)
2453 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302454 logger.Infow(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302455 return true
2456 }
2457 if device.State != controller.DeviceStateUP {
2458 logger.Errorw(ctx, "Push Dev Flows Failed - Device state DOWN", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan, "device": device})
2459 return true
2460 }
2461 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2462 logger.Errorw(ctx, "Push Dev Flows Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2463 return true
2464 }
2465
2466 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2467 vnetList := vnetListIntf.(*util.ConcurrentMap)
2468 vnetList.Set(vnet.Name, true)
2469 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2470 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()})
2471 return true
2472 }
2473 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2474 err := ProcessIcmpv6McGroup(device.Name, false)
2475 if err != nil {
2476 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2477 return true
2478 }
2479 if portID, err := va.GetPortID(device.NniPort); err == nil {
2480 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2481 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2482 return true
2483 }
2484
vinokuma926cb3e2023-03-29 11:41:06 +05302485 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302486 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302487 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302488 if err != nil {
2489 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2490 return true
2491 }
2492 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2493
2494 // Pushing ARP Flow
2495 flow = BuildDSArpFlow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302496 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302497 if err != nil {
2498 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2499 return true
2500 }
2501 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2502
2503 vnetList := util.NewConcurrentMap()
2504 vnetList.Set(vnet.Name, true)
2505 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2506 }
2507 return true
2508 }
2509 va.DevicesDisc.Range(pushflow)
2510}
2511
2512// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302513func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302514 logger.Infow(ctx, "PushDevFlowForDevice", log.Fields{"device": device})
2515
2516 logger.Debugw(ctx, "Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2517 err := ProcessIcmpv6McGroup(device.Name, false)
2518 if err != nil {
2519 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2520 return
2521 }
2522 pushicmpv6 := func(key, value interface{}) bool {
2523 vnet := value.(*VoltVnet)
2524 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2525 vnetList := vnetListIntf.(*util.ConcurrentMap)
2526 vnetList.Set(vnet.Name, true)
2527 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2528 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()})
2529 return true
2530 }
2531 nniPortID, err := va.GetPortID(device.NniPort)
2532 if err != nil {
2533 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2534 }
2535 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2536 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2537 return true
2538 }
2539 flow := BuildICMPv6Flow(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 ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2543 return true
2544 }
2545 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2546
2547 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302548 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302549 if err != nil {
2550 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2551 return true
2552 }
2553 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2554
2555 vnetList := util.NewConcurrentMap()
2556 vnetList.Set(vnet.Name, true)
2557 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2558 return true
2559 }
2560 va.VnetsByName.Range(pushicmpv6)
2561}
2562
2563// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302564func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302565 logger.Infow(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2566 delflows := func(key interface{}, value interface{}) bool {
2567 device := value.(*VoltDevice)
2568
2569 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2570 vnetList := vnetListIntf.(*util.ConcurrentMap)
2571 vnetList.Remove(vnet.Name)
2572 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2573 if vnetList.Length() != 0 {
2574 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()})
2575 return true
2576 }
2577 }
2578 if portID, err := va.GetPortID(device.NniPort); err == nil {
2579 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2580 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2581 return true
2582 }
vinokuma926cb3e2023-03-29 11:41:06 +05302583 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302584 flow := BuildICMPv6Flow(portID, vnet)
2585 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302586 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302587 if err != nil {
2588 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2589 return true
2590 }
2591 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2592
vinokuma926cb3e2023-03-29 11:41:06 +05302593 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302594 flow = BuildDSArpFlow(portID, vnet)
2595 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302596 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302597 if err != nil {
2598 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2599 return true
2600 }
2601 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2602
2603 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2604 }
2605 return true
2606 }
2607 va.DevicesDisc.Range(delflows)
2608}
2609
2610// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302611func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302612 logger.Infow(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
2613 delicmpv6 := func(key, value interface{}) bool {
2614 vnet := value.(*VoltVnet)
2615 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2616 vnetList := vnetListIntf.(*util.ConcurrentMap)
2617 vnetList.Remove(vnet.Name)
2618 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2619 if vnetList.Length() != 0 {
2620 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()})
2621 return true
2622 }
2623 } else {
2624 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2625 return true
2626 }
2627 nniPortID, err := va.GetPortID(device.NniPort)
2628 if err != nil {
2629 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2630 }
2631 flow := BuildICMPv6Flow(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 ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2636 return true
2637 }
2638
2639 flow = BuildDSArpFlow(nniPortID, vnet)
2640 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302641 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302642 if err != nil {
2643 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2644 return true
2645 }
2646
2647 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2648 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2649 return true
2650 }
2651 va.VnetsByName.Range(delicmpv6)
2652 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2653 err := ProcessIcmpv6McGroup(device.Name, true)
2654 if err != nil {
2655 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2656 return
2657 }
2658}
2659
2660// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302661func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302662 logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2663 delflows := func(key interface{}, value interface{}) bool {
2664 device := value.(*VoltDevice)
2665 if device.SerialNum != deviceSerialNum {
2666 return true
2667 }
2668 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2669 vnetList := vnetListIntf.(*util.ConcurrentMap)
2670 vnetList.Remove(vnet.Name)
2671 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2672 if vnetList.Length() != 0 {
2673 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()})
2674 return true
2675 }
2676 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2677 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2678 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2679 // The step will be as follow:
2680 // 1. Deact Service
2681 // 2. Pod Reboot
2682 // 3. Pending Delete Service triggered
2683 // 4. Del Service Ind followed by DelVnet req from NB
2684 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2685 // hence the flow will not be cleared
2686 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2687 return true
2688 }
2689 if portID, err := va.GetPortID(device.NniPort); err == nil {
2690 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2691 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2692 return false
2693 }
2694 flow := BuildICMPv6Flow(portID, vnet)
2695 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302696 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302697 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2698 }
2699 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2700
2701 flow = BuildDSArpFlow(portID, vnet)
2702 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302703 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302704 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2705 }
2706 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2707 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2708 }
2709 return false
2710 }
2711 va.DevicesDisc.Range(delflows)
2712}
2713
2714// BuildICMPv6Flow to Build DS flow for ICMPv6
2715func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302716 logger.Infow(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302717 flow := &of.VoltFlow{}
2718 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2719 subFlow := of.NewVoltSubFlow()
2720
2721 subFlow.SetICMPv6Match()
2722 subFlow.SetMatchVlan(vnet.SVlan)
2723 subFlow.SetInPort(inport)
2724 subFlow.SetPopVlan()
2725 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2726 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2727 subFlow.Priority = of.McFlowPriority
2728 var metadata uint64
2729 if vnet.VlanControl == None {
2730 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2731 } else {
2732 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2733 }
2734 subFlow.SetTableMetadata(metadata)
2735 metadata = uint64(vnet.setPbitRemarking())
2736
2737 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2738 subFlow.SetWriteMetadata(metadata)
2739 flow.SubFlows[subFlow.Cookie] = subFlow
2740 return flow
2741}
2742
vinokuma926cb3e2023-03-29 11:41:06 +05302743// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302744func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302745 logger.Infow(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302746
2747 flow := &of.VoltFlow{}
2748 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2749 subFlow := of.NewVoltSubFlow()
2750
2751 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2752 subFlow.SetArpMatch()
2753 subFlow.SetMatchDstMac(BcastMAC)
2754 subFlow.SetMatchVlan(vnet.SVlan)
2755 subFlow.SetInPort(inport)
2756 subFlow.SetPopVlan()
2757 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2758
2759 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2760 subFlow.Priority = of.McFlowPriority
2761
2762 var metadata uint64
2763 if vnet.VlanControl == None {
2764 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2765 } else {
2766 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2767 }
2768 subFlow.SetTableMetadata(metadata)
2769 metadata = uint64(vnet.setPbitRemarking())
2770 subFlow.SetWriteMetadata(metadata)
2771
2772 flow.SubFlows[subFlow.Cookie] = subFlow
2773 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2774 return flow
2775}
2776
2777// setPbitRemarking to set Pbit remarking
2778func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302779 // Remarkable
2780 // Remarked Pbit Pbit
2781 // |-----------------------------| |------|
2782 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2783 // 000 000 000 000 000 000 000 000 00000000
2784
2785 // Eg:
2786 // For 6:3 & 7:1
2787 // 001 011 000 000 000 000 000 000 11000000
2788
2789 var remarkable uint8
2790 var remarked uint32
2791 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2792 remarkable = remarkable | 1<<refPbit
2793 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2794 }
2795 return remarked<<8 | uint32(remarkable)
2796}
2797
2798// ProcessIcmpv6McGroup to add icmpv6 multicast group
2799func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302800 logger.Info(ctx, "Creating ICMPv6 MC Group")
2801 va := GetApplication()
2802 vd := va.GetDevice(device)
2803 group := &of.Group{}
2804 group.GroupID = ICMPv6ArpGroupID
2805 group.Device = device
2806 if delete {
2807 if !vd.icmpv6GroupAdded {
2808 logger.Info(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
2809 return nil //TODO
2810 }
2811 vd.icmpv6GroupAdded = false
2812 group.Command = of.GroupCommandDel
2813 group.ForceAction = true
2814 } else {
2815 if vd.icmpv6GroupAdded {
2816 logger.Info(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
2817 return nil //TODO
2818 }
2819 vd.icmpv6GroupAdded = true
2820 group.Command = of.GroupCommandAdd
2821 receivers := GetApplication().GetIcmpv6Receivers(device)
2822 group.Buckets = append(group.Buckets, receivers...)
2823 }
2824 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2825 port, _ := GetApplication().GetNniPort(device)
2826 err := cntlr.GetController().GroupUpdate(port, device, group)
2827 return err
2828}
2829
vinokuma926cb3e2023-03-29 11:41:06 +05302830// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302831func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05302832 switch vpv.VlanControl {
2833 case ONUCVlanOLTSVlan,
2834 OLTCVlanOLTSVlan:
2835 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2836 return true
2837 }
2838 case ONUCVlan,
2839 OLTSVlan,
2840 None:
2841 if vpv.SVlan == svlan {
2842 return true
2843 }
2844 default:
2845 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2846 }
2847 return false
2848}
2849
vinokuma926cb3e2023-03-29 11:41:06 +05302850// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302851func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302852 for cookie := range flow.SubFlows {
2853 cookie := strconv.FormatUint(cookie, 10)
2854 fe := &FlowEvent{
2855 eType: EventTypeControlFlowAdded,
2856 cookie: cookie,
2857 eventData: vpv,
2858 }
2859 device.RegisterFlowAddEvent(cookie, fe)
2860 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302861 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302862}
2863
vinokuma926cb3e2023-03-29 11:41:06 +05302864// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302865func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302866 sendFlowFailureInd := func(key, value interface{}) bool {
2867 //svc := value.(*VoltService)
2868 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2869 return true
2870 }
2871 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2872 vpv.services.Range(sendFlowFailureInd)
2873}
2874
vinokuma926cb3e2023-03-29 11:41:06 +05302875// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302876func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302877 vpv.PendingFlowLock.Lock()
2878 defer vpv.PendingFlowLock.Unlock()
2879
2880 for cookie := range flow.SubFlows {
2881 cookie := strconv.FormatUint(cookie, 10)
2882 fe := &FlowEvent{
2883 eType: EventTypeControlFlowRemoved,
2884 device: device.Name,
2885 cookie: cookie,
2886 eventData: vpv,
2887 }
2888 device.RegisterFlowDelEvent(cookie, fe)
2889 vpv.PendingDeleteFlow[cookie] = true
2890 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302891 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302892}
2893
vinokuma926cb3e2023-03-29 11:41:06 +05302894// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302895func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302896 vpv.PendingFlowLock.RLock()
2897 defer vpv.PendingFlowLock.RUnlock()
2898 if !vpv.DeleteInProgress {
2899 return
2900 }
2901 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
2902 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 +05302903 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302904 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2905 }
2906}
2907
vinokuma926cb3e2023-03-29 11:41:06 +05302908// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302909func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302910 vpv.PendingFlowLock.Lock()
2911 logger.Infow(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
2912
2913 delete(vpv.PendingDeleteFlow, cookie)
2914 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302915 vpv.CheckAndDeleteVpv(cntx)
2916 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302917}
2918
vinokuma926cb3e2023-03-29 11:41:06 +05302919// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302920func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302921 vpv.PendingFlowLock.Lock()
2922
2923 logger.Errorw(ctx, "VPV Flow Remove Failure Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
2924
2925 sendFlowFailureInd := func(key, value interface{}) bool {
2926 svc := value.(*VoltService)
2927 svc.triggerServiceFailureInd(errorCode, errReason)
2928 return true
2929 }
2930 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2931 vpv.services.Range(sendFlowFailureInd)
2932
2933 if vpv.DeleteInProgress {
2934 delete(vpv.PendingDeleteFlow, cookie)
2935 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302936 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302937 } else {
2938 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302939 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302940 }
2941}
2942
vinokuma926cb3e2023-03-29 11:41:06 +05302943// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302944func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302945 vv.VnetLock.Lock()
2946 defer vv.VnetLock.Unlock()
2947
2948 var flowMap map[string]bool
2949 var ok bool
2950
2951 for cookie := range flow.SubFlows {
2952 cookie := strconv.FormatUint(cookie, 10)
2953 fe := &FlowEvent{
2954 eType: EventTypeDeviceFlowRemoved,
2955 device: device.Name,
2956 cookie: cookie,
2957 eventData: vv,
2958 }
2959 device.RegisterFlowDelEvent(cookie, fe)
2960 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
2961 flowMap = make(map[string]bool)
2962 }
2963 flowMap[cookie] = true
2964 vv.PendingDeleteFlow[device.Name] = flowMap
2965 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302966 vv.WriteToDb(cntx)
2967 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302968}
2969
vinokuma926cb3e2023-03-29 11:41:06 +05302970// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302971func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302972 if !vv.DeleteInProgress {
2973 return
2974 }
2975 vv.VnetPortLock.RLock()
2976 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
2977 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
2978 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302979 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05302980 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
2981 } else {
2982 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
2983 }
2984 vv.VnetPortLock.RUnlock()
2985}
2986
vinokuma926cb3e2023-03-29 11:41:06 +05302987// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302988func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302989 vv.VnetLock.Lock()
2990 defer vv.VnetLock.Unlock()
2991
2992 logger.Infow(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
2993
2994 if _, ok := vv.PendingDeleteFlow[device]; ok {
2995 delete(vv.PendingDeleteFlow[device], cookie)
2996 }
2997
2998 //Check and update success for pending disable request
2999 if d := GetApplication().GetDevice(device); d != nil {
3000 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
3001 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303002 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303003 }
3004 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303005 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05303006}
3007
vinokuma926cb3e2023-03-29 11:41:06 +05303008// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303009func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303010 vv.VnetLock.Lock()
3011 defer vv.VnetLock.Unlock()
3012
3013 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3014 if _, ok := flowMap[cookie]; ok {
3015 logger.Errorw(ctx, "Device Flow Remove Failure Notification", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
3016
3017 if vv.DeleteInProgress {
3018 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303019 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303020 }
3021 return
3022 }
3023 }
3024 logger.Errorw(ctx, "Device Flow Remove Failure Notification for Unknown cookie", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3025}
3026
vinokuma926cb3e2023-03-29 11:41:06 +05303027// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303028func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303029 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3030 // When multiple Igmp-suported service enabled, comment "return false"
Naveen Sampath04696f72022-06-13 15:19:14 +05303031
3032 sendFlowFailureInd := func(key, value interface{}) bool {
3033 svc := value.(*VoltService)
3034 if svc.IgmpEnabled {
3035 svc.triggerServiceFailureInd(errorCode, errReason)
3036 return false
3037 }
3038 return true
3039 }
3040 logger.Errorw(ctx, "US IGMP Flow Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3041 vpv.services.Range(sendFlowFailureInd)
3042}
3043
3044// GetMatchingMcastService to get matching multicast service
3045func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +05303046 var service *VoltService
3047 dIntf, ok := va.DevicesDisc.Load(device)
3048 if !ok {
3049 return nil
3050 }
3051 d := dIntf.(*VoltDevice)
3052
3053 // If the port is NNI port, the services dont exist on it. The svc then
3054 // must be obtained from a different context and is not included here
3055 if port == d.NniPort {
3056 return nil
3057 }
3058
3059 // This is an access port and the port should have all the associated
3060 // services which can be uniquely identified by the VLANs in the packet
3061 vnets, ok := va.VnetsByPort.Load(port)
3062
3063 if !ok {
3064 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3065 return nil
3066 }
3067 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3068 getMcastService := func(key, value interface{}) bool {
3069 srv := value.(*VoltService)
3070 if srv.IgmpEnabled {
3071 service = srv
3072
3073 //TODO: Current implementation supports only for single service with Igmp Enabled
3074 //FIX-ME: When multiple service suports Igmp, update of logic required
3075 return false
3076 }
3077 return true
3078 }
3079
3080 for _, vpv := range vnets.([]*VoltPortVnet) {
3081 if vpv.CVlan == cvlan {
3082 vpv.services.Range(getMcastService)
3083 if service != nil {
3084 break
3085 }
3086 }
3087 }
3088 return service
3089}
3090
vinokuma926cb3e2023-03-29 11:41:06 +05303091// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303092func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05303093 vv.VnetLock.Lock()
3094 cookieList := []uint64{}
3095 flowMap := vv.PendingDeleteFlow[device]
3096
3097 for cookie := range flowMap {
3098 cookieList = append(cookieList, convertToUInt64(cookie))
3099 }
3100 vv.VnetLock.Unlock()
3101
3102 if len(cookieList) == 0 {
3103 return false
3104 }
3105
3106 for _, cookie := range cookieList {
3107 if vd := GetApplication().GetDevice(device); vd != nil {
3108 flow := &of.VoltFlow{}
3109 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3110 subFlow := of.NewVoltSubFlow()
3111 subFlow.Cookie = cookie
3112 flow.SubFlows[cookie] = subFlow
3113 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303114 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303115 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3116 }
3117 }
3118 }
3119 return true
3120}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303121
vinokuma926cb3e2023-03-29 11:41:06 +05303122// JSONMarshal wrapper function for json Marshal VoltVnet
3123func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303124 return json.Marshal(VoltVnet{
3125 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303126 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303127 VnetOper: VnetOper{
3128 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3129 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3130 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3131 },
3132 })
3133}
3134
vinokuma926cb3e2023-03-29 11:41:06 +05303135// JSONMarshal wrapper function for json Marshal VoltPortVnet
3136func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303137 return json.Marshal(VoltPortVnet{
3138 Device: vpv.Device,
3139 Port: vpv.Port,
3140 PonPort: vpv.PonPort,
3141 VnetName: vpv.VnetName,
3142 SVlan: vpv.SVlan,
3143 CVlan: vpv.CVlan,
3144 UniVlan: vpv.UniVlan,
3145 SVlanTpid: vpv.SVlanTpid,
3146 DhcpRelay: vpv.DhcpRelay,
3147 ArpRelay: vpv.ArpRelay,
3148 PppoeIa: vpv.PppoeIa,
3149 MacLearning: vpv.MacLearning,
3150 DhcpStatus: vpv.DhcpStatus,
3151 DhcpExpiryTime: vpv.DhcpExpiryTime,
3152 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3153 FlowsApplied: vpv.FlowsApplied,
3154 Ipv4Addr: vpv.Ipv4Addr,
3155 Ipv6Addr: vpv.Ipv6Addr,
3156 MacAddr: vpv.MacAddr,
3157 LearntMacAddr: vpv.LearntMacAddr,
3158 CircuitID: vpv.CircuitID,
3159 RemoteID: vpv.RemoteID,
3160 IsOption82Disabled: vpv.IsOption82Disabled,
3161 RelayState: vpv.RelayState,
3162 PPPoeState: vpv.PPPoeState,
3163 RelayStatev6: vpv.RelayStatev6,
3164 IgmpEnabled: vpv.IgmpEnabled,
3165 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3166 McastService: vpv.McastService,
3167 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3168 VlanControl: vpv.VlanControl,
3169 MvlanProfileName: vpv.MvlanProfileName,
3170 Version: vpv.Version,
3171 McastTechProfileID: vpv.McastTechProfileID,
3172 McastPbit: vpv.McastPbit,
3173 McastUsMeterID: vpv.McastUsMeterID,
3174 AllowTransparent: vpv.AllowTransparent,
3175 SchedID: vpv.SchedID,
3176 DHCPv6DUID: vpv.DHCPv6DUID,
3177 PendingDeleteFlow: vpv.PendingDeleteFlow,
3178 DeleteInProgress: vpv.DeleteInProgress,
3179 Blocked: vpv.Blocked,
3180 DhcpPbit: vpv.DhcpPbit,
3181 })
3182}
Tinoj Josephec742f62022-09-29 19:11:10 +05303183
3184func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
3185 isActivated := false
3186 vpv.services.Range(func(key, value interface{}) bool {
3187 svc := value.(*VoltService)
3188 if svc.IsActivated {
3189 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3190 isActivated = true
3191 return false //to exit loop
3192 }
3193 return true
3194 })
3195 return isActivated
3196}