blob: 09613c9d8e86787a41b32917c7241880193ee689 [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
Naveen Sampath04696f72022-06-13 15:19:14 +0530730 //Disable the flag so that flows can be pushed again
731 // vpv.IgmpFlowsApplied = false
732 // vpv.DsFlowsApplied = false
733 // vpv.UsFlowsApplied = false
734 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530735 vpv.PortUpInd(cntx, d, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +0530736 vpv.VpvLock.Unlock()
737}
738
739// PortUpInd : When a port transistions to UP state, the indication is passed
740// on to this module via the application. We read the VNET configuration
741// again here to apply the latest configuration if the configuration
742// changed. Thus, a reboot of ONT forces the new configuration to get
743// applied.
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530744func (vpv *VoltPortVnet) PortUpInd(cntx context.Context, device *VoltDevice, port string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530745 if vpv.DeleteInProgress {
746 logger.Errorw(ctx, "Ignoring VPV Port UP Ind, VPV deleteion In-Progress", log.Fields{"Device": device, "Port": port, "Vnet": vpv.VnetName})
747 return
748 }
749 vpv.setDevice(device.Name)
750 logger.Infow(ctx, "Port UP Ind, pushing flows for the port", log.Fields{"Device": device, "Port": port, "VnetDhcp": vpv.DhcpRelay, "McastService": vpv.McastService})
751
752 nni, _ := GetApplication().GetNniPort(device.Name)
753 if nni == "" {
754 logger.Warnw(ctx, "Ignoring Vnet Port UP indication: NNI is unavailable", log.Fields{"Port": vpv.Port, "Device": device.Name})
755 return
756 }
757
Akash Sonia8246972023-01-03 10:37:08 +0530758 if nniPort := device.GetPort(nni); nniPort != nil {
759 //If NNI port is not mached to nb nni port dont send flows
760 devConfig := GetApplication().GetDeviceConfig(device.SerialNum)
761 if devConfig != nil {
Akash Soni53da2852023-03-15 00:31:31 +0530762 if devConfig.UplinkPort != strconv.Itoa(int(nniPort.ID)) {
763 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 +0530764 return
765 }
766 }
767 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530768
Naveen Sampath04696f72022-06-13 15:19:14 +0530769 if vpv.Blocked {
770 logger.Errorw(ctx, "VPV Bocked for Processing. Ignoring flow push request", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
771 return
772 }
773
774 if vpv.DhcpRelay || vpv.ArpRelay || vpv.PppoeIa {
775 // If MAC Learning is true if no MAC is configured, push DS/US DHCP, US HSIA flows without MAC.
776 // DS HSIA flows are installed after learning the MAC.
777 logger.Infow(ctx, "Port Up - Trap Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530778 // no HSIA flows for multicast service and DPU_MGMT Service
vinokuma926cb3e2023-03-29 11:41:06 +0530779 if !vpv.McastService && vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530780 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530781 }
vinokuma926cb3e2023-03-29 11:41:06 +0530782 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530783 vpv.RangeOnServices(cntx, AddMeterToDevice)
784 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530785 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530786 if vpv.MacLearning == MacLearningNone || NonZeroMacAddress(vpv.MacAddr) {
787 logger.Infow(ctx, "Port Up - DS Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530788 /*In case of DPU_MGMT_TRAFFIC, need to install both US and DS traffic */
vinokuma926cb3e2023-03-29 11:41:06 +0530789 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530790 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
791 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530792 // US & DS DHCP, US HSIA flows are already installed
793 // install only DS HSIA flow here.
794 // no HSIA flows for multicast service
Akash Soni53da2852023-03-15 00:31:31 +0530795 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530796 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530797 }
798 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530799 } else {
800 // DHCP relay is not configured. This implies that the service must use
801 // 1:1 and does not require MAC learning. In a completely uncommon but
802 // plausible case, the MAC address can be learnt from N:1 without DHCP
803 // relay by configuring any unknown MAC address to be reported. This
804 // however is not seen as a real use case.
805 logger.Infow(ctx, "Port Up - Service Flows", log.Fields{"Device": device.Name, "Port": port})
806 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530807 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530808 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530809 vpv.AddTrapFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530810 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530811 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530812 }
813 }
814
815 // Process IGMP proxy - install IGMP trap rules before DHCP trap rules
816 if vpv.IgmpEnabled {
817 logger.Infow(ctx, "Port Up - IGMP Flows", log.Fields{"Device": device.Name, "Port": port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530818 vpv.RangeOnServices(cntx, AddSvcUsMeterToDevice)
819 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +0530820 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530821 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
822 }
823
824 if vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530825 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +0530826 }
827 }
828
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530829 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530830}
831
832// PortDownInd : When the port status changes to down, we delete all configured flows
833// The same indication is also passed to the services enqueued for them
834// to take appropriate actions
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530835func (vpv *VoltPortVnet) PortDownInd(cntx context.Context, device string, port string, nbRequest bool) {
Tinoj Joseph4ead4e02023-01-30 03:12:44 +0530836 if !nbRequest && !GetApplication().OltFlowServiceConfig.RemoveFlowsOnDisable {
837 logger.Info(ctx, "VPV Port DOWN Ind, Not deleting flows since RemoveOnDisable is disabled")
838 return
839 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530840 logger.Infow(ctx, "VPV Port DOWN Ind, deleting all flows for services",
841 log.Fields{"service count": vpv.servicesCount.Load()})
842
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530843 //vpv.RangeOnServices(cntx, DelAllFlows)
844 vpv.DelTrapFlows(cntx)
845 vpv.DelHsiaFlows(cntx)
846 vpv.WriteToDb(cntx)
847 vpv.ClearServiceCounters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530848}
849
850// SetMacAddr : The MAC address is set when a MAC address is learnt through the
851// packets received from the network. Currently, DHCP packets are
852// only packets we learn the MAC address from
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530853func (vpv *VoltPortVnet) SetMacAddr(cntx context.Context, addr net.HardwareAddr) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530854 //Store Learnt MAC address and return if MACLearning is not enabled
855 vpv.LearntMacAddr = addr
856 if vpv.MacLearning == MacLearningNone || !NonZeroMacAddress(addr) ||
857 (NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn) {
858 return
859 }
860
861 // Compare the two MAC addresses to see if it is same
862 // If they are same, we just return. If not, we perform
863 // actions to address the change in MAC address
864 //if NonZeroMacAddress(vpv.MacAddr) && !util.MacAddrsMatch(vpv.MacAddr, addr) {
865 if !util.MacAddrsMatch(vpv.MacAddr, addr) {
866 expectedPort := GetApplication().GetMacInPortMap(addr)
867 if expectedPort != "" && expectedPort != vpv.Port {
868 logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-setmacaddr",
869 log.Fields{"ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": addr.String()})
870 return
871 }
872 if NonZeroMacAddress(vpv.MacAddr) {
873 logger.Warnw(ctx, "MAC Address Changed. Remove old flows (if added) and re-add with updated MAC", log.Fields{"UpdatedMAC": addr})
874
875 // The newly learnt MAC address is different than earlier one.
876 // The existing MAC based HSIA flows need to be undone as the device
877 // may have been changed
878 // Atleast one HSIA flow should be present in adapter to retain the TP and GEM
879 // hence delete one after the other
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530880 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530881 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530882 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
883 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
884 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530885 GetApplication().DeleteMacInPortMap(vpv.MacAddr)
886 } else {
887 vpv.MacAddr = addr
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530888 vpv.RangeOnServices(cntx, vpv.setLearntMAC)
Naveen Sampath04696f72022-06-13 15:19:14 +0530889 logger.Infow(ctx, "MAC Address learnt from DHCP or ARP", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
890 }
891 GetApplication().UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
892 } else {
893 logger.Infow(ctx, "Leant MAC Address is same", log.Fields{"Learnt MAC": addr.String(), "Port": vpv.Port})
894 }
895
896 _, err := GetApplication().GetDeviceFromPort(vpv.Port)
897 if err != nil {
898 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
Akash Sonia8246972023-01-03 10:37:08 +0530899 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530900 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
901 return
902 }
903 // Ds Hsia flows has to be pushed
904 if vpv.FlowsApplied {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530905 // In case of DPU_MGMT_TRAFFIC install both US and DS Flows
vinokuma926cb3e2023-03-29 11:41:06 +0530906 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530907 vpv.RangeOnServices(cntx, AddUsHsiaFlows)
908 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530909 // no HSIA flows for multicast service
910 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530911 vpv.RangeOnServices(cntx, AddDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +0530912 }
913 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530914 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530915}
916
917// MatchesVlans : If the VNET matches both S and C VLANs, return true. Else, return false
918func (vpv *VoltPortVnet) MatchesVlans(svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) bool {
919 if vpv.SVlan != svlan || vpv.CVlan != cvlan || vpv.UniVlan != univlan {
920 return false
921 }
922 return true
923}
924
925// MatchesCvlan : If the VNET matches CVLAN, return true. Else, return false
926func (vpv *VoltPortVnet) MatchesCvlan(cvlan []of.VlanType) bool {
927 if len(cvlan) != 1 && !vpv.AllowTransparent {
928 return false
929 }
930 if vpv.CVlan != cvlan[0] {
931 return false
932 }
933 return true
934}
935
936// MatchesPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
937func (vpv *VoltPortVnet) MatchesPriority(priority uint8) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +0530938 var service *VoltService
939 pbitFound := false
940 matchpbitsFunc := func(key, value interface{}) bool {
941 svc := value.(*VoltService)
942 for _, pbit := range svc.Pbits {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530943 if uint8(pbit) == priority || uint8(pbit) == uint8(of.PbitMatchAll) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530944 logger.Infow(ctx, "Pbit match found with service",
945 log.Fields{"Pbit": priority, "serviceName": svc.Name})
946 pbitFound = true
947 service = svc
948 return false //Returning false to stop the Range loop
949 }
950 }
951 return true
952 }
953 _ = pbitFound
954 vpv.services.Range(matchpbitsFunc)
955 return service
956}
957
958// GetRemarkedPriority : If the VNET matches priority of the incoming packet with any service, return true. Else, return false
959func (vpv *VoltPortVnet) GetRemarkedPriority(priority uint8) uint8 {
Naveen Sampath04696f72022-06-13 15:19:14 +0530960 dsPbit := uint8(0)
961 matchpbitsFunc := func(key, value interface{}) bool {
962 svc := value.(*VoltService)
963 if remarkPbit, ok := svc.DsRemarkPbitsMap[int(priority)]; ok {
964 logger.Infow(ctx, "Pbit match found with service",
965 log.Fields{"Pbit": priority, "serviceName": svc.Name, "remarkPbit": remarkPbit})
966 dsPbit = uint8(remarkPbit)
967 return false //Returning false to stop the Range loop
968 }
969 // When no remarking info is available, remark the incoming pbit
970 // to highest pbit configured for the subscriber (across all subservices associated)
971 svcPbit := uint8(svc.Pbits[0])
972 if svcPbit > dsPbit {
973 dsPbit = svcPbit
974 }
975 return true
976 }
977 vpv.services.Range(matchpbitsFunc)
978 logger.Debugw(ctx, "Remarked Pbit Value", log.Fields{"Incoming": priority, "Remarked": dsPbit})
979 return dsPbit
980}
981
982// AddSvc adds a service on the VNET on a port. The addition is
983// triggered when NB requests for service addition
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530984func (vpv *VoltPortVnet) AddSvc(cntx context.Context, svc *VoltService) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530985 //vpv.services = append(vpv.services, svc)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530986 vpv.AddService(cntx, svc)
Naveen Sampath04696f72022-06-13 15:19:14 +0530987 logger.Debugw(ctx, "Added Service to VPV", log.Fields{"Num of SVCs": vpv.servicesCount.Load(), "SVC": svc})
988
989 // Learn the circuit-id and remote-id from the service
990 // TODO: There must be a better way of doing this. This
991 // may be explored
992 if svc.IgmpEnabled {
993 vpv.IgmpEnabled = true
994 }
995 // first time service activation MacLearning will have default value as None.
996 // to handle reciliency if anythng other then None we should retain it .
997 if svc.MacLearning == MacLearningNone {
998 if !vpv.DhcpRelay && !vpv.ArpRelay {
999 svc.MacLearning = MacLearningNone
1000 } else if vpv.MacLearning == Learn {
1001 svc.MacLearning = Learn
1002 } else if vpv.MacLearning == ReLearn {
1003 svc.MacLearning = ReLearn
1004 }
1005 }
1006
vinokuma926cb3e2023-03-29 11:41:06 +05301007 // TODO: Temp Change - Need to address MAC Learning flow issues completely
Naveen Sampath04696f72022-06-13 15:19:14 +05301008 if (svc.MacLearning == Learn || svc.MacLearning == ReLearn) && NonZeroMacAddress(vpv.MacAddr) {
1009 svc.MacAddr = vpv.MacAddr
1010 } else if vpv.servicesCount.Load() == 1 {
1011 vpv.MacAddr = svc.MacAddr
1012 }
1013
1014 vpv.MacLearning = svc.MacLearning
1015 vpv.PonPort = svc.PonPort
1016 logger.Debugw(ctx, "Added MAC to VPV", log.Fields{"MacLearning": vpv.MacLearning, "VPV": vpv})
vinokuma926cb3e2023-03-29 11:41:06 +05301017 // Reconfigure Vlans based on Vlan Control type
Naveen Sampath04696f72022-06-13 15:19:14 +05301018 svc.VlanControl = vpv.VlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301019 if svc.McastService {
1020 vpv.McastService = true
1021 vpv.McastTechProfileID = svc.TechProfileID
vinokuma926cb3e2023-03-29 11:41:06 +05301022 // Assumption: Only one Pbit for mcast service
Naveen Sampath04696f72022-06-13 15:19:14 +05301023 vpv.McastPbit = svc.Pbits[0]
1024 vpv.McastUsMeterID = svc.UsMeterID
1025 vpv.SchedID = svc.SchedID
1026 }
1027 svc.ONTEtherTypeClassification = vpv.ONTEtherTypeClassification
1028 svc.AllowTransparent = vpv.AllowTransparent
1029 svc.SVlanTpid = vpv.SVlanTpid
1030
vinokuma926cb3e2023-03-29 11:41:06 +05301031 // Ensure configuring the mvlan profile only once
1032 // One subscriber cannot have multiple mvlan profiles. Only the first configuration is valid
Naveen Sampath04696f72022-06-13 15:19:14 +05301033 if svc.MvlanProfileName != "" {
1034 if vpv.MvlanProfileName == "" {
1035 vpv.MvlanProfileName = svc.MvlanProfileName
1036 } else {
1037 logger.Warnw(ctx, "Mvlan Profile already configured for subscriber. Ignoring new Mvlan", log.Fields{"Existing Mvlan": vpv.MvlanProfileName, "New Mvlan": svc.MvlanProfileName})
1038 }
1039 }
1040
Akash Sonia8246972023-01-03 10:37:08 +05301041 voltDevice, err := GetApplication().GetDeviceFromPort(vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301042 if err != nil {
1043 logger.Warnw(ctx, "Not pushing Service Flows: Error Getting Device", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301044 // statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1045 // TODO-COMM: vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301046 return
1047 }
Tinoj Josephec742f62022-09-29 19:11:10 +05301048 if !svc.IsActivated {
1049 logger.Warn(ctx, "Not pushing Service Flows: Service Not activated")
1050 return
1051 }
Akash Sonia8246972023-01-03 10:37:08 +05301052
vinokuma926cb3e2023-03-29 11:41:06 +05301053 // If NNI port is not mached to nb nni port
Akash Sonia8246972023-01-03 10:37:08 +05301054 devConfig := GetApplication().GetDeviceConfig(voltDevice.SerialNum)
1055
Akash Soni53da2852023-03-15 00:31:31 +05301056 if devConfig.UplinkPort != voltDevice.NniPort {
1057 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 +05301058 return
1059 }
vinokuma926cb3e2023-03-29 11:41:06 +05301060 // Push Service Flows if DHCP relay is not configured
1061 // or already DHCP flows are configured for the VPV
1062 // to which the serivce is associated
Naveen Sampath04696f72022-06-13 15:19:14 +05301063 if vpv.FlowsApplied {
1064 if NonZeroMacAddress(vpv.MacAddr) || svc.MacLearning == MacLearningNone {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301065 svc.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301066 } else {
Akash Sonia8246972023-01-03 10:37:08 +05301067 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301068 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1069 }
1070 }
1071 }
1072
vinokuma926cb3e2023-03-29 11:41:06 +05301073 // Assumption: Igmp will be enabled only for one service and SubMgr ensure the same
Naveen Sampath04696f72022-06-13 15:19:14 +05301074 // When already the port is UP and provisioned a service without igmp, then trap flows for subsequent
1075 // service with Igmp Enabled needs to be installed
1076 if svc.IgmpEnabled && vpv.FlowsApplied {
1077 logger.Infow(ctx, "Add Service - IGMP Flows", log.Fields{"Device": vpv.Device, "Port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301078 if err := vpv.AddIgmpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301079 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301080 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1081 }
1082
1083 if vpv.McastService {
vinokuma926cb3e2023-03-29 11:41:06 +05301084 // For McastService, send Service Activated indication once IGMP US flow is pushed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301085 vpv.RangeOnServices(cntx, PostAccessConfigSuccessInd)
Naveen Sampath04696f72022-06-13 15:19:14 +05301086 }
1087 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301088 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301089}
1090
1091// setLearntMAC to set learnt mac
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301092func (vpv *VoltPortVnet) setLearntMAC(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301093 svc := value.(*VoltService)
1094 svc.SetMacAddr(vpv.MacAddr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301095 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301096 return true
1097}
1098
1099// PostAccessConfigSuccessInd for posting access config success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301100func PostAccessConfigSuccessInd(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301101 return true
1102}
1103
1104// updateIPv4AndProvisionFlows to update ipv4 and provisional flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301105func (vpv *VoltPortVnet) updateIPv4AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301106 svc := value.(*VoltService)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301107 logger.Infow(ctx, "Updating Ipv4 address for service", log.Fields{"ServiceName": svc.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301108 svc.SetIpv4Addr(vpv.Ipv4Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301109 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301110
1111 return true
1112}
1113
1114// updateIPv6AndProvisionFlows to update ipv6 and provisional flow
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301115func (vpv *VoltPortVnet) updateIPv6AndProvisionFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301116 svc := value.(*VoltService)
1117 svc.SetIpv6Addr(vpv.Ipv6Addr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301118 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301119
1120 return true
1121}
1122
1123// AddUsHsiaFlows to add upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301124func AddUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301125 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301126 if err := svc.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301127 logger.Warnw(ctx, "Add US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1128 }
1129 return true
1130}
1131
1132// AddDsHsiaFlows to add downstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301133func AddDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301134 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301135 if err := svc.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301136 logger.Warnw(ctx, "Add DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1137 }
1138 return true
1139}
1140
1141// ClearFlagsInService to clear the flags used in service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301142func ClearFlagsInService(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301143 svc := value.(*VoltService)
1144 svc.ServiceLock.Lock()
1145 svc.IgmpFlowsApplied = false
1146 svc.DsDhcpFlowsApplied = false
1147 svc.DsHSIAFlowsApplied = false
1148 svc.Icmpv6FlowsApplied = false
1149 svc.UsHSIAFlowsApplied = false
1150 svc.UsDhcpFlowsApplied = false
1151 svc.PendingFlows = make(map[string]bool)
1152 svc.AssociatedFlows = make(map[string]bool)
1153 svc.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301154 svc.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301155 logger.Debugw(ctx, "Cleared Flow Flags for service", log.Fields{"name": svc.Name})
1156 return true
1157}
1158
1159// DelDsHsiaFlows to delete hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301160func DelDsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301161 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301162 if err := svc.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301163 logger.Warnw(ctx, "Delete DS hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1164 }
1165 return true
1166}
1167
1168// DelUsHsiaFlows to delete upstream hsia flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301169func DelUsHsiaFlows(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301170 svc := value.(*VoltService)
Akash Sonia8246972023-01-03 10:37:08 +05301171 if err := svc.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301172 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"service": svc.Name, "Error": err})
1173 }
1174 return true
1175}
1176
1177// ClearServiceCounters to clear the service counters
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301178func ClearServiceCounters(cntx context.Context, key, value interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05301179 svc := value.(*VoltService)
1180 //Delete the per service counter too
1181 GetApplication().ServiceCounters.Delete(svc.Name)
1182 if svc.IgmpEnabled && svc.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301183 _ = db.DelAllServiceChannelCounter(cntx, svc.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301184 }
1185 return true
1186}
1187
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301188// AddMeterToDevice to add meter config to device, used in FTTB case
1189func AddMeterToDevice(cntx context.Context, key, value interface{}) bool {
1190 svc := value.(*VoltService)
Akash Soni53da2852023-03-15 00:31:31 +05301191 if err := svc.AddMeterToDevice(cntx); err != nil {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301192 logger.Warnw(ctx, "Add Meter failed", log.Fields{"service": svc.Name, "Error": err})
1193 }
1194 return true
1195}
1196
vinokuma926cb3e2023-03-29 11:41:06 +05301197// AddTrapFlows - Adds US & DS Trap flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301198func (vpv *VoltPortVnet) AddTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301199 if !vpv.FlowsApplied || vgcRebooted {
1200 if vpv.DhcpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301201 if err := vpv.AddUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301202 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301203 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1204 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301205 if err := vpv.AddDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301206 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301207 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1208 }
1209 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1210 log.Fields{"port": vpv.Port})
1211 //vpv.updateICMPv6McGroup(true)
1212 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301213 if err := vpv.AddUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301214 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301215 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1216 }
1217 logger.Info(ctx, "ARP trap rules not added in downstream direction")
Naveen Sampath04696f72022-06-13 15:19:14 +05301218 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301219 if err := vpv.AddUsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301220 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301221 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1222 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301223 if err := vpv.AddDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301224 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301225 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1226 }
1227 }
1228 vpv.FlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301229 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301230 }
1231}
1232
vinokuma926cb3e2023-03-29 11:41:06 +05301233// DelTrapFlows - Removes all US & DS DHCP, IGMP trap flows.
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301234func (vpv *VoltPortVnet) DelTrapFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 // Delete HSIA & DHCP flows before deleting IGMP flows
1236 if vpv.FlowsApplied || vgcRebooted {
1237 if vpv.DhcpRelay {
Akash Sonia8246972023-01-03 10:37:08 +05301238 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301239 logger.Warnw(ctx, "Delete US hsia flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1240 "UniVlan": vpv.UniVlan, "Error": err})
1241 }
1242 logger.Infow(ctx, "ICMPv6 MC Group modification will not be triggered to rwcore for ",
1243 log.Fields{"port": vpv.Port})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301244 if err := vpv.DelDsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301245 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301246 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1247 }
1248 //vpv.updateICMPv6McGroup(false)
1249 } else if vpv.ArpRelay {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301250 if err := vpv.DelUsArpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301251 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301252 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1253 }
1254 } else if vpv.PppoeIa {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301255 if err := vpv.DelUsPppoeFlows(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 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301259 if err := vpv.DelDsPppoeFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301260 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301261 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1262 }
1263 }
1264 vpv.FlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301265 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301266 }
Akash Sonia8246972023-01-03 10:37:08 +05301267 if err := vpv.DelIgmpFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301268 logger.Warnw(ctx, "Delete igmp flow failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
1269 "UniVlan": vpv.UniVlan, "Error": err})
1270 }
1271}
1272
1273// DelHsiaFlows deletes the service flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301274func (vpv *VoltPortVnet) DelHsiaFlows(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301275 // no HSIA flows for multicast service
1276 if !vpv.McastService {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301277 vpv.RangeOnServices(cntx, DelUsHsiaFlows)
1278 vpv.RangeOnServices(cntx, DelDsHsiaFlows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301279 }
1280}
1281
vinokuma926cb3e2023-03-29 11:41:06 +05301282// ClearServiceCounters - Removes all igmp counters for a service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301283func (vpv *VoltPortVnet) ClearServiceCounters(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301284 //send flows deleted indication to submgr
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301285 vpv.RangeOnServices(cntx, ClearServiceCounters)
Naveen Sampath04696f72022-06-13 15:19:14 +05301286}
1287
1288// AddUsDhcpFlows pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301289func (vpv *VoltPortVnet) AddUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301290 var vd *VoltDevice
1291 device := vpv.Device
1292
1293 if vd = GetApplication().GetDevice(device); vd != nil {
1294 if vd.State != controller.DeviceStateUP {
1295 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})
1296 return nil
1297 }
1298 } else {
1299 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})
1300 return errorCodes.ErrDeviceNotFound
1301 }
1302
1303 flows, err := vpv.BuildUsDhcpFlows()
1304 if err == nil {
1305 logger.Debugw(ctx, "Adding US DHCP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301306 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301307 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301308 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301309 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1310 }
1311 } else {
1312 logger.Errorw(ctx, "US DHCP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
vinokuma926cb3e2023-03-29 11:41:06 +05301313 // push ind here ABHI
Akash Sonia8246972023-01-03 10:37:08 +05301314 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301315 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301316 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301317 return nil
1318}
1319
1320// AddDsDhcpFlows function pushes the DHCP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301321func (vpv *VoltPortVnet) AddDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301322 var vd *VoltDevice
1323 device := vpv.Device
1324
1325 if vd = GetApplication().GetDevice(device); vd != nil {
1326 if vd.State != controller.DeviceStateUP {
1327 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})
1328 return nil
1329 }
1330 } else {
1331 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})
1332 return errorCodes.ErrDeviceNotFound
1333 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301334 if vd.GlobalDhcpFlowAdded {
1335 logger.Info(ctx, "Global Dhcp flow already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301336 return nil
1337 }
1338
1339 flows, err := vpv.BuildDsDhcpFlows()
1340 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301341 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
vinokuma926cb3e2023-03-29 11:41:06 +05301342 // push ind here and procced
Akash Sonia8246972023-01-03 10:37:08 +05301343 statusCode, statusMessage := errorCodes.GetErrorInfo(err1)
Naveen Sampath04696f72022-06-13 15:19:14 +05301344 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301345 }
1346 } else {
1347 logger.Errorw(ctx, "DS DHCP Flow Add Failed", log.Fields{"Reason": err.Error()})
vinokuma926cb3e2023-03-29 11:41:06 +05301348 // send ind here and proceed
Akash Sonia8246972023-01-03 10:37:08 +05301349 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301350 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
Naveen Sampath04696f72022-06-13 15:19:14 +05301351 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301352 if GetApplication().GetVendorID() != Radisys {
1353 vd.GlobalDhcpFlowAdded = true
1354 }
1355 return nil
1356}
1357
1358// DelDhcpFlows deletes both US & DS DHCP flows applied for this Vnet instantiated on the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301359func (vpv *VoltPortVnet) DelDhcpFlows(cntx context.Context) {
1360 if err := vpv.DelUsDhcpFlows(cntx); err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301361 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301362 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1363 }
1364
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301365 if err := vpv.DelDsDhcpFlows(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}
1370
1371// DelUsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1372// Write the status of the VPV to the DB once the delete is scheduled
1373// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301374func (vpv *VoltPortVnet) DelUsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301375 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1376 if err != nil {
1377 return err
1378 }
1379
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301380 err = vpv.delDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301381 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301382 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301383 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1384 }
Akash Sonia8246972023-01-03 10:37:08 +05301385
Naveen Sampath04696f72022-06-13 15:19:14 +05301386 return nil
1387}
1388
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301389func (vpv *VoltPortVnet) delDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301390 flows, err := vpv.BuildUsDhcpFlows()
1391 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301392 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301393 }
1394 logger.Errorw(ctx, "US DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1395 return err
1396}
Naveen Sampath04696f72022-06-13 15:19:14 +05301397
1398// DelDsDhcpFlows delete the DHCP flows applied for this Vnet instantiated on the port
1399// Write the status of the VPV to the DB once the delete is scheduled
1400// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301401func (vpv *VoltPortVnet) DelDsDhcpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301402 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1403 if err != nil {
1404 return err
1405 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301406 err = vpv.delDsDhcp4Flows(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301407 if err != nil {
Akash Sonia8246972023-01-03 10:37:08 +05301408 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
Naveen Sampath04696f72022-06-13 15:19:14 +05301409 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1410 }
1411 /*
Akash Sonia8246972023-01-03 10:37:08 +05301412 err = vpv.delDsDhcp6Flows(device)
1413 if err != nil {
1414 statusCode, statusMessage := errorCodes.GetErrorInfo(err)
1415 vpv.FlowInstallFailure("VGC processing failure", statusCode, statusMessage)
1416 }*/
Naveen Sampath04696f72022-06-13 15:19:14 +05301417 return nil
1418}
1419
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301420func (vpv *VoltPortVnet) delDsDhcp4Flows(cntx context.Context, device *VoltDevice) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301421 flows, err := vpv.BuildDsDhcpFlows()
1422 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301423 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301424 }
1425 logger.Errorw(ctx, "DS DHCP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1426 return err
1427}
1428
1429/*
1430func (vpv *VoltPortVnet) delDsDhcp6Flows(device *VoltDevice) error {
1431 flows, err := vpv.BuildDsDhcp6Flows()
1432 if err == nil {
1433 return vpv.RemoveFlows(device, flows)
1434 }
1435 logger.Errorw(ctx, "DS DHCP6 Flow Delete Failed", log.Fields{"Reason": err.Error()})
1436 return err
1437}*/
1438
1439// AddUsArpFlows pushes the ARP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301440func (vpv *VoltPortVnet) AddUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301441 var vd *VoltDevice
1442 device := vpv.Device
1443 if vd = GetApplication().GetDevice(device); vd != nil {
1444 if vd.State != controller.DeviceStateUP {
1445 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})
1446 return nil
1447 }
1448 } else {
1449 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})
1450 return errorCodes.ErrDeviceNotFound
1451 }
1452
1453 flows, err := vpv.BuildUsArpFlows()
1454 if err == nil {
1455 logger.Debugw(ctx, "Adding US ARP flows", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301456 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301457 return err1
1458 }
1459 } else {
1460 logger.Errorw(ctx, "US ARP Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1461 return err
1462 }
1463 return nil
1464}
1465
1466// DelUsArpFlows delete the ARP flows applied for this Vnet instantiated on the port
1467// Write the status of the VPV to the DB once the delete is scheduled
1468// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301469func (vpv *VoltPortVnet) DelUsArpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301470 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1471 if err != nil {
1472 return err
1473 }
1474 flows, err := vpv.BuildUsArpFlows()
1475 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301476 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301477 }
1478 logger.Errorw(ctx, "US ARP Flow Delete Failed", log.Fields{"Reason": err.Error()})
1479 return err
1480}
1481
1482// AddUsPppoeFlows pushes the PPPoE flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301483func (vpv *VoltPortVnet) AddUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301484 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1485
1486 var vd *VoltDevice
1487 device := vpv.Device
1488
1489 if vd = GetApplication().GetDevice(device); vd != nil {
1490 if vd.State != controller.DeviceStateUP {
1491 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})
1492 return nil
1493 }
1494 } else {
1495 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})
1496 return errorCodes.ErrDeviceNotFound
1497 }
1498
1499 if flows, err := vpv.BuildUsPppoeFlows(); err == nil {
1500 logger.Debugw(ctx, "Adding US PPPoE flows", log.Fields{"Device": device})
1501
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301502 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301503 return err1
1504 }
1505 } else {
1506 logger.Errorw(ctx, "US PPPoE Flow Add Failed", log.Fields{"Reason": err.Error(), "Device": device})
1507 return err
1508 }
1509 return nil
1510}
1511
1512// AddDsPppoeFlows to add downstream pppoe flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301513func (vpv *VoltPortVnet) AddDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301514 logger.Debugw(ctx, "Adding DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1515 var vd *VoltDevice
1516 device := vpv.Device
1517
1518 if vd = GetApplication().GetDevice(device); vd != nil {
1519 if vd.State != controller.DeviceStateUP {
1520 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})
1521 return nil
1522 }
1523 } else {
1524 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})
1525 return errorCodes.ErrDeviceNotFound
1526 }
1527
1528 flows, err := vpv.BuildDsPppoeFlows()
1529 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301530 if err1 := vpv.PushFlows(cntx, vd, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301531 return err1
1532 }
1533 } else {
1534 logger.Errorw(ctx, "DS PPPoE Flow Add Failed", log.Fields{"Reason": err.Error()})
1535 return err
1536 }
1537 return nil
1538}
1539
1540// DelUsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1541// Write the status of the VPV to the DB once the delete is scheduled
1542// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301543func (vpv *VoltPortVnet) DelUsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301544 logger.Debugw(ctx, "Deleting US PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1545 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1546 if err != nil {
1547 return err
1548 }
1549 flows, err := vpv.BuildUsPppoeFlows()
1550 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301551 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301552 }
1553 logger.Errorw(ctx, "US PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1554 return err
1555}
1556
1557// DelDsPppoeFlows delete the PPPoE flows applied for this Vnet instantiated on the port
1558// Write the status of the VPV to the DB once the delete is scheduled
1559// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301560func (vpv *VoltPortVnet) DelDsPppoeFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301561 logger.Debugw(ctx, "Deleting DS PPPoE flows", log.Fields{"STAG": vpv.SVlan, "CTAG": vpv.CVlan, "Device": vpv.Device})
1562 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1563 if err != nil {
1564 return err
1565 }
1566 flows, err := vpv.BuildDsPppoeFlows()
1567 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301568 return vpv.RemoveFlows(cntx, device, flows)
Naveen Sampath04696f72022-06-13 15:19:14 +05301569 }
1570 logger.Errorw(ctx, "DS PPPoE Flow Delete Failed", log.Fields{"Reason": err.Error()})
1571 return err
1572}
1573
1574// AddIgmpFlows function pushes the IGMP flows to the VOLTHA via the controller
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301575func (vpv *VoltPortVnet) AddIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301576 if !vpv.IgmpFlowsApplied || vgcRebooted {
1577 if vpv.MvlanProfileName == "" {
1578 logger.Info(ctx, "Mvlan Profile not configured. Ignoring Igmp trap flow")
1579 return nil
1580 }
1581 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1582 if err != nil {
1583 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1584 return err
1585 } else if device.State != controller.DeviceStateUP {
1586 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})
1587 return nil
1588 }
1589 flows, err := vpv.BuildIgmpFlows()
1590 if err == nil {
1591 for cookie := range flows.SubFlows {
1592 if vd := GetApplication().GetDevice(device.Name); vd != nil {
1593 cookie := strconv.FormatUint(cookie, 10)
1594 fe := &FlowEvent{
1595 eType: EventTypeUsIgmpFlowAdded,
1596 cookie: cookie,
1597 eventData: vpv,
1598 }
1599 vd.RegisterFlowAddEvent(cookie, fe)
1600 }
1601 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301602 if err1 := cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301603 return err1
1604 }
1605 } else {
1606 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1607 return err
1608 }
1609 vpv.IgmpFlowsApplied = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301610 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301611 }
1612 return nil
1613}
1614
1615// DelIgmpFlows delete the IGMP flows applied for this Vnet instantiated on the port
1616// Write the status of the VPV to the DB once the delete is scheduled
1617// for dispatch
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301618func (vpv *VoltPortVnet) DelIgmpFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301619 if vpv.IgmpFlowsApplied || vgcRebooted {
1620 device, err := GetApplication().GetDeviceFromPort(vpv.Port)
1621 if err != nil {
1622 logger.Errorw(ctx, "Error getting device from port", log.Fields{"Port": vpv.Port, "Reason": err.Error()})
1623 return err
1624 }
1625 flows, err := vpv.BuildIgmpFlows()
1626 if err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301627 if err1 := vpv.RemoveFlows(cntx, device, flows); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301628 return err1
1629 }
1630 } else {
1631 logger.Errorw(ctx, "IGMP Flow Add Failed", log.Fields{"Reason": err.Error()})
1632 return err
1633 }
1634 vpv.IgmpFlowsApplied = false
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301635 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301636 }
1637 return nil
1638}
1639
1640// BuildUsDhcpFlows builds the US DHCP relay flows for a subscriber
1641// The flows included by this function cover US only as the DS is
1642// created either automatically by the VOLTHA or at the device level
1643// earlier
1644func (vpv *VoltPortVnet) BuildUsDhcpFlows() (*of.VoltFlow, error) {
1645 flow := &of.VoltFlow{}
1646 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1647
1648 logger.Infow(ctx, "Building US DHCP flow", log.Fields{"Port": vpv.Port})
1649 subFlow := of.NewVoltSubFlow()
1650 subFlow.SetTableID(0)
1651
vinokuma926cb3e2023-03-29 11:41:06 +05301652 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301653 subFlow.SetMatchVlan(vpv.CVlan)
1654 subFlow.SetMatchPbit(vpv.UsPonCTagPriority)
1655 subFlow.SetPcp(vpv.UsPonSTagPriority)
1656 subFlow.SetSetVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301657 } else {
1658 subFlow.SetMatchVlan(vpv.UniVlan)
1659 subFlow.SetSetVlan(vpv.CVlan)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301660 subFlow.SetPcp(vpv.DhcpPbit)
Naveen Sampath04696f72022-06-13 15:19:14 +05301661 }
1662 subFlow.SetUdpv4Match()
Naveen Sampath04696f72022-06-13 15:19:14 +05301663 subFlow.DstPort = 67
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301664 subFlow.SrcPort = 68
Naveen Sampath04696f72022-06-13 15:19:14 +05301665 uniport, err := GetApplication().GetPortID(vpv.Port)
1666 if err != nil {
1667 logger.Errorw(ctx, "Failed to fetch uni port from vpv", log.Fields{"error": err, "port": vpv.Port})
1668 return nil, err
1669 }
1670 subFlow.SetInPort(uniport)
1671 // PortName and PortID to be used for validation of port before flow pushing
1672 flow.PortID = uniport
1673 flow.PortName = vpv.Port
1674 subFlow.SetReportToController()
1675
1676 // Set techprofile, meterid of first service
1677 vpv.services.Range(func(key, value interface{}) bool {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301678 vs := value.(*VoltService)
1679 var writemetadata uint64
vinokuma926cb3e2023-03-29 11:41:06 +05301680 if vpv.VnetType == DpuMgmtTraffic {
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +05301681 writemetadata = uint64(vs.TechProfileID)<<32 + uint64(vs.UsMeterID)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301682 } else {
1683 writemetadata = uint64(vs.TechProfileID) << 32
1684 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301685 subFlow.SetWriteMetadata(writemetadata)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301686 subFlow.SetMeterID(vs.UsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301687 return false
1688 })
1689
Naveen Sampath04696f72022-06-13 15:19:14 +05301690 // metadata := uint64(uniport)
1691 // subFlow.SetWriteMetadata(metadata)
1692 allowTransparent := 0
1693 if vpv.AllowTransparent {
1694 allowTransparent = 1
1695 }
vinokuma926cb3e2023-03-29 11:41:06 +05301696 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301697 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1698 subFlow.SetTableMetadata(metadata)
1699 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301700 //| 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
1701 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.UsFlowMask
1702 subFlow.Priority = of.DhcpFlowPriority
1703
1704 flow.SubFlows[subFlow.Cookie] = subFlow
1705 logger.Infow(ctx, "Built US DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1706 return flow, nil
1707}
1708
1709// BuildDsDhcpFlows to build the downstream dhcp flows
1710func (vpv *VoltPortVnet) BuildDsDhcpFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301711 logger.Infow(ctx, "Building DS DHCP flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1712 flow := &of.VoltFlow{}
1713 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1714 subFlow := of.NewVoltSubFlow()
1715 subFlow.SetTableID(0)
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301716 // match on vlan only for fttb case
vinokuma926cb3e2023-03-29 11:41:06 +05301717 if vpv.VnetType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301718 subFlow.SetMatchVlan(vpv.SVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05301719 }
1720 subFlow.SetUdpv4Match()
1721 subFlow.SrcPort = 67
1722 subFlow.DstPort = 68
1723 uniport, _ := GetApplication().GetPortID(vpv.Port)
1724 nni, err := GetApplication().GetNniPort(vpv.Device)
1725 if err != nil {
1726 return nil, err
1727 }
1728 nniport, err := GetApplication().GetPortID(nni)
1729 if err != nil {
1730 return nil, err
1731 }
1732 subFlow.SetInPort(nniport)
1733 // PortName and PortID to be used for validation of port before flow pushing
1734 flow.PortID = uniport
1735 flow.PortName = vpv.Port
1736 // metadata := uint64(uniport)
1737 // subFlow.SetWriteMetadata(metadata)
1738 allowTransparent := 0
1739 if vpv.AllowTransparent {
1740 allowTransparent = 1
1741 }
vinokuma926cb3e2023-03-29 11:41:06 +05301742 if vpv.VnetType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301743 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1744 subFlow.SetTableMetadata(metadata)
1745 subFlow.Priority = of.DhcpFlowPriority
1746 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301747 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301748 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301749 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.DhcpArpFlowMask | of.DsFlowMask
Naveen Sampath04696f72022-06-13 15:19:14 +05301750
1751 flow.SubFlows[subFlow.Cookie] = subFlow
1752 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
1753
1754 return flow, nil
1755}
1756
1757// BuildUsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1758// application.
1759func (vpv *VoltPortVnet) BuildUsDhcp6Flows() (*of.VoltFlow, error) {
1760 flow := &of.VoltFlow{}
1761 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1762
1763 logger.Infow(ctx, "Building US DHCPv6 flow", log.Fields{"Port": vpv.Port})
1764 subFlow := of.NewVoltSubFlow()
1765 subFlow.SetTableID(0)
1766
1767 subFlow.SetMatchVlan(vpv.UniVlan)
1768 subFlow.SetSetVlan(vpv.CVlan)
1769 subFlow.SetUdpv6Match()
1770 subFlow.SrcPort = 546
1771 subFlow.DstPort = 547
1772 uniport, err := GetApplication().GetPortID(vpv.Port)
1773 if err != nil {
1774 return nil, err
1775 }
1776 // Set techprofile, meterid of first service
1777 vpv.services.Range(func(key, value interface{}) bool {
1778 svc := value.(*VoltService)
1779 writemetadata := uint64(svc.TechProfileID) << 32
1780 subFlow.SetWriteMetadata(writemetadata)
1781 subFlow.SetMeterID(svc.UsMeterID)
1782 return false
1783 })
1784 subFlow.SetInPort(uniport)
1785 // PortName and PortID to be used for validation of port before flow pushing
1786 flow.PortID = uniport
1787 flow.PortName = vpv.Port
vinokuma926cb3e2023-03-29 11:41:06 +05301788 // subFlow.SetMeterId(vpv.UsDhcpMeterId)
Naveen Sampath04696f72022-06-13 15:19:14 +05301789 // metadata := uint64(uniport)
1790 // subFlow.SetWriteMetadata(metadata)
1791 allowTransparent := 0
1792 if vpv.AllowTransparent {
1793 allowTransparent = 1
1794 }
1795 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1796 subFlow.SetTableMetadata(metadata)
1797 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301798 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301799 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.UsFlowMask
1800 subFlow.Priority = of.DhcpFlowPriority
1801
1802 flow.SubFlows[subFlow.Cookie] = subFlow
1803 logger.Infow(ctx, "Built US DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1804 return flow, nil
1805}
1806
1807// BuildDsDhcp6Flows to trap the DHCPv6 packets to be reported to the
1808// application.
1809func (vpv *VoltPortVnet) BuildDsDhcp6Flows() (*of.VoltFlow, error) {
1810 logger.Infow(ctx, "Building DS DHCPv6 flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1811
1812 flow := &of.VoltFlow{}
1813 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1814 subFlow := of.NewVoltSubFlow()
1815 subFlow.SetTableID(0)
1816
1817 vpv.setDsMatchVlan(subFlow)
1818 subFlow.SetUdpv6Match()
1819 subFlow.SrcPort = 547
1820 subFlow.DstPort = 547
1821 uniport, _ := GetApplication().GetPortID(vpv.Port)
1822 nni, err := GetApplication().GetNniPort(vpv.Device)
1823 if err != nil {
1824 return nil, err
1825 }
1826 nniport, err := GetApplication().GetPortID(nni)
1827 if err != nil {
1828 return nil, err
1829 }
1830 subFlow.SetInPort(nniport)
1831 // PortName and PortID to be used for validation of port before flow pushing
1832 flow.PortID = uniport
1833 flow.PortName = vpv.Port
1834 // metadata := uint64(uniport)
1835 // subFlow.SetWriteMetadata(metadata)
1836 allowTransparent := 0
1837 if vpv.AllowTransparent {
1838 allowTransparent = 1
1839 }
1840 metadata := uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1841 subFlow.SetTableMetadata(metadata)
1842 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05301843 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301844 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.Dhcpv6FlowMask | of.DsFlowMask
1845 subFlow.Priority = of.DhcpFlowPriority
1846
1847 flow.SubFlows[subFlow.Cookie] = subFlow
1848 logger.Infow(ctx, "Built DS DHCPv6 flow", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1849 return flow, nil
1850}
1851
1852// BuildUsArpFlows builds the US ARP relay flows for a subscriber
1853// The flows included by this function cover US only as the DS is
1854// created either automatically by the VOLTHA or at the device level
1855// earlier
1856func (vpv *VoltPortVnet) BuildUsArpFlows() (*of.VoltFlow, error) {
1857 flow := &of.VoltFlow{}
1858 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1859
1860 logger.Infow(ctx, "Building US ARP flow", log.Fields{"Port": vpv.Port})
1861 subFlow := of.NewVoltSubFlow()
1862 subFlow.SetTableID(0)
1863
1864 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1865 subFlow.SetMatchSrcMac(vpv.MacAddr)
1866 }
1867
1868 subFlow.SetMatchDstMac(BroadcastMAC)
1869 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1870 return nil, err
1871 }
1872 subFlow.SetArpMatch()
1873 uniport, err := GetApplication().GetPortID(vpv.Port)
1874 if err != nil {
1875 return nil, err
1876 }
1877 subFlow.SetInPort(uniport)
1878 // PortName and PortID to be used for validation of port before flow pushing
1879 flow.PortID = uniport
1880 flow.PortName = vpv.Port
1881 subFlow.SetReportToController()
1882 allowTransparent := 0
1883 if vpv.AllowTransparent {
1884 allowTransparent = 1
1885 }
1886 metadata := uint64(uniport)
1887 subFlow.SetWriteMetadata(metadata)
1888 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1889 subFlow.SetTableMetadata(metadata)
1890 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<32 | of.DhcpArpFlowMask | of.UsFlowMask
1891 subFlow.Priority = of.ArpFlowPriority
1892
1893 flow.SubFlows[subFlow.Cookie] = subFlow
1894 logger.Infow(ctx, "Built US ARP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1895 return flow, nil
1896}
1897
1898// setUsMatchVlan to set upstream match vlan
1899func (vpv *VoltPortVnet) setUsMatchVlan(flow *of.VoltSubFlow) error {
1900 switch vpv.VlanControl {
1901 case None:
1902 flow.SetMatchVlan(vpv.SVlan)
1903 case ONUCVlanOLTSVlan:
1904 flow.SetMatchVlan(vpv.CVlan)
1905 case OLTCVlanOLTSVlan:
1906 flow.SetMatchVlan(vpv.UniVlan)
1907 //flow.SetSetVlan(vpv.CVlan)
1908 case ONUCVlan:
1909 flow.SetMatchVlan(vpv.SVlan)
1910 case OLTSVlan:
1911 flow.SetMatchVlan(vpv.UniVlan)
1912 //flow.SetSetVlan(vpv.SVlan)
1913 default:
1914 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
1915 return errorCodes.ErrInvalidParamInRequest
1916 }
1917 return nil
1918}
1919
1920// BuildUsPppoeFlows to build upstream pppoe flows
1921func (vpv *VoltPortVnet) BuildUsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301922 flow := &of.VoltFlow{}
1923 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1924 logger.Infow(ctx, "Building US PPPoE flow", log.Fields{"Port": vpv.Port})
1925 subFlow := of.NewVoltSubFlow()
1926 subFlow.SetTableID(0)
1927
1928 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
1929 subFlow.SetMatchSrcMac(vpv.MacAddr)
1930 }
1931
1932 if err := vpv.setUsMatchVlan(subFlow); err != nil {
1933 return nil, err
1934 }
1935 subFlow.SetPppoeDiscoveryMatch()
1936 uniport, err := GetApplication().GetPortID(vpv.Port)
1937 if err != nil {
1938 return nil, err
1939 }
1940 subFlow.SetInPort(uniport)
1941 subFlow.SetReportToController()
1942 // PortName and PortID to be used for validation of port before flow pushing
1943 flow.PortID = uniport
1944 flow.PortName = vpv.Port
1945
1946 allowTransparent := 0
1947 if vpv.AllowTransparent {
1948 allowTransparent = 1
1949 }
1950 metadata := uint64(uniport)
1951 subFlow.SetWriteMetadata(metadata)
1952
1953 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
1954 subFlow.SetTableMetadata(metadata)
1955
vinokuma926cb3e2023-03-29 11:41:06 +05301956 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits pppoe mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05301957 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.UsFlowMask
1958 subFlow.Priority = of.PppoeFlowPriority
1959
1960 flow.SubFlows[subFlow.Cookie] = subFlow
1961 logger.Infow(ctx, "Built US PPPoE flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
1962 return flow, nil
1963}
1964
1965// BuildDsPppoeFlows to build downstream pppoe flows
1966func (vpv *VoltPortVnet) BuildDsPppoeFlows() (*of.VoltFlow, error) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301967 logger.Infow(ctx, "Building DS PPPoE flow", log.Fields{"Port": vpv.Port, "ML": vpv.MacLearning, "Mac": vpv.MacAddr})
1968 flow := &of.VoltFlow{}
1969 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1970 subFlow := of.NewVoltSubFlow()
1971 subFlow.SetTableID(0)
1972
1973 vpv.setDsMatchVlan(subFlow)
1974 subFlow.SetPppoeDiscoveryMatch()
1975
1976 if NonZeroMacAddress(vpv.MacAddr) {
1977 subFlow.SetMatchDstMac(vpv.MacAddr)
1978 }
1979
1980 uniport, _ := GetApplication().GetPortID(vpv.Port)
1981 nni, err := GetApplication().GetNniPort(vpv.Device)
1982 if err != nil {
1983 return nil, err
1984 }
1985 nniport, err := GetApplication().GetPortID(nni)
1986 if err != nil {
1987 return nil, err
1988 }
1989 subFlow.SetInPort(nniport)
1990 // PortName and PortID to be used for validation of port before flow pushing
1991 flow.PortID = uniport
1992 flow.PortName = vpv.Port
1993 metadata := uint64(uniport)
1994 subFlow.SetWriteMetadata(metadata)
1995 allowTransparent := 0
1996 if vpv.AllowTransparent {
1997 allowTransparent = 1
1998 }
1999 metadata = uint64(allowTransparent)<<56 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2000 subFlow.SetTableMetadata(metadata)
2001 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302002 // | 12-bit cvlan | 4 bits empty | <32-bits uniport>| 16-bits dhcp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302003 subFlow.Cookie = uint64(vpv.CVlan)<<52 | uint64(uniport)<<16 | of.PppoeFlowMask | of.DsFlowMask
2004 subFlow.Priority = of.PppoeFlowPriority
2005
2006 flow.SubFlows[subFlow.Cookie] = subFlow
2007 logger.Infow(ctx, "Built DS DHCP flow ", log.Fields{"cookie": subFlow.Cookie, "Flow": flow})
2008 return flow, nil
2009}
2010
2011// setDsMatchVlan to set downstream match vlan
2012func (vpv *VoltPortVnet) setDsMatchVlan(flow *of.VoltSubFlow) {
2013 switch vpv.VlanControl {
2014 case None:
2015 flow.SetMatchVlan(vpv.SVlan)
2016 case ONUCVlanOLTSVlan,
2017 OLTCVlanOLTSVlan,
2018 ONUCVlan,
2019 OLTSVlan:
2020 flow.SetMatchVlan(vpv.SVlan)
2021 default:
2022 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2023 }
2024}
2025
2026// BuildIgmpFlows builds the US IGMP flows for a subscriber. IGMP requires flows only
2027// in the US direction.
2028func (vpv *VoltPortVnet) BuildIgmpFlows() (*of.VoltFlow, error) {
2029 logger.Infow(ctx, "Building US IGMP Flow", log.Fields{"Port": vpv.Port})
2030 mvp := GetApplication().GetMvlanProfileByName(vpv.MvlanProfileName)
2031 if mvp == nil {
2032 return nil, errors.New("Mvlan Profile configured not found")
2033 }
2034 mvlan := mvp.GetUsMatchVlan()
2035 flow := &of.VoltFlow{}
2036 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2037 subFlow := of.NewVoltSubFlow()
2038 subFlow.SetTableID(0)
2039
Akash Sonia8246972023-01-03 10:37:08 +05302040 subFlow.SetMatchVlan(vpv.UniVlan)
2041 subFlow.SetSetVlan(vpv.CVlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302042
2043 uniport, err := GetApplication().GetPortID(vpv.Port)
2044 if err != nil {
2045 return nil, err
2046 }
2047 subFlow.SetInPort(uniport)
2048 // PortName and PortID to be used for validation of port before flow pushing
2049 flow.PortID = uniport
2050 flow.PortName = vpv.Port
2051
2052 if vpv.MacLearning == MacLearningNone && NonZeroMacAddress(vpv.MacAddr) {
2053 subFlow.SetMatchSrcMac(vpv.MacAddr)
2054 }
2055 logger.Infow(ctx, "Mvlan", log.Fields{"mvlan": mvlan})
vinokuma926cb3e2023-03-29 11:41:06 +05302056 // metadata := uint64(mvlan)
Naveen Sampath04696f72022-06-13 15:19:14 +05302057
2058 if vpv.McastService {
2059 metadata := uint64(vpv.McastUsMeterID)
2060 metadata = metadata | uint64(vpv.McastTechProfileID)<<32
2061 subFlow.SetMatchPbit(vpv.McastPbit)
2062 subFlow.SetMeterID(vpv.McastUsMeterID)
2063 subFlow.SetWriteMetadata(metadata)
2064 } else {
2065 // Set techprofile, meterid of first service
2066 vpv.services.Range(func(key, value interface{}) bool {
2067 svc := value.(*VoltService)
2068 writemetadata := uint64(svc.TechProfileID) << 32
2069 subFlow.SetWriteMetadata(writemetadata)
2070 subFlow.SetMeterID(svc.UsMeterID)
2071 return false
2072 })
2073 }
2074
2075 allowTransparent := 0
2076 if vpv.AllowTransparent {
2077 allowTransparent = 1
2078 }
2079 metadata := uint64(allowTransparent)<<56 | uint64(vpv.SchedID)<<40 | uint64(vpv.ONTEtherTypeClassification)<<36 | uint64(vpv.VlanControl)<<32 | uint64(vpv.UniVlan)<<16 | uint64(vpv.CVlan)
2080 subFlow.SetTableMetadata(metadata)
2081 subFlow.SetIgmpMatch()
2082 subFlow.SetReportToController()
vinokuma926cb3e2023-03-29 11:41:06 +05302083 // | 16 bits empty | <32-bits uniport>| 16-bits igmp mask or flow mask |
Naveen Sampath04696f72022-06-13 15:19:14 +05302084 subFlow.Cookie = uint64(uniport)<<16 | of.IgmpFlowMask | of.UsFlowMask
2085 subFlow.Priority = of.IgmpFlowPriority
2086
2087 flow.SubFlows[subFlow.Cookie] = subFlow
2088 logger.Infow(ctx, "Built US IGMP flow ", log.Fields{"cookie": subFlow.Cookie, "flow": flow})
2089 return flow, nil
2090}
2091
2092// WriteToDb for writing to database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302093func (vpv *VoltPortVnet) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302094 if vpv.DeleteInProgress {
2095 logger.Warnw(ctx, "Skipping Redis Update for VPV, VPV delete in progress", log.Fields{"Vnet": vpv.VnetName, "Port": vpv.Port})
2096 return
2097 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302098 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302099}
2100
vinokuma926cb3e2023-03-29 11:41:06 +05302101// ForceWriteToDb force commit a VPV to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302102func (vpv *VoltPortVnet) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302103 vpv.PendingFlowLock.RLock()
2104 defer vpv.PendingFlowLock.RUnlock()
2105 vpv.Version = database.PresentVersionMap[database.VpvPath]
2106 if b, err := json.Marshal(vpv); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302107 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 +05302108 logger.Warnw(ctx, "VPV write to DB failed", log.Fields{"port": vpv.Port, "SVlan": vpv.SVlan, "CVlan": vpv.CVlan,
2109 "UniVlan": vpv.UniVlan, "Error": err})
2110 }
2111 }
2112}
2113
2114// DelFromDb for deleting from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302115func (vpv *VoltPortVnet) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302116 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 +05302117 _ = db.DelVpv(cntx, vpv.Port, uint16(vpv.SVlan), uint16(vpv.CVlan), uint16(vpv.UniVlan))
Naveen Sampath04696f72022-06-13 15:19:14 +05302118}
2119
2120// ClearAllServiceFlags to clear all service flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302121func (vpv *VoltPortVnet) ClearAllServiceFlags(cntx context.Context) {
2122 vpv.RangeOnServices(cntx, ClearFlagsInService)
Naveen Sampath04696f72022-06-13 15:19:14 +05302123}
2124
2125// ClearAllVpvFlags to clear all vpv flags
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302126func (vpv *VoltPortVnet) ClearAllVpvFlags(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302127 vpv.PendingFlowLock.Lock()
2128 vpv.FlowsApplied = false
2129 vpv.IgmpFlowsApplied = false
2130 vpv.PendingDeleteFlow = make(map[string]bool)
2131 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302132 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302133 logger.Debugw(ctx, "Cleared Flow Flags for VPV",
2134 log.Fields{"device": vpv.Device, "port": vpv.Port,
2135 "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2136}
2137
2138// CreateVpvFromString to create vpv from string
2139func (va *VoltApplication) CreateVpvFromString(b []byte, hash string) {
2140 var vpv VoltPortVnet
2141 if err := json.Unmarshal(b, &vpv); err == nil {
2142 vnetsByPortsSliceIntf, ok := va.VnetsByPort.Load(vpv.Port)
2143 if !ok {
2144 va.VnetsByPort.Store(vpv.Port, []*VoltPortVnet{})
2145 vnetsByPortsSliceIntf = []*VoltPortVnet{}
2146 }
2147 vpv.servicesCount = atomic.NewUint64(0)
2148 vnetsByPortsSlice := vnetsByPortsSliceIntf.([]*VoltPortVnet)
2149 vnetsByPortsSlice = append(vnetsByPortsSlice, &vpv)
2150 va.VnetsByPort.Store(vpv.Port, vnetsByPortsSlice)
2151 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2152 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
2153 vnet.associatePortToVnet(vpv.Port)
2154 }
2155
2156 if vpv.DeleteInProgress {
2157 va.VoltPortVnetsToDelete[&vpv] = true
2158 logger.Warnw(ctx, "VPV (restored) to be deleted", log.Fields{"Port": vpv.Port, "Vnet": vpv.VnetName})
2159 }
2160 logger.Debugw(ctx, "Added VPV from string", log.Fields{"port": vpv.Port, "svlan": vpv.SVlan, "cvlan": vpv.CVlan, "univlan": vpv.UniVlan})
2161 }
2162}
2163
2164// RestoreVpvsFromDb to restore vpvs from database
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302165func (va *VoltApplication) RestoreVpvsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302166 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302167 vpvs, _ := db.GetVpvs(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302168 for hash, vpv := range vpvs {
2169 b, ok := vpv.Value.([]byte)
2170 if !ok {
2171 logger.Warn(ctx, "The value type is not []byte")
2172 continue
2173 }
2174 va.CreateVpvFromString(b, hash)
2175 }
2176}
2177
2178// GetVnetByPort : VNET related functionality of VOLT Application here on.
2179// Get the VNET from a port. The port identity is passed as device and port identities in string.
2180// The identity of the VNET is the SVLAN and the CVLAN. Only if the both match the VLAN
2181// is assumed to have matched. TODO: 1:1 should be treated differently and needs to be addressed
2182func (va *VoltApplication) GetVnetByPort(port string, svlan of.VlanType, cvlan of.VlanType, univlan of.VlanType) *VoltPortVnet {
2183 if _, ok := va.VnetsByPort.Load(port); !ok {
2184 return nil
2185 }
2186 vpvs, _ := va.VnetsByPort.Load(port)
2187 for _, vpv := range vpvs.([]*VoltPortVnet) {
2188 if vpv.MatchesVlans(svlan, cvlan, univlan) {
2189 return vpv
2190 }
2191 }
2192 return nil
2193}
2194
2195// AddVnetToPort to add vnet to port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302196func (va *VoltApplication) AddVnetToPort(cntx context.Context, port string, vvnet *VoltVnet, vs *VoltService) *VoltPortVnet {
Naveen Sampath04696f72022-06-13 15:19:14 +05302197 // The VNET is not on the port and is to be added
2198 logger.Debugw(ctx, "Adding VNET to Port", log.Fields{"Port": port, "VNET": vvnet.Name})
2199 vpv := NewVoltPortVnet(vvnet)
2200 vpv.MacLearning = vvnet.MacLearning
2201 vpv.Port = port
2202 vvnet.associatePortToVnet(port)
2203 if _, ok := va.VnetsByPort.Load(port); !ok {
2204 va.VnetsByPort.Store(port, []*VoltPortVnet{})
2205 }
2206 vpvsIntf, _ := va.VnetsByPort.Load(port)
2207 vpvs := vpvsIntf.([]*VoltPortVnet)
2208 vpvs = append(vpvs, vpv)
2209 va.VnetsByPort.Store(port, vpvs)
2210 va.UpdateMacInPortMap(vpv.MacAddr, vpv.Port)
2211
2212 vpv.VpvLock.Lock()
2213 defer vpv.VpvLock.Unlock()
2214
2215 // Add the service that is causing the VNET to be added to the port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302216 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05302217
Tinoj Josephec742f62022-09-29 19:11:10 +05302218 if !vs.IsActivated {
2219 logger.Warn(ctx, "Not Checking port state: Service Not activated")
2220 // Process the PORT UP if the port is already up
2221 d, err := va.GetDeviceFromPort(port)
2222 if err == nil {
2223 vpv.setDevice(d.Name)
2224 }
2225 vpv.WriteToDb(cntx)
2226 return vpv
2227 }
2228
Naveen Sampath04696f72022-06-13 15:19:14 +05302229 // Process the PORT UP if the port is already up
2230 d, err := va.GetDeviceFromPort(port)
2231 if err == nil {
2232 vpv.setDevice(d.Name)
2233 p := d.GetPort(port)
2234 if p != nil {
Akash Soni024eb8e2023-04-28 16:25:09 +05302235 logger.Infow(ctx, "Checking UNI port state", log.Fields{"State": p.State})
2236 if d.State == controller.DeviceStateUP && p.State == PortStateUp {
2237 vpv.PortUpInd(cntx, d, port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302238 }
2239 }
2240 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302241 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302242 return vpv
2243}
2244
2245// DelVnetFromPort for deleting vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302246func (va *VoltApplication) DelVnetFromPort(cntx context.Context, port string, vpv *VoltPortVnet) {
vinokuma926cb3e2023-03-29 11:41:06 +05302247 // Delete DHCP Session
Naveen Sampath04696f72022-06-13 15:19:14 +05302248 delDhcpSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan, vpv.DHCPv6DUID)
2249
vinokuma926cb3e2023-03-29 11:41:06 +05302250 // Delete PPPoE session
Naveen Sampath04696f72022-06-13 15:19:14 +05302251 delPppoeIaSessions(vpv.LearntMacAddr, vpv.SVlan, vpv.CVlan)
2252
vinokuma926cb3e2023-03-29 11:41:06 +05302253 // Delete Mac from MacPortMap
Naveen Sampath04696f72022-06-13 15:19:14 +05302254 va.DeleteMacInPortMap(vpv.MacAddr)
2255
vinokuma926cb3e2023-03-29 11:41:06 +05302256 // Delete VPV
Naveen Sampath04696f72022-06-13 15:19:14 +05302257 vpvsIntf, ok := va.VnetsByPort.Load(port)
2258 if !ok {
2259 return
2260 }
2261 vpvs := vpvsIntf.([]*VoltPortVnet)
2262 for i, lvpv := range vpvs {
2263 if lvpv == vpv {
2264 logger.Debugw(ctx, "Deleting VPV from port", log.Fields{"Port": vpv.Port, "SVLAN": vpv.SVlan, "CVLAN": vpv.CVlan,
2265 "UNIVLAN": vpv.UniVlan})
2266
2267 vpvs = append(vpvs[0:i], vpvs[i+1:]...)
2268
2269 vpv.DeleteInProgress = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302270 vpv.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302271
2272 va.VnetsByPort.Store(port, vpvs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302273 vpv.DelTrapFlows(cntx)
2274 vpv.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302275 va.DisassociateVpvsFromDevice(vpv.Device, vpv)
2276 vpv.PendingFlowLock.RLock()
2277 if len(vpv.PendingDeleteFlow) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302278 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302279 }
2280 if vnet := va.GetVnetByName(vpv.VnetName); vnet != nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302281 vnet.disassociatePortFromVnet(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05302282 }
2283 vpv.PendingFlowLock.RUnlock()
2284 return
2285 }
2286 }
2287}
2288
2289// RestoreVnetsFromDb to restore vnet from port
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302290func (va *VoltApplication) RestoreVnetsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302291 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302292 vnets, _ := db.GetVnets(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302293 for _, net := range vnets {
2294 b, ok := net.Value.([]byte)
2295 if !ok {
2296 logger.Warn(ctx, "The value type is not []byte")
2297 continue
2298 }
2299 var vnet VoltVnet
2300 err := json.Unmarshal(b, &vnet)
2301 if err != nil {
2302 logger.Warn(ctx, "Unmarshal of VNET failed")
2303 continue
2304 }
2305 logger.Debugw(ctx, "Retrieved VNET", log.Fields{"VNET": vnet.VnetConfig})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302306 if err := va.AddVnet(cntx, vnet.VnetConfig, &vnet.VnetOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302307 logger.Warnw(ctx, "Add Vnet Failed", log.Fields{"Config": vnet.VnetConfig, "Error": err})
2308 }
2309
2310 if vnet.DeleteInProgress {
2311 va.VnetsToDelete[vnet.Name] = true
2312 logger.Warnw(ctx, "Vnet (restored) to be deleted", log.Fields{"Vnet": vnet.Name})
2313 }
Naveen Sampath04696f72022-06-13 15:19:14 +05302314 }
2315}
2316
2317// GetServiceFromCvlan : Locate a service based on the packet received. The packet contains VLANs that
2318// are used as the key to locate the service. If more than one service is on the
2319// same port (essentially a UNI of ONU), the services must be separated by different
2320// CVLANs
2321func (va *VoltApplication) GetServiceFromCvlan(device, port string, vlans []of.VlanType, priority uint8) *VoltService {
2322 // Fetch the device first to make sure the device exists
2323 dIntf, ok := va.DevicesDisc.Load(device)
2324 if !ok {
2325 return nil
2326 }
2327 d := dIntf.(*VoltDevice)
2328
2329 // If the port is NNI port, the services dont exist on it. The svc then
2330 // must be obtained from a different context and is not included here
2331 if port == d.NniPort {
2332 return nil
2333 }
2334
vinokuma926cb3e2023-03-29 11:41:06 +05302335 // To return the matched service
Naveen Sampath04696f72022-06-13 15:19:14 +05302336 var service *VoltService
2337
2338 // This is an access port and the port should have all the associated
2339 // services which can be uniquely identified by the VLANs in the packet
2340 vnets, ok := va.VnetsByPort.Load(port)
2341
2342 if !ok {
2343 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
2344 return nil
2345 }
2346 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2347 for _, vnet := range vnets.([]*VoltPortVnet) {
2348 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2349 switch vnet.VlanControl {
2350 case ONUCVlanOLTSVlan:
2351 service = vnet.MatchesPriority(priority)
2352 if vnet.MatchesCvlan(vlans) && service != nil {
2353 return service
2354 }
2355 case ONUCVlan,
2356 None:
2357 service = vnet.MatchesPriority(priority)
2358 // In case of DHCP Flow - cvlan == VlanNone
2359 // In case of HSIA Flow - cvlan == Svlan
2360 if len(vlans) == 1 && (vlans[0] == vnet.SVlan || vlans[0] == of.VlanNone) && service != nil {
2361 return service
2362 }
2363 case OLTCVlanOLTSVlan,
2364 OLTSVlan:
2365 service = vnet.MatchesPriority(priority)
2366 if len(vlans) == 1 && vlans[0] == vnet.UniVlan && service != nil {
2367 return service
2368 }
2369 default:
2370 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2371 }
2372 }
2373 return nil
2374}
2375
2376// GetVnetFromFields : Locate a service based on the packet received. The packet contains VLANs that
2377// are used as the key to locate the service. If more than one service is on the
2378// same port (essentially a UNI of ONU), the services must be separated by different
2379// CVLANs
2380func (va *VoltApplication) GetVnetFromFields(device string, port string, vlans []of.VlanType, priority uint8) (*VoltPortVnet, *VoltService) {
2381 // Fetch the device first to make sure the device exists
2382 dIntf, ok := va.DevicesDisc.Load(device)
2383 if !ok {
2384 return nil, nil
2385 }
2386 d := dIntf.(*VoltDevice)
2387
2388 // If the port is NNI port, the services dont exist on it. The svc then
2389 // must be obtained from a different context and is not included here
2390 if port == d.NniPort {
2391 return nil, nil
2392 }
2393
2394 //To return the matched service
2395 var service *VoltService
2396
2397 // This is an access port and the port should have all the associated
2398 // services which can be uniquely identified by the VLANs in the packet
2399 if vnets, ok := va.VnetsByPort.Load(port); ok {
2400 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": vlans, "Priority": priority})
2401 for _, vnet := range vnets.([]*VoltPortVnet) {
2402 logger.Infow(ctx, "Vnet", log.Fields{"Vnet": vnet})
2403 switch vnet.VlanControl {
2404 case ONUCVlanOLTSVlan:
2405 service = vnet.MatchesPriority(priority)
2406 if vnet.MatchesCvlan(vlans) && service != nil {
2407 return vnet, service
2408 }
2409 case ONUCVlan,
2410 None:
2411 service = vnet.MatchesPriority(priority)
2412 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.SVlan && service != nil {
2413 return vnet, service
2414 }
2415 case OLTCVlanOLTSVlan,
2416 OLTSVlan:
2417 service = vnet.MatchesPriority(priority)
2418 if (len(vlans) == 1 || vnet.AllowTransparent) && vlans[0] == vnet.UniVlan && service != nil {
2419 return vnet, service
2420 }
2421 default:
2422 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vnet.VlanControl})
2423 }
2424 }
2425 }
2426 return nil, nil
2427}
2428
2429// GetVnetFromPkt : Locate a service based on the packet received. The packet contains VLANs that
2430// are used as the key to locate the service. If more than one service is on the
2431// same port (essentially a UNI of ONU), the services must be separated by different
2432// CVLANs
2433func (va *VoltApplication) GetVnetFromPkt(device string, port string, pkt gopacket.Packet) (*VoltPortVnet, *VoltService) {
2434 vlans := GetVlans(pkt)
2435 priority := GetPriority(pkt)
2436 return va.GetVnetFromFields(device, port, vlans, priority)
2437}
2438
2439// PushDevFlowForVlan to push icmpv6 flows for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302440func (va *VoltApplication) PushDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302441 logger.Infow(ctx, "PushDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2442 pushflow := func(key interface{}, value interface{}) bool {
2443 device := value.(*VoltDevice)
2444 if !isDeviceInList(device.SerialNum, vnet.DevicesList) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302445 logger.Infow(ctx, "Device not present in vnet device list", log.Fields{"Device": device.SerialNum})
Naveen Sampath04696f72022-06-13 15:19:14 +05302446 return true
2447 }
2448 if device.State != controller.DeviceStateUP {
2449 logger.Errorw(ctx, "Push Dev Flows Failed - Device state DOWN", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan, "device": device})
2450 return true
2451 }
2452 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2453 logger.Errorw(ctx, "Push Dev Flows Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2454 return true
2455 }
2456
2457 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2458 vnetList := vnetListIntf.(*util.ConcurrentMap)
2459 vnetList.Set(vnet.Name, true)
2460 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2461 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()})
2462 return true
2463 }
2464 logger.Debugw(ctx, "Configuring Dev Flows Group for device ", log.Fields{"Device": device})
2465 err := ProcessIcmpv6McGroup(device.Name, false)
2466 if err != nil {
2467 logger.Warnw(ctx, "Configuring Dev Flows Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2468 return true
2469 }
2470 if portID, err := va.GetPortID(device.NniPort); err == nil {
2471 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2472 logger.Warnw(ctx, "Skipping Dev Flow Configuration - Port Down", log.Fields{"Device": device})
2473 return true
2474 }
2475
vinokuma926cb3e2023-03-29 11:41:06 +05302476 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302477 flow := BuildICMPv6Flow(portID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302478 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302479 if err != nil {
2480 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2481 return true
2482 }
2483 logger.Infow(ctx, "ICMPv6 Flow Added to Queue", log.Fields{"flow": flow})
2484
2485 // Pushing ARP Flow
2486 flow = BuildDSArpFlow(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 ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2490 return true
2491 }
2492 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2493
2494 vnetList := util.NewConcurrentMap()
2495 vnetList.Set(vnet.Name, true)
2496 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2497 }
2498 return true
2499 }
2500 va.DevicesDisc.Range(pushflow)
2501}
2502
2503// PushDevFlowForDevice to push icmpv6 flows for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302504func (va *VoltApplication) PushDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302505 logger.Infow(ctx, "PushDevFlowForDevice", log.Fields{"device": device})
2506
2507 logger.Debugw(ctx, "Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2508 err := ProcessIcmpv6McGroup(device.Name, false)
2509 if err != nil {
2510 logger.Warnw(ctx, "Configuring ICMPv6 Group for device failed ", log.Fields{"Device": device.Name, "err": err})
2511 return
2512 }
2513 pushicmpv6 := func(key, value interface{}) bool {
2514 vnet := value.(*VoltVnet)
2515 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2516 vnetList := vnetListIntf.(*util.ConcurrentMap)
2517 vnetList.Set(vnet.Name, true)
2518 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2519 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()})
2520 return true
2521 }
2522 nniPortID, err := va.GetPortID(device.NniPort)
2523 if err != nil {
2524 logger.Errorw(ctx, "Push ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2525 }
2526 if applied, ok := device.VlanPortStatus.Load(uint16(vnet.SVlan)); !ok || !applied.(bool) {
2527 logger.Warnw(ctx, "Push ICMPv6 Failed - Vlan not enabled yet", log.Fields{"Port": device.NniPort, "Vlan": vnet.SVlan})
2528 return true
2529 }
2530 flow := BuildICMPv6Flow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302531 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302532 if err != nil {
2533 logger.Warnw(ctx, "Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2534 return true
2535 }
2536 logger.Infow(ctx, "ICMP Flow Added to Queue", log.Fields{"flow": flow})
2537
2538 flow = BuildDSArpFlow(nniPortID, vnet)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302539 err = cntlr.GetController().AddFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302540 if err != nil {
2541 logger.Warnw(ctx, "Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2542 return true
2543 }
2544 logger.Infow(ctx, "ARP Flow Added to Queue", log.Fields{"flow": flow})
2545
2546 vnetList := util.NewConcurrentMap()
2547 vnetList.Set(vnet.Name, true)
2548 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2549 return true
2550 }
2551 va.VnetsByName.Range(pushicmpv6)
2552}
2553
2554// DeleteDevFlowForVlan to delete icmpv6 flow for vlan
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302555func (va *VoltApplication) DeleteDevFlowForVlan(cntx context.Context, vnet *VoltVnet) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302556 logger.Infow(ctx, "DeleteDevFlowForVlan", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2557 delflows := func(key interface{}, value interface{}) bool {
2558 device := value.(*VoltDevice)
2559
2560 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2561 vnetList := vnetListIntf.(*util.ConcurrentMap)
2562 vnetList.Remove(vnet.Name)
2563 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2564 if vnetList.Length() != 0 {
2565 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()})
2566 return true
2567 }
2568 }
2569 if portID, err := va.GetPortID(device.NniPort); err == nil {
2570 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2571 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2572 return true
2573 }
vinokuma926cb3e2023-03-29 11:41:06 +05302574 // Pushing ICMPv6 Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302575 flow := BuildICMPv6Flow(portID, vnet)
2576 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302577 err := vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302578 if err != nil {
2579 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2580 return true
2581 }
2582 logger.Infow(ctx, "ICMPv6 Flow Delete Added to Queue", log.Fields{"flow": flow})
2583
vinokuma926cb3e2023-03-29 11:41:06 +05302584 // Pushing ARP Flow
Naveen Sampath04696f72022-06-13 15:19:14 +05302585 flow = BuildDSArpFlow(portID, vnet)
2586 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302587 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302588 if err != nil {
2589 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2590 return true
2591 }
2592 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2593
2594 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2595 }
2596 return true
2597 }
2598 va.DevicesDisc.Range(delflows)
2599}
2600
2601// DeleteDevFlowForDevice to delete icmpv6 flow for device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302602func (va *VoltApplication) DeleteDevFlowForDevice(cntx context.Context, device *VoltDevice) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302603 logger.Infow(ctx, "DeleteDevFlowForDevice", log.Fields{"Device": device})
2604 delicmpv6 := func(key, value interface{}) bool {
2605 vnet := value.(*VoltVnet)
2606 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2607 vnetList := vnetListIntf.(*util.ConcurrentMap)
2608 vnetList.Remove(vnet.Name)
2609 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2610 if vnetList.Length() != 0 {
2611 logger.Warnw(ctx, "Similar VNet associated to diff service. Not removing ICMPv6 flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan, "vnetList-len": vnetList.Length()})
2612 return true
2613 }
2614 } else {
2615 logger.Warnw(ctx, "ICMPv6 Flow map entry not found for Vnet", log.Fields{"Vnet": vnet.VnetConfig})
2616 return true
2617 }
2618 nniPortID, err := va.GetPortID(device.NniPort)
2619 if err != nil {
2620 logger.Errorw(ctx, "Delete ICMPv6 Failed - Failed to get NNI Port Id", log.Fields{"Port": device.NniPort, "Reason": err.Error})
2621 }
2622 flow := BuildICMPv6Flow(nniPortID, vnet)
2623 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302624 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302625 if err != nil {
2626 logger.Warnw(ctx, "De-Configuring ICMPv6 Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2627 return true
2628 }
2629
2630 flow = BuildDSArpFlow(nniPortID, vnet)
2631 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302632 err = vnet.RemoveFlows(cntx, device, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302633 if err != nil {
2634 logger.Warnw(ctx, "De-Configuring ARP Flow for device failed ", log.Fields{"Device": device.Name, "err": err})
2635 return true
2636 }
2637
2638 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2639 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2640 return true
2641 }
2642 va.VnetsByName.Range(delicmpv6)
2643 logger.Debugw(ctx, "De-Configuring ICMPv6 Group for device ", log.Fields{"Device": device.Name})
2644 err := ProcessIcmpv6McGroup(device.Name, true)
2645 if err != nil {
2646 logger.Warnw(ctx, "De-Configuring ICMPv6 Group on device failed ", log.Fields{"Device": device.Name, "err": err})
2647 return
2648 }
2649}
2650
2651// DeleteDevFlowForVlanFromDevice to delete icmpv6 flow for vlan from device
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302652func (va *VoltApplication) DeleteDevFlowForVlanFromDevice(cntx context.Context, vnet *VoltVnet, deviceSerialNum string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302653 logger.Infow(ctx, "DeleteDevFlowForVlanFromDevice", log.Fields{"Device-serialNum": deviceSerialNum, "SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
2654 delflows := func(key interface{}, value interface{}) bool {
2655 device := value.(*VoltDevice)
2656 if device.SerialNum != deviceSerialNum {
2657 return true
2658 }
2659 if vnetListIntf, ok := device.ConfiguredVlanForDeviceFlows.Get(VnetKey(vnet.SVlan, vnet.CVlan, 0)); ok {
2660 vnetList := vnetListIntf.(*util.ConcurrentMap)
2661 vnetList.Remove(vnet.Name)
2662 device.ConfiguredVlanForDeviceFlows.Set(VnetKey(vnet.SVlan, vnet.CVlan, 0), vnetList)
2663 if vnetList.Length() != 0 {
2664 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()})
2665 return true
2666 }
2667 } else if !vgcRebooted && len(vnet.DevicesList) != 0 {
2668 // Return only in-case of non-reboot/delete scenario. Else, the flows need to be force removed
2669 // DeviceList check is there to avoid dangling flow in-case of pod restart during service de-activation.
2670 // The step will be as follow:
2671 // 1. Deact Service
2672 // 2. Pod Reboot
2673 // 3. Pending Delete Service triggered
2674 // 4. Del Service Ind followed by DelVnet req from NB
2675 // 5. If Vlan status response is awaited, the ConfiguredVlanForDeviceFlows cache will not have flow info
2676 // hence the flow will not be cleared
2677 logger.Warnw(ctx, "Dev Flow map entry not found for Vnet", log.Fields{"PodReboot": vgcRebooted, "VnetDeleteInProgress": vnet.DeleteInProgress})
2678 return true
2679 }
2680 if portID, err := va.GetPortID(device.NniPort); err == nil {
2681 if state, _ := cntlr.GetController().GetPortState(device.Name, device.NniPort); state != cntlr.PortStateUp {
2682 logger.Warnw(ctx, "Skipping ICMPv6 Flow Deletion - Port Down", log.Fields{"Device": device})
2683 return false
2684 }
2685 flow := BuildICMPv6Flow(portID, vnet)
2686 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302687 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302688 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2689 }
2690 logger.Infow(ctx, "ICMP Flow Delete Added to Queue", log.Fields{"flow": flow})
2691
2692 flow = BuildDSArpFlow(portID, vnet)
2693 flow.ForceAction = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302694 if err := vnet.RemoveFlows(cntx, device, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05302695 logger.Warnw(ctx, "Delete Flow Failed", log.Fields{"Device": device, "Flow": flow, "Error": err})
2696 }
2697 logger.Infow(ctx, "ARP Flow Delete Added to Queue", log.Fields{"flow": flow})
2698 device.ConfiguredVlanForDeviceFlows.Remove(VnetKey(vnet.SVlan, vnet.CVlan, 0))
2699 }
2700 return false
2701 }
2702 va.DevicesDisc.Range(delflows)
2703}
2704
2705// BuildICMPv6Flow to Build DS flow for ICMPv6
2706func BuildICMPv6Flow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302707 logger.Infow(ctx, "Building ICMPv6 MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302708 flow := &of.VoltFlow{}
2709 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2710 subFlow := of.NewVoltSubFlow()
2711
2712 subFlow.SetICMPv6Match()
2713 subFlow.SetMatchVlan(vnet.SVlan)
2714 subFlow.SetInPort(inport)
2715 subFlow.SetPopVlan()
2716 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2717 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.IgmpFlowMask | of.DsFlowMask
2718 subFlow.Priority = of.McFlowPriority
2719 var metadata uint64
2720 if vnet.VlanControl == None {
2721 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2722 } else {
2723 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2724 }
2725 subFlow.SetTableMetadata(metadata)
2726 metadata = uint64(vnet.setPbitRemarking())
2727
2728 logger.Infow(ctx, "ICMPv6 Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2729 subFlow.SetWriteMetadata(metadata)
2730 flow.SubFlows[subFlow.Cookie] = subFlow
2731 return flow
2732}
2733
vinokuma926cb3e2023-03-29 11:41:06 +05302734// BuildDSArpFlow Builds DS flow for ARP
Naveen Sampath04696f72022-06-13 15:19:14 +05302735func BuildDSArpFlow(inport uint32, vnet *VoltVnet) *of.VoltFlow {
Tinoj Joseph1d108322022-07-13 10:07:39 +05302736 logger.Infow(ctx, "Building ARP MC Flow", log.Fields{"SVlan": vnet.SVlan, "CVlan": vnet.CVlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05302737
2738 flow := &of.VoltFlow{}
2739 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2740 subFlow := of.NewVoltSubFlow()
2741
2742 BcastMAC, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
2743 subFlow.SetArpMatch()
2744 subFlow.SetMatchDstMac(BcastMAC)
2745 subFlow.SetMatchVlan(vnet.SVlan)
2746 subFlow.SetInPort(inport)
2747 subFlow.SetPopVlan()
2748 subFlow.SetOutGroup(ICMPv6ArpGroupID)
2749
2750 subFlow.Cookie = uint64(vnet.CVlan)<<48 | uint64(vnet.SVlan)<<32 | of.DsArpFlowMask | of.DsFlowMask
2751 subFlow.Priority = of.McFlowPriority
2752
2753 var metadata uint64
2754 if vnet.VlanControl == None {
2755 metadata = uint64(ONUCVlan)<<32 | uint64(vnet.CVlan)
2756 } else {
2757 metadata = uint64(vnet.VlanControl)<<32 | uint64(vnet.CVlan)
2758 }
2759 subFlow.SetTableMetadata(metadata)
2760 metadata = uint64(vnet.setPbitRemarking())
2761 subFlow.SetWriteMetadata(metadata)
2762
2763 flow.SubFlows[subFlow.Cookie] = subFlow
2764 logger.Infow(ctx, "ARP Pbit Remarking", log.Fields{"RemarkPbit": metadata})
2765 return flow
2766}
2767
2768// setPbitRemarking to set Pbit remarking
2769func (vv *VoltVnet) setPbitRemarking() uint32 {
Naveen Sampath04696f72022-06-13 15:19:14 +05302770 // Remarkable
2771 // Remarked Pbit Pbit
2772 // |-----------------------------| |------|
2773 // |7| |6| |5| |4| |3| |2| |1| |0| 76543210
2774 // 000 000 000 000 000 000 000 000 00000000
2775
2776 // Eg:
2777 // For 6:3 & 7:1
2778 // 001 011 000 000 000 000 000 000 11000000
2779
2780 var remarkable uint8
2781 var remarked uint32
2782 for refPbit, remarkPbit := range vv.CtrlPktPbitRemark {
2783 remarkable = remarkable | 1<<refPbit
2784 remarked = remarked | uint32(remarkPbit)<<(refPbit*3)
2785 }
2786 return remarked<<8 | uint32(remarkable)
2787}
2788
2789// ProcessIcmpv6McGroup to add icmpv6 multicast group
2790func ProcessIcmpv6McGroup(device string, delete bool) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302791 logger.Info(ctx, "Creating ICMPv6 MC Group")
2792 va := GetApplication()
2793 vd := va.GetDevice(device)
2794 group := &of.Group{}
2795 group.GroupID = ICMPv6ArpGroupID
2796 group.Device = device
2797 if delete {
2798 if !vd.icmpv6GroupAdded {
2799 logger.Info(ctx, "ICMPv6 MC Group is already deleted. Ignoring icmpv6 group Delete")
2800 return nil //TODO
2801 }
2802 vd.icmpv6GroupAdded = false
2803 group.Command = of.GroupCommandDel
2804 group.ForceAction = true
2805 } else {
2806 if vd.icmpv6GroupAdded {
2807 logger.Info(ctx, "ICMPv6 MC Group is already added. Ignoring icmpv6 group Add")
2808 return nil //TODO
2809 }
2810 vd.icmpv6GroupAdded = true
2811 group.Command = of.GroupCommandAdd
2812 receivers := GetApplication().GetIcmpv6Receivers(device)
2813 group.Buckets = append(group.Buckets, receivers...)
2814 }
2815 logger.Infow(ctx, "ICMPv6 MC Group Action", log.Fields{"Device": device, "Delete": delete})
2816 port, _ := GetApplication().GetNniPort(device)
2817 err := cntlr.GetController().GroupUpdate(port, device, group)
2818 return err
2819}
2820
vinokuma926cb3e2023-03-29 11:41:06 +05302821// isVlanMatching - checks is vlans matches with vpv based on vlan control
Naveen Sampath04696f72022-06-13 15:19:14 +05302822func (vpv *VoltPortVnet) isVlanMatching(cvlan of.VlanType, svlan of.VlanType) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05302823 switch vpv.VlanControl {
2824 case ONUCVlanOLTSVlan,
2825 OLTCVlanOLTSVlan:
2826 if vpv.SVlan == svlan && vpv.CVlan == cvlan {
2827 return true
2828 }
2829 case ONUCVlan,
2830 OLTSVlan,
2831 None:
2832 if vpv.SVlan == svlan {
2833 return true
2834 }
2835 default:
2836 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
2837 }
2838 return false
2839}
2840
vinokuma926cb3e2023-03-29 11:41:06 +05302841// PushFlows - Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302842func (vpv *VoltPortVnet) PushFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302843 for cookie := range flow.SubFlows {
2844 cookie := strconv.FormatUint(cookie, 10)
2845 fe := &FlowEvent{
2846 eType: EventTypeControlFlowAdded,
2847 cookie: cookie,
2848 eventData: vpv,
2849 }
2850 device.RegisterFlowAddEvent(cookie, fe)
2851 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302852 return cntlr.GetController().AddFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302853}
2854
vinokuma926cb3e2023-03-29 11:41:06 +05302855// FlowInstallFailure - Process flow failure indication and triggers HSIA failure for all associated services
Naveen Sampath04696f72022-06-13 15:19:14 +05302856func (vpv *VoltPortVnet) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302857 sendFlowFailureInd := func(key, value interface{}) bool {
2858 //svc := value.(*VoltService)
2859 //TODO-COMM: svc.triggerServiceFailureInd(errorCode, errReason)
2860 return true
2861 }
2862 logger.Errorw(ctx, "Control Flow Add Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2863 vpv.services.Range(sendFlowFailureInd)
2864}
2865
vinokuma926cb3e2023-03-29 11:41:06 +05302866// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302867func (vpv *VoltPortVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302868 vpv.PendingFlowLock.Lock()
2869 defer vpv.PendingFlowLock.Unlock()
2870
2871 for cookie := range flow.SubFlows {
2872 cookie := strconv.FormatUint(cookie, 10)
2873 fe := &FlowEvent{
2874 eType: EventTypeControlFlowRemoved,
2875 device: device.Name,
2876 cookie: cookie,
2877 eventData: vpv,
2878 }
2879 device.RegisterFlowDelEvent(cookie, fe)
2880 vpv.PendingDeleteFlow[cookie] = true
2881 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302882 return cntlr.GetController().DelFlows(cntx, vpv.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302883}
2884
vinokuma926cb3e2023-03-29 11:41:06 +05302885// CheckAndDeleteVpv - remove VPV from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302886func (vpv *VoltPortVnet) CheckAndDeleteVpv(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302887 vpv.PendingFlowLock.RLock()
2888 defer vpv.PendingFlowLock.RUnlock()
2889 if !vpv.DeleteInProgress {
2890 return
2891 }
2892 if len(vpv.PendingDeleteFlow) == 0 && !vpv.FlowsApplied {
2893 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 +05302894 vpv.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302895 logger.Infow(ctx, "Deleted VPV from DB/Cache successfully", log.Fields{"VPV Port": vpv.Port, "Device": vpv.Device, "Vnet": vpv.VnetName})
2896 }
2897}
2898
vinokuma926cb3e2023-03-29 11:41:06 +05302899// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302900func (vpv *VoltPortVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302901 vpv.PendingFlowLock.Lock()
2902 logger.Infow(ctx, "VPV Flow Remove Success Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "Device": device})
2903
2904 delete(vpv.PendingDeleteFlow, cookie)
2905 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302906 vpv.CheckAndDeleteVpv(cntx)
2907 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302908}
2909
vinokuma926cb3e2023-03-29 11:41:06 +05302910// FlowRemoveFailure - Process flow failure indication and triggers Del HSIA failure for all associated services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302911func (vpv *VoltPortVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302912 vpv.PendingFlowLock.Lock()
2913
2914 logger.Errorw(ctx, "VPV Flow Remove Failure Notification", log.Fields{"Port": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
2915
2916 sendFlowFailureInd := func(key, value interface{}) bool {
2917 svc := value.(*VoltService)
2918 svc.triggerServiceFailureInd(errorCode, errReason)
2919 return true
2920 }
2921 logger.Errorw(ctx, "Control Flow Del Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
2922 vpv.services.Range(sendFlowFailureInd)
2923
2924 if vpv.DeleteInProgress {
2925 delete(vpv.PendingDeleteFlow, cookie)
2926 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302927 vpv.CheckAndDeleteVpv(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302928 } else {
2929 vpv.PendingFlowLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302930 vpv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302931 }
2932}
2933
vinokuma926cb3e2023-03-29 11:41:06 +05302934// RemoveFlows - Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302935func (vv *VoltVnet) RemoveFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05302936 vv.VnetLock.Lock()
2937 defer vv.VnetLock.Unlock()
2938
2939 var flowMap map[string]bool
2940 var ok bool
2941
2942 for cookie := range flow.SubFlows {
2943 cookie := strconv.FormatUint(cookie, 10)
2944 fe := &FlowEvent{
2945 eType: EventTypeDeviceFlowRemoved,
2946 device: device.Name,
2947 cookie: cookie,
2948 eventData: vv,
2949 }
2950 device.RegisterFlowDelEvent(cookie, fe)
2951 if flowMap, ok = vv.PendingDeleteFlow[device.Name]; !ok {
2952 flowMap = make(map[string]bool)
2953 }
2954 flowMap[cookie] = true
2955 vv.PendingDeleteFlow[device.Name] = flowMap
2956 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302957 vv.WriteToDb(cntx)
2958 return cntlr.GetController().DelFlows(cntx, device.NniPort, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05302959}
2960
vinokuma926cb3e2023-03-29 11:41:06 +05302961// CheckAndDeleteVnet - remove Vnet from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302962func (vv *VoltVnet) CheckAndDeleteVnet(cntx context.Context, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302963 if !vv.DeleteInProgress {
2964 return
2965 }
2966 vv.VnetPortLock.RLock()
2967 if len(vv.PendingDeleteFlow[device]) == 0 && !vv.isAssociatedPortsPresent() {
2968 logger.Warnw(ctx, "Deleting Vnet : All flows removed", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "Device": device})
2969 GetApplication().deleteVnetConfig(vv)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302970 _ = db.DelVnet(cntx, vv.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +05302971 logger.Infow(ctx, "Deleted Vnet from DB/Cache successfully", log.Fields{"Device": device, "Vnet": vv.Name})
2972 } else {
2973 logger.Warnw(ctx, "Skipping Del Vnet", log.Fields{"Name": vv.Name, "AssociatedPorts": vv.AssociatedPorts, "PendingDelFlows": vv.PendingDeleteFlow[device]})
2974 }
2975 vv.VnetPortLock.RUnlock()
2976}
2977
vinokuma926cb3e2023-03-29 11:41:06 +05302978// FlowRemoveSuccess - Process flow success indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302979func (vv *VoltVnet) FlowRemoveSuccess(cntx context.Context, cookie string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05302980 vv.VnetLock.Lock()
2981 defer vv.VnetLock.Unlock()
2982
2983 logger.Infow(ctx, "Vnet Flow Remove Success Notification", log.Fields{"VnetProfile": vv.Name, "Cookie": cookie, "Device": device})
2984
2985 if _, ok := vv.PendingDeleteFlow[device]; ok {
2986 delete(vv.PendingDeleteFlow[device], cookie)
2987 }
2988
2989 //Check and update success for pending disable request
2990 if d := GetApplication().GetDevice(device); d != nil {
2991 _, present := d.ConfiguredVlanForDeviceFlows.Get(VnetKey(vv.SVlan, vv.CVlan, 0))
2992 if !present && len(vv.PendingDeleteFlow[device]) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302993 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05302994 }
2995 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302996 vv.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05302997}
2998
vinokuma926cb3e2023-03-29 11:41:06 +05302999// FlowRemoveFailure - Process flow failure indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303000func (vv *VoltVnet) FlowRemoveFailure(cntx context.Context, cookie string, device string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05303001 vv.VnetLock.Lock()
3002 defer vv.VnetLock.Unlock()
3003
3004 if flowMap, ok := vv.PendingDeleteFlow[device]; ok {
3005 if _, ok := flowMap[cookie]; ok {
3006 logger.Errorw(ctx, "Device Flow Remove Failure Notification", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason, "Device": device})
3007
3008 if vv.DeleteInProgress {
3009 delete(vv.PendingDeleteFlow[device], cookie)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303010 vv.CheckAndDeleteVnet(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05303011 }
3012 return
3013 }
3014 }
3015 logger.Errorw(ctx, "Device Flow Remove Failure Notification for Unknown cookie", log.Fields{"Vnet": vv.Name, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3016}
3017
vinokuma926cb3e2023-03-29 11:41:06 +05303018// IgmpFlowInstallFailure - Process flow failure indication and triggers HSIA failure for Igmp enabled services
Naveen Sampath04696f72022-06-13 15:19:14 +05303019func (vpv *VoltPortVnet) IgmpFlowInstallFailure(cookie string, errorCode uint32, errReason string) {
vinokuma926cb3e2023-03-29 11:41:06 +05303020 // Note: Current implementation supports only for single service with Igmp Enabled for a subscriber
3021 // When multiple Igmp-suported service enabled, comment "return false"
Naveen Sampath04696f72022-06-13 15:19:14 +05303022
3023 sendFlowFailureInd := func(key, value interface{}) bool {
3024 svc := value.(*VoltService)
3025 if svc.IgmpEnabled {
3026 svc.triggerServiceFailureInd(errorCode, errReason)
3027 return false
3028 }
3029 return true
3030 }
3031 logger.Errorw(ctx, "US IGMP Flow Failure Notification", log.Fields{"uniPort": vpv.Port, "Cookie": cookie, "ErrorCode": errorCode, "ErrorReason": errReason})
3032 vpv.services.Range(sendFlowFailureInd)
3033}
3034
3035// GetMatchingMcastService to get matching multicast service
3036func (va *VoltApplication) GetMatchingMcastService(port string, device string, cvlan of.VlanType) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +05303037 var service *VoltService
3038 dIntf, ok := va.DevicesDisc.Load(device)
3039 if !ok {
3040 return nil
3041 }
3042 d := dIntf.(*VoltDevice)
3043
3044 // If the port is NNI port, the services dont exist on it. The svc then
3045 // must be obtained from a different context and is not included here
3046 if port == d.NniPort {
3047 return nil
3048 }
3049
3050 // This is an access port and the port should have all the associated
3051 // services which can be uniquely identified by the VLANs in the packet
3052 vnets, ok := va.VnetsByPort.Load(port)
3053
3054 if !ok {
3055 logger.Debugw(ctx, "No Vnets for port", log.Fields{"Port": port})
3056 return nil
3057 }
3058 logger.Debugw(ctx, "Matching for VLANs", log.Fields{"VLANs": cvlan})
3059 getMcastService := func(key, value interface{}) bool {
3060 srv := value.(*VoltService)
3061 if srv.IgmpEnabled {
3062 service = srv
3063
3064 //TODO: Current implementation supports only for single service with Igmp Enabled
3065 //FIX-ME: When multiple service suports Igmp, update of logic required
3066 return false
3067 }
3068 return true
3069 }
3070
3071 for _, vpv := range vnets.([]*VoltPortVnet) {
3072 if vpv.CVlan == cvlan {
3073 vpv.services.Range(getMcastService)
3074 if service != nil {
3075 break
3076 }
3077 }
3078 }
3079 return service
3080}
3081
vinokuma926cb3e2023-03-29 11:41:06 +05303082// TriggerAssociatedFlowDelete - Re-trigger delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303083func (vv *VoltVnet) TriggerAssociatedFlowDelete(cntx context.Context, device string) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +05303084 vv.VnetLock.Lock()
3085 cookieList := []uint64{}
3086 flowMap := vv.PendingDeleteFlow[device]
3087
3088 for cookie := range flowMap {
3089 cookieList = append(cookieList, convertToUInt64(cookie))
3090 }
3091 vv.VnetLock.Unlock()
3092
3093 if len(cookieList) == 0 {
3094 return false
3095 }
3096
3097 for _, cookie := range cookieList {
3098 if vd := GetApplication().GetDevice(device); vd != nil {
3099 flow := &of.VoltFlow{}
3100 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
3101 subFlow := of.NewVoltSubFlow()
3102 subFlow.Cookie = cookie
3103 flow.SubFlows[cookie] = subFlow
3104 logger.Infow(ctx, "Retriggering Vnet Delete Flow", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05303105 if err := vv.RemoveFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05303106 logger.Warnw(ctx, "Vnet Delete Flow Failed", log.Fields{"Device": device, "Vnet": vv.Name, "Cookie": cookie, "Error": err})
3107 }
3108 }
3109 }
3110 return true
3111}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303112
vinokuma926cb3e2023-03-29 11:41:06 +05303113// JSONMarshal wrapper function for json Marshal VoltVnet
3114func (vv *VoltVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303115 return json.Marshal(VoltVnet{
3116 VnetConfig: vv.VnetConfig,
Akash Sonia8246972023-01-03 10:37:08 +05303117 Version: vv.Version,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303118 VnetOper: VnetOper{
3119 PendingDeleteFlow: vv.VnetOper.PendingDeleteFlow,
3120 DeleteInProgress: vv.VnetOper.DeleteInProgress,
3121 PendingDeviceToDelete: vv.VnetOper.PendingDeviceToDelete,
3122 },
3123 })
3124}
3125
vinokuma926cb3e2023-03-29 11:41:06 +05303126// JSONMarshal wrapper function for json Marshal VoltPortVnet
3127func (vpv *VoltPortVnet) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05303128 return json.Marshal(VoltPortVnet{
3129 Device: vpv.Device,
3130 Port: vpv.Port,
3131 PonPort: vpv.PonPort,
3132 VnetName: vpv.VnetName,
3133 SVlan: vpv.SVlan,
3134 CVlan: vpv.CVlan,
3135 UniVlan: vpv.UniVlan,
3136 SVlanTpid: vpv.SVlanTpid,
3137 DhcpRelay: vpv.DhcpRelay,
3138 ArpRelay: vpv.ArpRelay,
3139 PppoeIa: vpv.PppoeIa,
3140 MacLearning: vpv.MacLearning,
3141 DhcpStatus: vpv.DhcpStatus,
3142 DhcpExpiryTime: vpv.DhcpExpiryTime,
3143 Dhcp6ExpiryTime: vpv.Dhcp6ExpiryTime,
3144 FlowsApplied: vpv.FlowsApplied,
3145 Ipv4Addr: vpv.Ipv4Addr,
3146 Ipv6Addr: vpv.Ipv6Addr,
3147 MacAddr: vpv.MacAddr,
3148 LearntMacAddr: vpv.LearntMacAddr,
3149 CircuitID: vpv.CircuitID,
3150 RemoteID: vpv.RemoteID,
3151 IsOption82Disabled: vpv.IsOption82Disabled,
3152 RelayState: vpv.RelayState,
3153 PPPoeState: vpv.PPPoeState,
3154 RelayStatev6: vpv.RelayStatev6,
3155 IgmpEnabled: vpv.IgmpEnabled,
3156 IgmpFlowsApplied: vpv.IgmpFlowsApplied,
3157 McastService: vpv.McastService,
3158 ONTEtherTypeClassification: vpv.ONTEtherTypeClassification,
3159 VlanControl: vpv.VlanControl,
3160 MvlanProfileName: vpv.MvlanProfileName,
3161 Version: vpv.Version,
3162 McastTechProfileID: vpv.McastTechProfileID,
3163 McastPbit: vpv.McastPbit,
3164 McastUsMeterID: vpv.McastUsMeterID,
3165 AllowTransparent: vpv.AllowTransparent,
3166 SchedID: vpv.SchedID,
3167 DHCPv6DUID: vpv.DHCPv6DUID,
3168 PendingDeleteFlow: vpv.PendingDeleteFlow,
3169 DeleteInProgress: vpv.DeleteInProgress,
3170 Blocked: vpv.Blocked,
3171 DhcpPbit: vpv.DhcpPbit,
3172 })
3173}
Tinoj Josephec742f62022-09-29 19:11:10 +05303174
3175func (vpv *VoltPortVnet) IsServiceActivated(cntx context.Context) bool {
3176 isActivated := false
3177 vpv.services.Range(func(key, value interface{}) bool {
3178 svc := value.(*VoltService)
3179 if svc.IsActivated {
3180 logger.Infow(ctx, "Found activated service on the vpv", log.Fields{"Name": svc.Name})
3181 isActivated = true
3182 return false //to exit loop
3183 }
3184 return true
3185 })
3186 return isActivated
3187}