blob: e06054814976a43b7566becb652ab6e10f0e7c76 [file] [log] [blame]
Joey Armstrongaca03cf2024-04-23 09:29:52 -04001/* -----------------------------------------------------------------------
2 * Copyright 2022-2024 Open Networking Foundation Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * -----------------------------------------------------------------------
16 * SPDX-FileCopyrightText: 2022-2024 Open Networking Foundation Contributors
17 * SPDX-License-Identifier: Apache-2.0
18 * -----------------------------------------------------------------------
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053019 */
Naveen Sampath04696f72022-06-13 15:19:14 +053020
21package application
22
23import (
24 "bytes"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053025 "context"
Naveen Sampath04696f72022-06-13 15:19:14 +053026 "encoding/json"
27 "errors"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +053028 "fmt"
Naveen Sampath04696f72022-06-13 15:19:14 +053029 "net"
30 "reflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053031 "sort"
32 "strconv"
33 "strings"
34 "sync"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053035 infraerrorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053036
37 "github.com/google/gopacket/layers"
38
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053039 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053040 "voltha-go-controller/internal/pkg/controller"
41 cntlr "voltha-go-controller/internal/pkg/controller"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053042 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053043 "voltha-go-controller/internal/pkg/of"
44 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053045 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053046)
47
48const (
49 // DSLAttrEnabled constant
50 DSLAttrEnabled string = "ENABLED"
Tinoj Josephec742f62022-09-29 19:11:10 +053051 // DeviceAny constant
52 DeviceAny string = "DEVICE-ANY"
Akash Soni634d9bf2023-07-10 12:11:10 +053053
54 ALL_FLOWS_PROVISIONED string = "ALL_FLOWS_PROVISIONED"
55
56 NO_FLOWS_PROVISIONED string = "NO_FLOWS_PROVISIONED"
57
58 FLOWS_PROVISIONED_PARTIALLY string = "FLOWS_PROVISIONED_PARTIALLY"
59
60 SUBSCRIBER_DISABLED_IN_CONTROLLER string = "DISABLED_IN_CONTROLLER"
61
62 SUBSCRIBER_NOT_IN_CONTROLLER string = "NOT_IN_CONTROLLER"
63
64 ONT_FLOWS_PROVISION_STATE_UNUSED string = "ONT_FLOWS_PROVISION_STATE_UNUSED"
Naveen Sampath04696f72022-06-13 15:19:14 +053065)
66
67// VoltServiceCfg structure
68// Name - Uniquely identifies a service across the entire application
69// UniVlan - The VLAN of the packets entering the UNI of ONU
70// CVlan - The VLAN to transalate to/from on the PON link
71// SVlan - The outer VLAN to be used on the NNI of OLT.
vinokuma926cb3e2023-03-29 11:41:06 +053072// - In general, 4096 is used as NO VLAN for all the above
73// SVlanTpid - SVlan Tag Protocol Identifier
Naveen Sampath04696f72022-06-13 15:19:14 +053074// Pbits - Each bit of uint8 represents one p-bit. MSB is pbit 7
75// DhcpRelay - Whether it is turned on/off
76// CircuitId - The circuit id to be used with DHCP relay. Unused otherwise
77// RemoveId - Same as above
78// Port - The access port for the service. Each service has a single access
vinokuma926cb3e2023-03-29 11:41:06 +053079// port. The converse is not always true
Naveen Sampath04696f72022-06-13 15:19:14 +053080// MacLearning - If MAC learning is turned on, the MAC address learned from the
vinokuma926cb3e2023-03-29 11:41:06 +053081// the service activation is used in programming flows
Naveen Sampath04696f72022-06-13 15:19:14 +053082// MacAddress - The MAC hardware address learnt on the UNI interface
83// MacAddresses - Not yet implemented. To be used to learn more MAC addresses
84type VoltServiceCfg struct {
Akash Sonief452f12024-12-12 18:20:28 +053085 DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
vinokuma926cb3e2023-03-29 11:41:06 +053086 Name string
Naveen Sampath04696f72022-06-13 15:19:14 +053087 CircuitID string
Naveen Sampath04696f72022-06-13 15:19:14 +053088 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +053089 UsMeterProfile string
90 DsMeterProfile string
91 AggDsMeterProfile string
92 VnetID string
93 MvlanProfileName string
94 RemoteIDType string
Naveen Sampath04696f72022-06-13 15:19:14 +053095 DataRateAttr string
vinokuma926cb3e2023-03-29 11:41:06 +053096 ServiceType string
vinokuma926cb3e2023-03-29 11:41:06 +053097 MacAddr net.HardwareAddr
Akash Sonief452f12024-12-12 18:20:28 +053098 RemoteID []byte
99 Pbits []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530100 Trigger ServiceTrigger
101 MacLearning MacLearningType
Akash Sonief452f12024-12-12 18:20:28 +0530102 ONTEtherTypeClassification int
103 SchedID int
vinokuma926cb3e2023-03-29 11:41:06 +0530104 PonPort uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530105 MinDataRateUs uint32
106 MinDataRateDs uint32
107 MaxDataRateUs uint32
108 MaxDataRateDs uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530109 SVlanTpid layers.EthernetType
Akash Sonief452f12024-12-12 18:20:28 +0530110 TechProfileID uint16
vinokuma926cb3e2023-03-29 11:41:06 +0530111 UniVlan of.VlanType
112 CVlan of.VlanType
113 SVlan of.VlanType
114 UsPonCTagPriority of.PbitType
115 UsPonSTagPriority of.PbitType
116 DsPonSTagPriority of.PbitType
117 DsPonCTagPriority of.PbitType
Akash Sonief452f12024-12-12 18:20:28 +0530118 ServiceDeactivateReason SvcDeactivateReason // Mentions why the service was deactivated
vinokuma926cb3e2023-03-29 11:41:06 +0530119 VlanControl VlanControl
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530120 IsOption82Enabled bool
vinokuma926cb3e2023-03-29 11:41:06 +0530121 IgmpEnabled bool
122 McastService bool
123 AllowTransparent bool
124 EnableMulticastKPI bool
Tinoj Josephec742f62022-09-29 19:11:10 +0530125 IsActivated bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530126}
127
128// VoltServiceOper structure
129type VoltServiceOper struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530130 Metadata interface{}
131 PendingFlows map[string]bool
132 AssociatedFlows map[string]bool
133 BwAvailInfo string
Naveen Sampath04696f72022-06-13 15:19:14 +0530134 //MacLearning bool
135 //MacAddr net.HardwareAddr
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530136 Device string
137 Ipv4Addr net.IP
138 Ipv6Addr net.IP
139 ServiceLock sync.RWMutex `json:"-"`
140 UsMeterID uint32
141 DsMeterID uint32
142 AggDsMeterID uint32
143 UpdateInProgress bool
144 DeleteInProgress bool
145 DeactivateInProgress bool
146 ForceDelete bool
vinokuma926cb3e2023-03-29 11:41:06 +0530147 // Multiservice-Fix
Naveen Sampath04696f72022-06-13 15:19:14 +0530148 UsHSIAFlowsApplied bool
149 DsHSIAFlowsApplied bool
150 UsDhcpFlowsApplied bool
151 DsDhcpFlowsApplied bool
152 IgmpFlowsApplied bool
153 Icmpv6FlowsApplied bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530154}
155
156// VoltService structure
157type VoltService struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530158 VoltServiceOper
159 Version string
vinokuma926cb3e2023-03-29 11:41:06 +0530160 VoltServiceCfg
Naveen Sampath04696f72022-06-13 15:19:14 +0530161}
162
vinokuma926cb3e2023-03-29 11:41:06 +0530163// ServiceTrigger - Service activation trigger
Naveen Sampath04696f72022-06-13 15:19:14 +0530164type ServiceTrigger int
165
166const (
vinokuma926cb3e2023-03-29 11:41:06 +0530167 // NBActivate - Service added due to NB Action
Naveen Sampath04696f72022-06-13 15:19:14 +0530168 NBActivate ServiceTrigger = 0
vinokuma926cb3e2023-03-29 11:41:06 +0530169 // ServiceVlanUpdate - Service added due to Svlan Update
Naveen Sampath04696f72022-06-13 15:19:14 +0530170 ServiceVlanUpdate ServiceTrigger = 1
171)
172
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530173// SvcDeactivateReason - Reason for service deactivation
174type SvcDeactivateReason uint8
175
176const (
177 // Service deactivated reason - none
178 SvcDeacRsn_None SvcDeactivateReason = 0
179 // Service deactivate reason - NB
180 SvcDeacRsn_NB SvcDeactivateReason = 1
181 // Service deactivate reason - Controller
182 SvcDeacRsn_Controller SvcDeactivateReason = 2
183)
184
Naveen Sampath04696f72022-06-13 15:19:14 +0530185// AppMutexes structure
186type AppMutexes struct {
187 ServiceDataMutex sync.Mutex `json:"-"`
188 VnetMutex sync.Mutex `json:"-"`
189}
190
vinokuma926cb3e2023-03-29 11:41:06 +0530191// MigrateServiceMetadata - migrate services request metadata
Naveen Sampath04696f72022-06-13 15:19:14 +0530192type MigrateServiceMetadata struct {
193 NewVnetID string
194 RequestID string
195}
196
197// AppMutex variable
198var AppMutex AppMutexes
199
200// NewVoltService for constructor for volt service
201func NewVoltService(cfg *VoltServiceCfg) *VoltService {
202 var vs VoltService
203 vs.VoltServiceCfg = *cfg
204 vs.UsHSIAFlowsApplied = false
205 vs.DsHSIAFlowsApplied = false
206 vs.DeleteInProgress = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530207 vs.DeactivateInProgress = false
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530208 vs.ServiceDeactivateReason = SvcDeacRsn_None
Naveen Sampath04696f72022-06-13 15:19:14 +0530209 //vs.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530210
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530211 vs.IsOption82Enabled = cfg.IsOption82Enabled
Naveen Sampath04696f72022-06-13 15:19:14 +0530212 vs.MacAddr = cfg.MacAddr
213 vs.Ipv4Addr = net.ParseIP("0.0.0.0")
214 vs.Ipv6Addr = net.ParseIP("::")
215 vs.PendingFlows = make(map[string]bool)
216 vs.AssociatedFlows = make(map[string]bool)
217 return &vs
218}
219
220// WriteToDb commit a service to the DB if service delete is not in-progress
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530221func (vs *VoltService) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530222 vs.ServiceLock.RLock()
223 defer vs.ServiceLock.RUnlock()
224
225 if vs.DeleteInProgress {
226 logger.Warnw(ctx, "Skipping Redis Update for Service, Service delete in progress", log.Fields{"Service": vs.Name})
227 return
228 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530229 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530230}
231
vinokuma926cb3e2023-03-29 11:41:06 +0530232// ForceWriteToDb force commit a service to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530233func (vs *VoltService) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530234 b, err := json.Marshal(vs)
235
236 if err != nil {
237 logger.Errorw(ctx, "Json Marshal Failed for Service", log.Fields{"Service": vs.Name})
238 return
239 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530240 if err1 := db.PutService(cntx, vs.Name, string(b)); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530241 logger.Errorw(ctx, "DB write oper failed for Service", log.Fields{"Service": vs.Name})
242 }
243}
244
245// isDataRateAttrPresent to check if data attribute is present
246func (vs *VoltService) isDataRateAttrPresent() bool {
247 return vs.DataRateAttr == DSLAttrEnabled
248}
249
250// DelFromDb delete a service from DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530251func (vs *VoltService) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530252 logger.Debugw(ctx, "Deleting Service from DB", log.Fields{"Name": vs.Name})
vinokuma926cb3e2023-03-29 11:41:06 +0530253 // TODO - Need to understand and delete the second call
254 // Calling twice has worked though don't know why
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530255 _ = db.DelService(cntx, vs.Name)
256 _ = db.DelService(cntx, vs.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530257}
258
259// MatchesVlans find the service that matches the VLANs. In this case it is
260// purely based on CVLAN. The CVLAN can sufficiently be used to
261// match a service
262func (vs *VoltService) MatchesVlans(vlans []of.VlanType) bool {
263 if len(vlans) != 1 {
264 return false
265 }
266
267 if vlans[0] == vs.CVlan {
268 return true
269 }
270 return false
271}
272
273// MatchesPbits allows matching a service to a pbit. This is used
274// to search for a service matching the pbits, typically to identify
275// attributes for other flows such as DHCP, IGMP, etc.
276func (vs *VoltService) MatchesPbits(pbits []of.PbitType) bool {
277 for _, pbit := range pbits {
278 for _, pb := range vs.Pbits {
279 if pb == pbit {
280 return true
281 }
282 }
283 }
284 return false
285}
286
287// IsPbitExist allows matching a service to a pbit. This is used
288// to search for a service matching the pbit
289func (vs *VoltService) IsPbitExist(pbit of.PbitType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530290 logger.Debugw(ctx, "Request for IsPbitExist", log.Fields{"pbit": pbit})
Naveen Sampath04696f72022-06-13 15:19:14 +0530291 for _, pb := range vs.Pbits {
292 if pb == pbit {
293 return true
294 }
295 }
296 return false
297}
298
299// AddHsiaFlows - Adds US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530300func (vs *VoltService) AddHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530301 logger.Debugw(ctx, "Add US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530302 if err := vs.AddUsHsiaFlows(cntx); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530303 logger.Errorw(ctx, "Error adding US HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530304 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
305 vs.triggerServiceFailureInd(statusCode, statusMessage)
306 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530307 if err := vs.AddDsHsiaFlows(cntx); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530308 logger.Errorw(ctx, "Error adding DS HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530309 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
310 vs.triggerServiceFailureInd(statusCode, statusMessage)
311 }
312}
313
vinokuma926cb3e2023-03-29 11:41:06 +0530314// DelHsiaFlows - Deletes US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530315func (vs *VoltService) DelHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530316 logger.Debugw(ctx, "Delete US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530317 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530318 logger.Errorw(ctx, "Error deleting US HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530319 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
320 vs.triggerServiceFailureInd(statusCode, statusMessage)
321 }
322
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530323 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530324 logger.Errorw(ctx, "Error deleting DS HSIA Flows", log.Fields{"Service": vs.Name, "Port": vs.Port, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530325 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
326 vs.triggerServiceFailureInd(statusCode, statusMessage)
327 }
328}
329
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530330func (vs *VoltService) AddMeterToDevice(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530331 logger.Debugw(ctx, "Add Meter To Device for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530332 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530333 logger.Warnw(ctx, "Ignoring Meter Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530334 }
335 va := GetApplication()
336 logger.Infow(ctx, "Configuring Meters for FTTB", log.Fields{"ServiceName": vs.Name})
337 device, err := va.GetDeviceFromPort(vs.Port)
338 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530339 return fmt.Errorf("Error during Getting Device from Port %s for service %s : %w", vs.Port, vs.Name, err)
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530340 } else if device.State != controller.DeviceStateUP {
341 logger.Warnw(ctx, "Device state Down. Ignoring Meter Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
342 return nil
343 }
344 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
345 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
346 return nil
347}
348
Naveen Sampath04696f72022-06-13 15:19:14 +0530349// AddUsHsiaFlows - Add US HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530350func (vs *VoltService) AddUsHsiaFlows(cntx context.Context) error {
Akash Sonief452f12024-12-12 18:20:28 +0530351 logger.Infow(ctx, "Configuring US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530352 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530353 logger.Warnw(ctx, "Ignoring US HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530354 return nil
355 }
356
357 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530358 if !vs.UsHSIAFlowsApplied || vgcRebooted {
359 device, err := va.GetDeviceFromPort(vs.Port)
360 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530361 logger.Errorw(ctx, "Error Getting Device for Service and Port", log.Fields{"Service": vs.Name, "Port": vs.Port, "Error": err})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530362 return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530363 } else if device.State != controller.DeviceStateUP {
364 logger.Warnw(ctx, "Device state Down. Ignoring US HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
365 return nil
366 }
367
368 vs.Device = device.Name
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530369 /* In case of DPU_MGMT_TRAFFIC the meters will be configured before US flow creation*/
vinokuma926cb3e2023-03-29 11:41:06 +0530370 if vs.ServiceType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530371 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
372 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
373 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530374 pBits := vs.Pbits
375
vinokuma926cb3e2023-03-29 11:41:06 +0530376 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530377 if len(vs.Pbits) == 0 {
378 pBits = append(pBits, PbitMatchNone)
379 }
380 for _, pbits := range pBits {
381 usflows, err := vs.BuildUsHsiaFlows(pbits)
382 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530383 logger.Errorw(ctx, "Error Building HSIA US flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530384 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
385 vs.triggerServiceFailureInd(statusCode, statusMessage)
386 continue
387 }
388 usflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530389 if err := vs.AddFlows(cntx, device, usflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530390 logger.Errorw(ctx, "Error adding HSIA US flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530391 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
392 vs.triggerServiceFailureInd(statusCode, statusMessage)
393 }
394 }
395 vs.UsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530396 logger.Debugw(ctx, "Pushed US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530397 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530398 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530399 return nil
400}
401
402// AddDsHsiaFlows - Add DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530403func (vs *VoltService) AddDsHsiaFlows(cntx context.Context) error {
Akash Sonief452f12024-12-12 18:20:28 +0530404 logger.Infow(ctx, "Configuring DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530405 if vs.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530406 logger.Warnw(ctx, "Ignoring DS HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530407 return nil
408 }
409
410 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530411 if !vs.DsHSIAFlowsApplied || vgcRebooted {
412 device, err := va.GetDeviceFromPort(vs.Port)
413 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530414 logger.Errorw(ctx, "Error Getting Device for Service and Port", log.Fields{"Service": vs.Name, "Port": vs.Port, "Error": err})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530415 return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530416 } else if device.State != controller.DeviceStateUP {
417 logger.Warnw(ctx, "Device state Down. Ignoring DS HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
418 return nil
419 }
420
421 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530422
423 //If no pbits configured for service, hence add PbitNone for flows
424 if len(vs.DsRemarkPbitsMap) == 0 {
425 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchNone))
426 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530427 return fmt.Errorf("Error Building HSIA DS flows for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530428 }
429 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530430 if err = vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530431 logger.Errorw(ctx, "Failed to add HSIA DS flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530432 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
433 vs.triggerServiceFailureInd(statusCode, statusMessage)
434 }
435 } else {
436 // if all 8 p-bits are to be remarked to one-pbit, configure all-to-one remarking flow
437 if _, ok := vs.DsRemarkPbitsMap[int(of.PbitMatchAll)]; ok {
438 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchAll))
439 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530440 return fmt.Errorf("Error Building HSIA DS flows for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530441 }
442 logger.Debug(ctx, "Add-one-match-all-pbit-flow")
443 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530444 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530445 logger.Errorw(ctx, "Failed to add HSIA DS flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530446 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
447 vs.triggerServiceFailureInd(statusCode, statusMessage)
448 }
449 } else {
450 for matchPbit := range vs.DsRemarkPbitsMap {
451 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
452 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530453 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530454 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
455 vs.triggerServiceFailureInd(statusCode, statusMessage)
456 continue
457 }
458 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530459 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530460 logger.Errorw(ctx, "Failed to Add HSIA DS flows", log.Fields{"Device": vs.Device, "Service": vs.Name, "Reason": err})
Naveen Sampath04696f72022-06-13 15:19:14 +0530461 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
462 vs.triggerServiceFailureInd(statusCode, statusMessage)
463 }
464 }
465 }
466 }
467 vs.DsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530468 logger.Debugw(ctx, "Pushed DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530469 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530470 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530471 return nil
472}
473
474// DelUsHsiaFlows - Deletes US HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530475func (vs *VoltService) DelUsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530476 logger.Infow(ctx, "Removing US HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530477 if vs.UsHSIAFlowsApplied || vgcRebooted {
478 device, err := GetApplication().GetDeviceFromPort(vs.Port)
479 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530480 logger.Errorw(ctx, "Error Getting Device for Servic and Port", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530481 return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530482 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530483 pBits := vs.Pbits
484
vinokuma926cb3e2023-03-29 11:41:06 +0530485 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530486 if len(vs.Pbits) == 0 {
487 pBits = append(pBits, PbitMatchNone)
488 }
489 for _, pbits := range pBits {
490 usflows, err := vs.BuildUsHsiaFlows(pbits)
491 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530492 logger.Errorw(ctx, "Error Building HSIA US flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530493 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
494 vs.triggerServiceFailureInd(statusCode, statusMessage)
495 continue
496 }
497 usflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530498 if err = vs.DelFlows(cntx, device, usflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530499 logger.Errorw(ctx, "Error Deleting HSIA US flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530500 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
501 vs.triggerServiceFailureInd(statusCode, statusMessage)
502 }
503 }
504 vs.UsHSIAFlowsApplied = false
505 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530506 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530507 return nil
508}
509
510// DelDsHsiaFlows - Deletes DS HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530511func (vs *VoltService) DelDsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530512 logger.Infow(ctx, "Removing DS HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530513 if vs.DsHSIAFlowsApplied || vgcRebooted {
514 device, err := GetApplication().GetDeviceFromPort(vs.Port)
515 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530516 return fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530517 }
518
Naveen Sampath04696f72022-06-13 15:19:14 +0530519 var matchPbit int
vinokuma926cb3e2023-03-29 11:41:06 +0530520 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530521 if len(vs.DsRemarkPbitsMap) == 0 {
522 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(PbitMatchNone))
523 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530524 return fmt.Errorf("Error Building HSIA DS flows for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530525 }
526 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530527 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530528 logger.Errorw(ctx, "Error Deleting HSIA DS flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530529 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
530 vs.triggerServiceFailureInd(statusCode, statusMessage)
531 }
532 } else if _, ok := vs.DsRemarkPbitsMap[int(PbitMatchAll)]; ok {
533 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(int(PbitMatchAll)))
534 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530535 return fmt.Errorf("Error Building HSIA DS flows for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530536 }
537 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530538 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530539 logger.Errorw(ctx, "Error Deleting HSIA DS flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530540 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
541 vs.triggerServiceFailureInd(statusCode, statusMessage)
542 }
543 } else {
544 for matchPbit = range vs.DsRemarkPbitsMap {
545 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
546 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530547 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530548 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
549 vs.triggerServiceFailureInd(statusCode, statusMessage)
550 continue
551 }
552 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530553 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530554 logger.Errorw(ctx, "Error Deleting HSIA DS flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Reason": err.Error()})
Naveen Sampath04696f72022-06-13 15:19:14 +0530555 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
556 vs.triggerServiceFailureInd(statusCode, statusMessage)
557 }
558 }
559 }
560 vs.DsHSIAFlowsApplied = false
561 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530562 logger.Infow(ctx, "Deleted HSIA DS flows from DB successfully", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530563 // Post HSIA configuration success indication on message bus
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530564 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530565 return nil
566}
567
568// BuildDsHsiaFlows build the DS HSIA flows
569// Called for add/delete HSIA flows
570func (vs *VoltService) BuildDsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530571 logger.Debugw(ctx, "Building DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530572 flow := &of.VoltFlow{}
573 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
574
575 // Get the out and in ports for the flows
576 device, err := GetApplication().GetDeviceFromPort(vs.Port)
577 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530578 return nil, fmt.Errorf("Error Getting Device for Service %s and Port %s : %w", vs.Name, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530579 }
580 inport, _ := GetApplication().GetPortID(device.NniPort)
581 outport, _ := GetApplication().GetPortID(vs.Port)
582 // PortName and PortID to be used for validation of port before flow pushing
583 flow.PortID = outport
584 flow.PortName = vs.Port
585 allowTransparent := 0
586 if vs.AllowTransparent {
587 allowTransparent = 1
588 }
589
590 // initialized actnPbit to 0 for cookie genration backward compatibility.
591 var actnPbit of.PbitType
592 remarkPbit, remarkExists := vs.DsRemarkPbitsMap[int(pbits)]
593
594 generateDSCookie := func(vlan of.VlanType, valToShift uint64) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530595 // | 12-bit cvlan/UniVlan | 4 bits action pbit | <32-bits uniport>| 16-bits HSIA mask OR flow mask OR pbit |
Naveen Sampath04696f72022-06-13 15:19:14 +0530596 cookie := uint64(vlan)<<52 + uint64(actnPbit)<<48 + uint64(outport)<<16 | of.HsiaFlowMask
597 cookie = cookie | of.DsFlowMask
598 cookie = cookie + (valToShift << 4) + uint64(pbits)
599 return cookie
600 }
601
602 l2ProtoValue, err := GetMetadataForL2Protocol(vs.SVlanTpid)
603 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530604 return nil, fmt.Errorf("DS HSIA flow push failed: Invalid SvlanTpid for Service %s and SvlanTpid %s : %w", vs.SVlanTpid, vs.Port, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530605 }
606
607 // Add Table-0 flow that deals with the outer VLAN in pOLT
608 {
609 subflow1 := of.NewVoltSubFlow()
610 subflow1.SetTableID(0)
611 subflow1.SetGoToTable(1)
612 subflow1.SetInPort(inport)
613
614 if pbits != PbitMatchNone {
615 subflow1.SetMatchPbit(pbits)
616 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530617 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
618 subflow1.SetPcp(of.PbitType(remarkPbit))
619 // match & action pbits are different, set remark-pbit action
620 actnPbit = of.PbitType(remarkPbit)
621 // mask remark p-bit to 4bits
622 actnPbit = actnPbit & 0x0F
623 }
624
625 if err := vs.setDSMatchActionVlanT0(subflow1); err != nil {
626 return nil, err
627 }
Tinoj Joseph1d108322022-07-13 10:07:39 +0530628 logger.Infow(ctx, "HSIA DS flows MAC Learning & MAC", log.Fields{"ML": vs.MacLearning, "Mac": vs.MacAddr})
Naveen Sampath04696f72022-06-13 15:19:14 +0530629 if NonZeroMacAddress(vs.MacAddr) {
630 subflow1.SetMatchDstMac(vs.MacAddr)
631 }
632 subflow1.Priority = of.HsiaFlowPriority
633 subflow1.SetMeterID(vs.DsMeterID)
634
635 /* WriteMetaData 8 Byte(uint64) usage:
636 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
637 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
638 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530639 if vs.ServiceType == FttbSubscriberTraffic {
640 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
641 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530642 subflow1.SetWriteMetadata(metadata)
643
644 /* TableMetaData 8 Byte(uint64) Voltha usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
645 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
646 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
647 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | unitag | unitag | ctag | ctag | */
648
649 //TODO-COMM:
650 /* TableMetaData 8 Byte(uint64) Community usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
651 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
652 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
653 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | ctag | ctag | ctag | ctag | */
654
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530655 if vs.ServiceType != FttbSubscriberTraffic {
656 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
657 subflow1.SetTableMetadata(metadata)
658 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530659 // TODO - We are using cookie as key and must come up with better cookie
660 // allocation algorithm
661 /**
662 * Cokies may clash when -
663 * on same uni-port we have two sub-service
664 * 1. U=10, C=100, S=310, p-bit=4 - VLAN_Control = OLT_CVLAN_OLT_SVLAN
665 * 2. U=10, C=10, S=320, p-bit=4 - VLAN_control = ONU_CVLAN_ONU_SVLAN
666 * However, this p-bit re-use will not be allowed by sub-mgr.
667 */
668 if vs.VlanControl == OLTCVlanOLTSVlan {
669 /**
670 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
671 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
672 * use old cookie.
673 */
674 subflow1.Cookie = generateDSCookie(vs.UniVlan, 0)
675 if vgcRebooted {
676 subflow1.OldCookie = generateDSCookie(vs.CVlan, 0)
677 }
678 } else {
679 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
680 subflow1.Cookie = generateDSCookie(vs.CVlan, 0)
681 }
682
683 flow.SubFlows[subflow1.Cookie] = subflow1
684 logger.Infow(ctx, "Building downstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie,
685 "subflow": subflow1})
686 }
687
vinokuma926cb3e2023-03-29 11:41:06 +0530688 // Add Table-1 flow that deals with inner VLAN at the ONU
Naveen Sampath04696f72022-06-13 15:19:14 +0530689 {
690 subflow2 := of.NewVoltSubFlow()
691 subflow2.SetTableID(1)
692 subflow2.SetInPort(inport)
693 if NonZeroMacAddress(vs.MacAddr) {
694 subflow2.SetMatchDstMac(vs.MacAddr)
695 }
696
697 if err := vs.setDSMatchActionVlanT1(subflow2); err != nil {
698 return nil, err
699 }
700 if pbits != PbitMatchNone {
701 subflow2.SetMatchPbit(pbits)
702 }
703
704 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
705 subflow2.SetPcp(of.PbitType(remarkPbit))
706 }
707
708 subflow2.SetOutPort(outport)
709 subflow2.SetMeterID(vs.DsMeterID)
710
711 // refer Table-0 flow generation for byte information
712 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530713 if vs.ServiceType == FttbSubscriberTraffic {
714 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
715 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530716 subflow2.SetWriteMetadata(metadata)
717
718 // Table-1 and inport is NNI: It is a DS flow for ONU, add uniport in metadata to make it unique
719 if util.IsNniPort(inport) {
720 metadata = uint64(outport)
721 } else {
722 // refer Table-0 flow generation for byte information
723 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
724 }
725 subflow2.SetTableMetadata(metadata)
726 // Setting of Cookie - TODO - Improve the allocation algorithm
727 if vs.VlanControl == OLTCVlanOLTSVlan {
728 /**
729 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
730 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
731 * use old cookie.
732 */
733 subflow2.Cookie = generateDSCookie(vs.UniVlan, 1)
734 if vgcRebooted {
735 subflow2.OldCookie = generateDSCookie(vs.CVlan, 1)
736 }
737 } else {
738 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
739 subflow2.Cookie = generateDSCookie(vs.CVlan, 1)
740 }
741
742 subflow2.Priority = of.HsiaFlowPriority
743 flow.SubFlows[subflow2.Cookie] = subflow2
744 logger.Infow(ctx, "Building downstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie,
745 "subflow": subflow2})
746 }
747
748 return flow, nil
749}
750
751// BuildUsHsiaFlows build the US HSIA flows
752// Called for add/delete HSIA flows
753func (vs *VoltService) BuildUsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Akash Sonief452f12024-12-12 18:20:28 +0530754 logger.Debugw(ctx, "Building US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530755 flow := &of.VoltFlow{}
756 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
757
758 // Get the out and in ports for the flows
759 device, err := GetApplication().GetDeviceFromPort(vs.Port)
760 if err != nil {
761 return nil, errorCodes.ErrDeviceNotFound
762 }
763 outport, _ := GetApplication().GetPortID(device.NniPort)
764 inport, _ := GetApplication().GetPortID(vs.Port)
765 // PortName and PortID to be used for validation of port before flow pushing
766 flow.PortID = inport
767 flow.PortName = vs.Port
Naveen Sampath04696f72022-06-13 15:19:14 +0530768
769 // Add Table-0 flow that deals with the inner VLAN in ONU
770 {
771 subflow1 := of.NewVoltSubFlow()
772 subflow1.SetTableID(0)
773 subflow1.SetGoToTable(1)
774 subflow1.SetInPort(inport)
775
vinokuma926cb3e2023-03-29 11:41:06 +0530776 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530777 subflow1.SetMatchPbit(vs.UsPonCTagPriority)
778 subflow1.SetPcp(vs.UsPonSTagPriority)
vinokuma926cb3e2023-03-29 11:41:06 +0530779 } else if vs.ServiceType == DpuAncpTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530780 subflow1.SetPcp(vs.UsPonSTagPriority)
781 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530782 if err := vs.setUSMatchActionVlanT0(subflow1); err != nil {
783 return nil, err
784 }
785 subflow1.SetMeterID(vs.UsMeterID)
786
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530787 /* WriteMetaData 8 Byte(uint64) usage:
788 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
789 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
790 //metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
791 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530792 if vs.ServiceType == FttbSubscriberTraffic {
793 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
794 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530795 subflow1.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530796
Naveen Sampath04696f72022-06-13 15:19:14 +0530797 if vs.VlanControl == OLTCVlanOLTSVlan {
798 /**
799 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
800 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
801 * use old cookie.
802 */
803 subflow1.Cookie = vs.generateUSCookie(vs.UniVlan, 0, inport, pbits)
804 if vgcRebooted {
805 subflow1.OldCookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
806 }
807 } else {
808 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
809 subflow1.Cookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
810 }
811 subflow1.Priority = of.HsiaFlowPriority
812 flow.SubFlows[subflow1.Cookie] = subflow1
813 logger.Infow(ctx, "Building upstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie, "subflow": subflow1})
814 }
815
vinokuma926cb3e2023-03-29 11:41:06 +0530816 // Add Table-1 flow that deals with the outer vlan in pOLT
Naveen Sampath04696f72022-06-13 15:19:14 +0530817 {
818 subflow2 := of.NewVoltSubFlow()
819 subflow2.SetTableID(1)
820 subflow2.SetInPort(inport)
821
Naveen Sampath04696f72022-06-13 15:19:14 +0530822 if err := vs.setUSMatchActionVlanT1(subflow2); err != nil {
823 return nil, err
824 }
vinokuma926cb3e2023-03-29 11:41:06 +0530825 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530826 subflow2.SetMatchSrcMac(vs.MacAddr)
827 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530828 subflow2.SetInPort(inport)
829 subflow2.SetOutPort(outport)
830 subflow2.SetMeterID(vs.UsMeterID)
831
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530832 // refer Table-0 flow generation for byte information
833 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530834 if vs.ServiceType == FttbSubscriberTraffic {
835 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
836 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530837 subflow2.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530838
Naveen Sampath04696f72022-06-13 15:19:14 +0530839 if vs.VlanControl == OLTCVlanOLTSVlan {
840 /**
841 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
842 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
843 * use old cookie.
844 */
845 subflow2.Cookie = vs.generateUSCookie(vs.UniVlan, 1, inport, pbits)
846 if vgcRebooted {
847 subflow2.OldCookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
848 }
849 } else {
850 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
851 subflow2.Cookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
852 }
853 subflow2.Priority = of.HsiaFlowPriority
854
855 flow.SubFlows[subflow2.Cookie] = subflow2
856 logger.Infow(ctx, "Building upstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie, "subflow": subflow2})
857 }
858
859 return flow, nil
860}
861
862func (vs *VoltService) generateUSCookie(vlan of.VlanType, valToShift uint64, inport uint32, pbits of.PbitType) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530863 // | 12-bit cvlan/UniVlan | 4 bits empty | <32-bits uniport>| 16-bits HSIA mask OR flow mask OR pbit |
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530864 logger.Debugw(ctx, "Generate US Cookie", log.Fields{"Vlan": vlan, "ValToShift": vlan, "Inport": inport, "Pbits": pbits})
Naveen Sampath04696f72022-06-13 15:19:14 +0530865 cookie := uint64(vlan)<<52 + uint64(inport)<<16 | of.HsiaFlowMask
866 cookie = cookie | of.UsFlowMask
867 cookie = cookie + (valToShift << 4) + uint64(pbits)
868 return cookie
869}
870
871// setUSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for US Table-1
872// based on different Vlan Controls
873func (vs *VoltService) setUSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530874 logger.Debugw(ctx, "Set US Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530875 switch vs.VlanControl {
876 case None:
877 flow.SetMatchVlan(vs.SVlan)
878 case ONUCVlanOLTSVlan:
879 flow.SetMatchVlan(vs.CVlan)
880 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
881 case OLTCVlanOLTSVlan:
882 flow.SetMatchVlan(vs.UniVlan)
883 flow.SetSetVlan(vs.CVlan)
884 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
885 case ONUCVlan:
886 flow.SetMatchVlan(vs.SVlan)
887 case OLTSVlan:
888 if vs.UniVlan != of.VlanAny && vs.UniVlan != of.VlanNone {
889 flow.SetMatchVlan(vs.UniVlan)
890 flow.SetSetVlan(vs.SVlan)
891 } else if vs.UniVlan != of.VlanNone {
892 flow.SetMatchVlan(vs.UniVlan)
893 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
894 } else {
895 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
896 }
897 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530898 err := errorCodes.ErrInvalidParamInRequest
899 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530900 }
901 return nil
902}
903
904// setDSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for DS Table-0
905// based on different Vlan Controls
906func (vs *VoltService) setDSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530907 logger.Debugw(ctx, "Set DS Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530908 switch vs.VlanControl {
909 case None:
910 flow.SetMatchVlan(vs.SVlan)
911 case ONUCVlanOLTSVlan:
912 flow.SetMatchVlan(vs.SVlan)
913 flow.SetPopVlan()
914 case OLTCVlanOLTSVlan:
915 flow.SetMatchVlan(vs.SVlan)
916 flow.SetPopVlan()
917 flow.SetSetVlan(vs.UniVlan)
918 case ONUCVlan:
919 flow.SetMatchVlan(vs.SVlan)
920 case OLTSVlan:
921 flow.SetMatchVlan(vs.SVlan)
922 if vs.UniVlan != of.VlanNone && vs.UniVlan != of.VlanAny {
923 flow.SetSetVlan(vs.UniVlan)
924 } else {
925 flow.SetPopVlan()
926 }
927 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530928 err := errorCodes.ErrInvalidParamInRequest
929 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530930 }
931 return nil
932}
933
934// setUSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for US Table-0
935// based on different Vlan Controls
936func (vs *VoltService) setUSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530937 logger.Debugw(ctx, "Set US Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530938 switch vs.VlanControl {
939 case None:
940 flow.SetMatchVlan(vs.SVlan)
941 case ONUCVlanOLTSVlan:
942 if vs.UniVlan != of.VlanNone {
943 flow.SetMatchVlan(vs.UniVlan)
944 flow.SetSetVlan(vs.CVlan)
945 } else {
946 flow.SetPushVlan(vs.CVlan, layers.EthernetTypeDot1Q)
947 }
948 case OLTCVlanOLTSVlan:
949 flow.SetMatchVlan(vs.UniVlan)
950 case ONUCVlan:
951 if vs.UniVlan != of.VlanNone {
952 flow.SetMatchVlan(vs.UniVlan)
953 flow.SetSetVlan(vs.SVlan)
954 } else {
955 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
956 }
957 case OLTSVlan:
958 flow.SetMatchVlan(vs.UniVlan)
959 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530960 err := errorCodes.ErrInvalidParamInRequest
961 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530962 }
963 return nil
964}
965
966// setDSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for DS Table-1
967// based on different Vlan Controls
968func (vs *VoltService) setDSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530969 logger.Debugw(ctx, "Set DS Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530970 switch vs.VlanControl {
971 case None:
972 flow.SetMatchVlan(vs.SVlan)
973 case ONUCVlanOLTSVlan:
974 flow.SetMatchVlan(vs.CVlan)
975 if vs.UniVlan != of.VlanNone {
976 flow.SetSetVlan(vs.UniVlan)
977 } else {
978 flow.SetPopVlan()
979 }
980 case OLTCVlanOLTSVlan:
981 flow.SetMatchVlan(vs.UniVlan)
982 case ONUCVlan:
983 flow.SetMatchVlan(vs.SVlan)
984 if vs.UniVlan != of.VlanNone {
985 flow.SetSetVlan(vs.UniVlan)
986 } else {
987 flow.SetPopVlan()
988 }
989 case OLTSVlan:
990 flow.SetMatchVlan(vs.UniVlan)
991 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530992 err := errorCodes.ErrInvalidParamInRequest
993 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530994 }
995 return nil
996}
997
998// SvcUpInd for service up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530999func (vs *VoltService) SvcUpInd(cntx context.Context) {
1000 vs.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301001}
1002
1003// SvcDownInd for service down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301004func (vs *VoltService) SvcDownInd(cntx context.Context) {
1005 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301006}
1007
1008// SetIpv4Addr to set ipv4 address
1009func (vs *VoltService) SetIpv4Addr(addr net.IP) {
1010 vs.Ipv4Addr = addr
1011}
1012
1013// SetIpv6Addr to set ipv6 address
1014func (vs *VoltService) SetIpv6Addr(addr net.IP) {
1015 vs.Ipv6Addr = addr
1016}
1017
1018// SetMacAddr to set mac address
1019func (vs *VoltService) SetMacAddr(addr net.HardwareAddr) {
1020 vs.MacAddr = addr
1021}
1022
1023// ----------------------------------------------
1024// VOLT Application - Related to services
1025// ---------------------------------------------
1026// ---------------------------------------------------------------
1027// Service CRUD functions. These are exposed to the overall binary
1028// to be invoked from the point where the CRUD operations are received
1029// from the external entities
1030
1031// AddService : A service in the context of VOLT is a subscriber or service of a
1032// subscriber which is uniquely identified by a combination of MAC
1033// address, VLAN tags, 802.1p bits. However, in the context of the
1034// current implementation, a service is an entity that is identified by a
1035// unique L2 (MAC address + VLANs) or unique L3 (VLANs + IP address)
1036// FUNC: Add Service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301037func (va *VoltApplication) AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301038 logger.Infow(ctx, "Service to be configured", log.Fields{"Cfg": cfg})
Naveen Sampath04696f72022-06-13 15:19:14 +05301039 var mmUs, mmDs *VoltMeter
1040 var err error
1041
vinokuma926cb3e2023-03-29 11:41:06 +05301042 // Take the Device lock only in case of NB add request.
Naveen Sampath04696f72022-06-13 15:19:14 +05301043 // Allow internal adds since internal add happen only under
1044 // 1. Restore Service from DB
1045 // 2. Service Migration
1046 if oper == nil {
1047 if svc := va.GetService(cfg.Name); svc != nil {
1048 logger.Warnw(ctx, "Service Already Exists. Ignoring Add Service Request", log.Fields{"Name": cfg.Name})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301049 return errors.New("service already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301050 }
1051 }
1052
Naveen Sampath04696f72022-06-13 15:19:14 +05301053 // Service doesn't exist. So create it and add to the port
1054 vs := NewVoltService(&cfg)
1055 if oper != nil {
1056 vs.UsHSIAFlowsApplied = oper.UsHSIAFlowsApplied
1057 vs.DsHSIAFlowsApplied = oper.DsHSIAFlowsApplied
1058 vs.Ipv4Addr = oper.Ipv4Addr
1059 vs.Ipv6Addr = oper.Ipv6Addr
1060 vs.MacLearning = cfg.MacLearning
1061 vs.PendingFlows = oper.PendingFlows
1062 vs.AssociatedFlows = oper.AssociatedFlows
1063 vs.DeleteInProgress = oper.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301064 vs.DeactivateInProgress = oper.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301065 vs.BwAvailInfo = oper.BwAvailInfo
1066 vs.Device = oper.Device
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301067 vs.ServiceDeactivateReason = cfg.ServiceDeactivateReason
Naveen Sampath04696f72022-06-13 15:19:14 +05301068 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301069 // Sorting Pbit from highest
Naveen Sampath04696f72022-06-13 15:19:14 +05301070 sort.Slice(vs.Pbits, func(i, j int) bool {
1071 return vs.Pbits[i] > vs.Pbits[j]
1072 })
Akash Sonief452f12024-12-12 18:20:28 +05301073 logger.Debugw(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
Naveen Sampath04696f72022-06-13 15:19:14 +05301074 }
1075 logger.Infow(ctx, "VolthService...", log.Fields{"vs": vs.Name})
1076
1077 // The bandwidth and shaper profile combined into meter
1078 if mmDs, err = va.GetMeter(cfg.DsMeterProfile); err == nil {
1079 vs.DsMeterID = mmDs.ID
1080 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301081 return errors.New("downStream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301082 }
1083
1084 // The aggregated downstream meter profile
1085 // if mmAg, err = va.GetMeter(cfg.AggDsMeterProfile); err == nil {
1086 // vs.AggDsMeterID = mmAg.ID
1087 // } else {
1088 // return errors.New("Aggregated meter profile not found")
1089 // }
1090
1091 // if cfg.AggDsMeterProfile == cfg.UsMeterProfile {
1092 // vs.UsMeterID = mmAg.ID
1093 // } else {
1094 // The bandwidth and shaper profile combined into meter
1095 if mmUs, err = va.GetMeter(cfg.UsMeterProfile); err == nil {
1096 vs.UsMeterID = mmUs.ID
1097 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301098 return errors.New("upstream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301099 }
1100 //}
1101
1102 AppMutex.ServiceDataMutex.Lock()
1103 defer AppMutex.ServiceDataMutex.Unlock()
1104
1105 // Add the service to the VNET
1106 vnet := va.GetVnet(cfg.SVlan, cfg.CVlan, cfg.UniVlan)
1107 if vnet != nil {
1108 if vpv := va.GetVnetByPort(vs.Port, cfg.SVlan, cfg.CVlan, cfg.UniVlan); vpv != nil {
1109 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301110 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301111 vpv.VpvLock.Unlock()
1112 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301113 va.AddVnetToPort(cntx, vs.Port, vnet, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301114 }
1115 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301116 logger.Warnw(ctx, "VNET-does-not-exist-for-service", log.Fields{"ServiceName": cfg.Name})
1117 return errors.New("vnet doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301118 }
1119
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301120 // If the device is already discovered, update the device name in service
1121 d, err := va.GetDeviceFromPort(vs.Port)
1122 if err == nil {
1123 vs.Device = d.Name
1124 }
1125
Naveen Sampath04696f72022-06-13 15:19:14 +05301126 vs.Version = database.PresentVersionMap[database.ServicePath]
1127 // Add the service to the volt application
1128 va.ServiceByName.Store(vs.Name, vs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301129 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301130
1131 if nil == oper {
Naveen Sampath04696f72022-06-13 15:19:14 +05301132 if !vs.UsHSIAFlowsApplied {
1133 vs.triggerServiceInProgressInd()
1134 }
1135
vinokuma926cb3e2023-03-29 11:41:06 +05301136 // Update meter profiles service count if service is being added from northbound
Naveen Sampath04696f72022-06-13 15:19:14 +05301137 mmDs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301138 va.UpdateMeterProf(cntx, *mmDs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301139 if mmUs != nil {
1140 mmUs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301141 va.UpdateMeterProf(cntx, *mmUs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301142 }
1143 //mmAg.AssociatedServices++
1144 //va.UpdateMeterProf(*mmAg)
vinokuma926cb3e2023-03-29 11:41:06 +05301145 logger.Debugw(ctx, "northbound-service-add-successful", log.Fields{"ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301146 }
1147
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301148 logger.Debugw(ctx, "Added Service to DB", log.Fields{"Name": vs.Name, "Port": (vs.Port), "ML": vs.MacLearning})
Naveen Sampath04696f72022-06-13 15:19:14 +05301149 return nil
1150}
1151
vinokuma926cb3e2023-03-29 11:41:06 +05301152// DelServiceWithPrefix - Deletes service with the provided prefix.
Naveen Sampath04696f72022-06-13 15:19:14 +05301153// Added for DT/TT usecase with sadis replica interface
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301154func (va *VoltApplication) DelServiceWithPrefix(cntx context.Context, prefix string) error {
Akash Sonief452f12024-12-12 18:20:28 +05301155 logger.Debugw(ctx, "Delete Service With provided Prefix", log.Fields{"Prefix": prefix})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301156 var isServiceExist bool
Naveen Sampath04696f72022-06-13 15:19:14 +05301157 va.ServiceByName.Range(func(key, value interface{}) bool {
1158 srvName := key.(string)
1159 vs := value.(*VoltService)
1160 if strings.Contains(srvName, prefix) {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301161 isServiceExist = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301162 va.DelService(cntx, srvName, true, nil, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301163
1164 vnetName := strconv.FormatUint(uint64(vs.SVlan), 10) + "-"
1165 vnetName = vnetName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1166 vnetName = vnetName + strconv.FormatUint(uint64(vs.UniVlan), 10)
1167
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301168 if err := va.DelVnet(cntx, vnetName, ""); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301169 logger.Warnw(ctx, "Delete Vnet Failed", log.Fields{"Name": vnetName, "Error": err})
1170 }
1171 }
1172 return true
1173 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301174
1175 if !isServiceExist {
1176 return errorCodes.ErrServiceNotFound
1177 }
1178 return nil
Naveen Sampath04696f72022-06-13 15:19:14 +05301179}
1180
1181// DelService delete a service form the application
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301182func (va *VoltApplication) DelService(cntx context.Context, name string, forceDelete bool, newSvc *VoltServiceCfg, serviceMigration bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301183 AppMutex.ServiceDataMutex.Lock()
1184 defer AppMutex.ServiceDataMutex.Unlock()
1185
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301186 logger.Infow(ctx, "Delete Service Request", log.Fields{"Service": name, "ForceDelete": forceDelete, "serviceMigration": serviceMigration})
Naveen Sampath04696f72022-06-13 15:19:14 +05301187 var noFlowsPresent bool
1188
1189 vsIntf, ok := va.ServiceByName.Load(name)
1190 if !ok {
1191 logger.Warnw(ctx, "Service doesn't exist", log.Fields{"ServiceName": name})
1192 return
1193 }
1194 vs := vsIntf.(*VoltService)
1195 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1196 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301197 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301198 return
1199 }
1200
vinokuma926cb3e2023-03-29 11:41:06 +05301201 // Set this to avoid race-condition during flow result processing
Naveen Sampath04696f72022-06-13 15:19:14 +05301202 vs.DeleteInProgress = true
1203 vs.ForceDelete = forceDelete
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301204 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301205
Akash Sonief452f12024-12-12 18:20:28 +05301206 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301207 if len(vs.AssociatedFlows) == 0 {
1208 noFlowsPresent = true
1209 }
Akash Sonief452f12024-12-12 18:20:28 +05301210 vs.ServiceLock.RUnlock()
1211
Naveen Sampath04696f72022-06-13 15:19:14 +05301212 vpv.VpvLock.Lock()
1213 defer vpv.VpvLock.Unlock()
1214
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301215 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301216
1217 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301218 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301219 }
1220 logger.Infow(ctx, "Delete Service from VPV", log.Fields{"VPV_Port": vpv.Port, "VPV_SVlan": vpv.SVlan, "VPV_CVlan": vpv.CVlan, "VPV_UniVlan": vpv.UniVlan, "ServiceName": name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301221 vpv.DelService(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301222 if vpv.servicesCount.Load() == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301223 va.DelVnetFromPort(cntx, vs.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301224 }
1225
1226 // Delete the service immediately in case of Force Delete
1227 // This will be enabled when profile reconciliation happens after restore
1228 // of backedup data
1229 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301230 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301231 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301232 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301233 }
1234
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 if nil != newSvc {
1236 logger.Infow(ctx, "Old Service meter profiles", log.Fields{"AGG": vs.AggDsMeterProfile, "DS": vs.DsMeterProfile, "US": vs.UsMeterProfile})
1237 logger.Infow(ctx, "New Service meter profiles", log.Fields{"AGG": newSvc.AggDsMeterProfile, "DS": newSvc.DsMeterProfile, "US": newSvc.UsMeterProfile})
1238 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301239
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301240 logger.Infow(ctx, "About to mark meter for deletion\n", log.Fields{"serviceName": vs.Name})
1241
1242 if aggMeter, ok := va.MeterMgr.GetMeterByID(vs.AggDsMeterID); ok {
1243 if nil == newSvc || (nil != newSvc && aggMeter.Name != newSvc.AggDsMeterProfile) {
vinokuma926cb3e2023-03-29 11:41:06 +05301244 if aggMeter.AssociatedServices > 0 {
1245 aggMeter.AssociatedServices--
1246 logger.Infow(ctx, "Agg Meter associated services updated\n", log.Fields{"MeterID": aggMeter})
1247 va.UpdateMeterProf(cntx, *aggMeter)
1248 }
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301249 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301250 }
1251 if dsMeter, ok := va.MeterMgr.GetMeterByID(vs.DsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301252 if nil == newSvc || (nil != newSvc && dsMeter.Name != newSvc.DsMeterProfile) {
1253 if dsMeter.AssociatedServices > 0 {
1254 dsMeter.AssociatedServices--
1255 logger.Infow(ctx, "DS Meter associated services updated\n", log.Fields{"MeterID": dsMeter})
1256 va.UpdateMeterProf(cntx, *dsMeter)
1257 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301258 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301259 }
1260 if vs.AggDsMeterID != vs.UsMeterID {
1261 if usMeter, ok := va.MeterMgr.GetMeterByID(vs.UsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301262 if nil == newSvc || (nil != newSvc && usMeter.Name != newSvc.UsMeterProfile) {
1263 if usMeter.AssociatedServices > 0 {
1264 usMeter.AssociatedServices--
1265 logger.Infow(ctx, "US Meter associated services updated\n", log.Fields{"MeterID": usMeter})
1266 va.UpdateMeterProf(cntx, *usMeter)
1267 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301268 }
1269 }
1270 }
1271
1272 if noFlowsPresent || vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301273 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301274 }
1275
vinokuma926cb3e2023-03-29 11:41:06 +05301276 // Delete the per service counter too
Naveen Sampath04696f72022-06-13 15:19:14 +05301277 va.ServiceCounters.Delete(name)
1278 if vs.IgmpEnabled && vs.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301279 _ = db.DelAllServiceChannelCounter(cntx, name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301280 }
1281}
1282
vinokuma926cb3e2023-03-29 11:41:06 +05301283// AddFlows - Adds the flow to the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301284// Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301285func (vs *VoltService) AddFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301286 // Using locks instead of concurrent map for PendingFlows to avoid
1287 // race condition during flow response indication processing
1288 vs.ServiceLock.Lock()
1289 defer vs.ServiceLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301290 logger.Debugw(ctx, "Adds the flow to the service", log.Fields{"Port": vs.Port, "Device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301291
1292 for cookie := range flow.SubFlows {
1293 cookie := strconv.FormatUint(cookie, 10)
1294 fe := &FlowEvent{
1295 eType: EventTypeServiceFlowAdded,
1296 device: device.Name,
1297 cookie: cookie,
1298 eventData: vs,
1299 }
1300 device.RegisterFlowAddEvent(cookie, fe)
1301 vs.PendingFlows[cookie] = true
1302 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301303 return cntlr.GetController().AddFlows(cntx, vs.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301304}
1305
vinokuma926cb3e2023-03-29 11:41:06 +05301306// FlowInstallSuccess - Called when corresponding service flow installation is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301307// If no more pending flows, HSIA indication wil be triggered
Akash Sonief452f12024-12-12 18:20:28 +05301308func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301309 logger.Debugw(ctx, "Flow Add Success Notification", log.Fields{"Cookie": cookie, "bwAvailInfo": bwAvailInfo, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301310 if vs.DeleteInProgress {
1311 logger.Warnw(ctx, "Skipping Flow Add Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1312 return
1313 }
1314 vs.ServiceLock.Lock()
1315
1316 if _, ok := vs.PendingFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301317 logger.Warnw(ctx, "Flow Add Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301318 vs.ServiceLock.Unlock()
1319 return
1320 }
1321
1322 delete(vs.PendingFlows, cookie)
1323 vs.AssociatedFlows[cookie] = true
1324 vs.ServiceLock.Unlock()
1325 var prevBwAvail, presentBwAvail string
1326 if bwAvailInfo.PrevBw != "" && bwAvailInfo.PresentBw != "" {
1327 prevBwAvail = bwAvailInfo.PrevBw
1328 presentBwAvail = bwAvailInfo.PresentBw
1329 vs.BwAvailInfo = prevBwAvail + "," + presentBwAvail
Tinoj Joseph1d108322022-07-13 10:07:39 +05301330 logger.Debugw(ctx, "Bandwidth-value-formed", log.Fields{"BwAvailInfo": vs.BwAvailInfo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301331 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301332 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301333
Akash Sonief452f12024-12-12 18:20:28 +05301334 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301335 if len(vs.PendingFlows) == 0 && vs.DsHSIAFlowsApplied {
Akash Sonief452f12024-12-12 18:20:28 +05301336 vs.ServiceLock.RUnlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301337 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1338 if err != nil {
1339 logger.Errorw(ctx, "Error Getting Device. Dropping HSIA Success indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1340 return
1341 } else if device.State != controller.DeviceStateUP {
1342 logger.Warnw(ctx, "Device state Down. Dropping HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1343 return
1344 }
1345
1346 if vs.Trigger == ServiceVlanUpdate {
1347 vs.Trigger = NBActivate
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301348 defer vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301349 }
1350 logger.Infow(ctx, "All Flows installed for Service", log.Fields{"Service": vs.Name})
1351 return
1352 }
Akash Sonief452f12024-12-12 18:20:28 +05301353 vs.ServiceLock.RUnlock()
1354 logger.Debugw(ctx, "Processed Service Flow Add Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301355}
1356
vinokuma926cb3e2023-03-29 11:41:06 +05301357// FlowInstallFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301358// Trigger service failure indication to NB
Akash Sonief452f12024-12-12 18:20:28 +05301359func (vs *VoltService) FlowInstallFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301360 logger.Debugw(ctx, "Service flow installation failure", log.Fields{"Service": vs.Name, "Cookie": cookie, "errorCode": errorCode, "errReason": errReason})
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301361 vs.ServiceLock.RLock()
Akash Sonief452f12024-12-12 18:20:28 +05301362
Naveen Sampath04696f72022-06-13 15:19:14 +05301363 if _, ok := vs.PendingFlows[cookie]; !ok {
1364 logger.Errorw(ctx, "Flow Add Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1365 vs.ServiceLock.RUnlock()
1366 return
1367 }
1368 vs.ServiceLock.RUnlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301369 logger.Debugw(ctx, "HSIA Flow Add Failure Notification", log.Fields{"uniPort": vs.Port, "Cookie": cookie, "Service": vs.Name, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05301370 vs.triggerServiceFailureInd(errorCode, errReason)
1371}
1372
vinokuma926cb3e2023-03-29 11:41:06 +05301373// DelFlows - Deletes the flow from the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301374// Triggers flow deletion after registering for flow indication event
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301375func (vs *VoltService) DelFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow, delFlowsInDevice bool) error {
Akash Sonief452f12024-12-12 18:20:28 +05301376 logger.Infow(ctx, "Delete the flow from the service", log.Fields{"Port": vs.Port, "Device": device.Name, "cookie": flow.MigrateCookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301377 if !vs.ForceDelete {
1378 // Using locks instead of concurrent map for AssociatedFlows to avoid
1379 // race condition during flow response indication processing
1380 vs.ServiceLock.Lock()
1381 defer vs.ServiceLock.Unlock()
1382
1383 for cookie := range flow.SubFlows {
1384 cookie := strconv.FormatUint(cookie, 10)
1385 fe := &FlowEvent{
1386 eType: EventTypeServiceFlowRemoved,
1387 cookie: cookie,
1388 eventData: vs,
1389 }
1390 device.RegisterFlowDelEvent(cookie, fe)
1391 }
1392 }
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301393 return cntlr.GetController().DelFlows(cntx, vs.Port, device.Name, flow, delFlowsInDevice)
Naveen Sampath04696f72022-06-13 15:19:14 +05301394}
1395
vinokuma926cb3e2023-03-29 11:41:06 +05301396// CheckAndDeleteService - remove service from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301397func (vs *VoltService) CheckAndDeleteService(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301398 logger.Debugw(ctx, "Delete service from DB/Cache", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301399 if vs.DeleteInProgress && len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301400 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301401 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301402 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301403 }
1404}
1405
vinokuma926cb3e2023-03-29 11:41:06 +05301406// FlowRemoveSuccess - Called when corresponding service flow removal is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301407// If no more associated flows, DelHSIA indication wil be triggered
Akash Sonief452f12024-12-12 18:20:28 +05301408func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301409 // if vs.DeleteInProgress {
1410 // logger.Warnw(ctx, "Skipping Flow Remove Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1411 // return
1412 // }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301413
Naveen Sampath04696f72022-06-13 15:19:14 +05301414 vs.ServiceLock.Lock()
Akash Sonief452f12024-12-12 18:20:28 +05301415 logger.Debugw(ctx, "Processing Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301416
1417 if _, ok := vs.AssociatedFlows[cookie]; ok {
1418 delete(vs.AssociatedFlows, cookie)
1419 } else if _, ok := vs.PendingFlows[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301420 logger.Debugw(ctx, "Service Flow Remove: Cookie Present in Pending Flow list. No Action", log.Fields{"Service": vs.Name, "Cookie": cookie, "AssociatedFlows": vs.AssociatedFlows, "PendingFlows": vs.PendingFlows})
Naveen Sampath04696f72022-06-13 15:19:14 +05301421 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301422 logger.Debugw(ctx, "Service Flow Remove Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie, "AssociatedFlows": vs.AssociatedFlows, "PendingFlows": vs.PendingFlows})
Naveen Sampath04696f72022-06-13 15:19:14 +05301423 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301424 vs.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301425 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301426
Akash Sonief452f12024-12-12 18:20:28 +05301427 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301428 if len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Akash Sonief452f12024-12-12 18:20:28 +05301429 vs.ServiceLock.RUnlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301430 device := GetApplication().GetDevice(vs.Device)
1431 if device == nil {
1432 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1433 return
1434 } else if device.State != controller.DeviceStateUP {
1435 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1436 return
1437 }
1438
1439 if vs.UpdateInProgress {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301440 vs.updateVnetProfile(cntx, vs.Device)
vinokuma926cb3e2023-03-29 11:41:06 +05301441 // Not sending DEL_HSIA Indication since it wil be generated internally by SubMgr
Naveen Sampath04696f72022-06-13 15:19:14 +05301442 return
1443 }
1444 logger.Infow(ctx, "All Flows removed for Service. Triggering Service De-activation Success indication to NB", log.Fields{"Service": vs.Name, "DeleteFlag": vs.DeleteInProgress})
Akash Sonief452f12024-12-12 18:20:28 +05301445 // Get the service from application before proceeding to delete, as the service might have been activated
1446 // by the time the flow removal response is received from SB
1447 svc := GetApplication().GetService(vs.Name)
1448 if svc != nil {
1449 svc.CheckAndDeleteService(cntx)
1450 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301451
1452 return
1453 }
Akash Sonief452f12024-12-12 18:20:28 +05301454 vs.ServiceLock.RUnlock()
1455 logger.Debugw(ctx, "Processed Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301456}
1457
vinokuma926cb3e2023-03-29 11:41:06 +05301458// FlowRemoveFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301459// Trigger service failure indication to NB
Akash Sonief452f12024-12-12 18:20:28 +05301460func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301461 vs.ServiceLock.Lock()
Akash Sonief452f12024-12-12 18:20:28 +05301462 logger.Debugw(ctx, "Processing Service Flow Remove Failure Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301463
1464 if _, ok := vs.AssociatedFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301465 logger.Warnw(ctx, "Flow Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301466 vs.ServiceLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301467 return
1468 }
1469 if vs.DeleteInProgress {
1470 delete(vs.AssociatedFlows, cookie)
1471 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301472 vs.ServiceLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301473 logger.Debugw(ctx, "Service Flow Remove Failure Notification", log.Fields{"uniPort": vs.Port, "Cookie": cookie, "Service": vs.Name, "ErrorCode": errorCode, "ErrorReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05301474
1475 vs.triggerServiceFailureInd(errorCode, errReason)
Akash Sonief452f12024-12-12 18:20:28 +05301476 // Get the service from application before proceeding to delete, as the service might have been activated
1477 // by the time the flow removal response is received from SB
1478 svc := GetApplication().GetService(vs.Name)
1479 if svc != nil {
1480 svc.CheckAndDeleteService(cntx)
1481 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301482}
1483
1484func (vs *VoltService) triggerServiceFailureInd(errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301485 logger.Debugw(ctx, "Trigger Service Failure Ind", log.Fields{"Service": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301486 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1487 if err != nil {
1488 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1489 return
1490 } else if device.State != controller.DeviceStateUP {
1491 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1492 return
1493 }
1494}
1495
1496// RestoreSvcsFromDb read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301497func (va *VoltApplication) RestoreSvcsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301498 // VNETS must be learnt first
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301499 logger.Debug(ctx, "Restore Svcs From Db")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301500 vss, _ := db.GetServices(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301501 for _, vs := range vss {
1502 b, ok := vs.Value.([]byte)
1503 if !ok {
1504 logger.Warn(ctx, "The value type is not []byte")
1505 continue
1506 }
1507 var vvs VoltService
1508 err := json.Unmarshal(b, &vvs)
1509 if err != nil {
1510 logger.Warn(ctx, "Unmarshal of VNET failed")
1511 continue
1512 }
1513 logger.Debugw(ctx, "Retrieved Service", log.Fields{"Service": vvs.VoltServiceCfg})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301514 if err := va.AddService(cntx, vvs.VoltServiceCfg, &vvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301515 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": vvs.Name, "Error": err})
1516 }
1517
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301518 if vvs.VoltServiceOper.DeactivateInProgress {
Akash Sonief452f12024-12-12 18:20:28 +05301519 va.ServicesToDeactivate.Store(vvs.VoltServiceCfg.Name, true)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301520 logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
1521 }
1522
Naveen Sampath04696f72022-06-13 15:19:14 +05301523 if vvs.VoltServiceOper.DeleteInProgress {
Akash Sonief452f12024-12-12 18:20:28 +05301524 va.ServicesToDelete.Store(vvs.VoltServiceCfg.Name, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301525 logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
1526 }
1527 }
1528}
1529
1530// GetService to get service
1531func (va *VoltApplication) GetService(name string) *VoltService {
1532 if vs, ok := va.ServiceByName.Load(name); ok {
1533 return vs.(*VoltService)
1534 }
1535 return nil
1536}
1537
1538// GetCircuitID to get circuit id
1539func (vs *VoltService) GetCircuitID() []byte {
1540 return []byte(vs.CircuitID)
1541}
1542
1543// GetRemoteID to get remote id
1544func (vs *VoltService) GetRemoteID() []byte {
1545 return []byte(vs.RemoteID)
1546}
1547
1548// IPAssigned to check if ip is assigned
1549func (vs *VoltService) IPAssigned() bool {
1550 if vs.Ipv4Addr != nil && !vs.Ipv4Addr.Equal(net.ParseIP("0.0.0.0")) {
1551 return true
1552 } else if vs.Ipv6Addr != nil && !vs.Ipv6Addr.Equal(net.ParseIP("0:0:0:0:0:0:0:0")) {
1553 return true
1554 }
1555 return false
1556}
1557
1558// GetServiceNameFromCookie to get service name from cookie
1559func (va *VoltApplication) GetServiceNameFromCookie(cookie uint64, portName string, pbit uint8, device string, tableMetadata uint64) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301560 logger.Debugw(ctx, "Get Service Name From Cookie", log.Fields{"Cookie": cookie, "PortName": portName, "Pbit": pbit, "Device": device, "TableMetadata": tableMetadata})
Naveen Sampath04696f72022-06-13 15:19:14 +05301561 var vlan uint64
1562 vlanControl := (tableMetadata >> 32) & 0xF
1563
1564 if vlanControl == uint64(OLTCVlanOLTSVlan) {
1565 // Fetching UniVlan for vlanControl OLTCVLANOLTSVLAN
1566 vlan = (tableMetadata >> 16) & 0xFFFF
1567 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301568 // Fetching CVlan for other vlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301569 vlan = cookie >> 52
1570 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301571 logger.Debugw(ctx, "Configured Params", log.Fields{"VlanControl": vlanControl, "vlan": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301572 var vlans []of.VlanType
1573 vlans = append(vlans, of.VlanType(vlan))
1574 service := GetApplication().GetServiceFromCvlan(device, portName, vlans, uint8(pbit))
1575 if nil != service {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301576 logger.Infow(ctx, "Service Found for", log.Fields{"serviceName": service.Name, "portName": portName, "ctag": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301577 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301578 logger.Warnw(ctx, "No Service for", log.Fields{"portName": portName, "ctag": vlan, "Pbit": pbit, "device": device, "VlanControl": vlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +05301579 }
1580 return service
1581}
1582
vinokuma926cb3e2023-03-29 11:41:06 +05301583// MigrateServicesReqStatus - update vnet request status
Naveen Sampath04696f72022-06-13 15:19:14 +05301584type MigrateServicesReqStatus string
1585
1586const (
vinokuma926cb3e2023-03-29 11:41:06 +05301587 // MigrateSrvsReqInit constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301588 MigrateSrvsReqInit MigrateServicesReqStatus = "Init"
vinokuma926cb3e2023-03-29 11:41:06 +05301589 // MigrateSrvsReqDeactTriggered constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301590 MigrateSrvsReqDeactTriggered MigrateServicesReqStatus = "Profiles Deactivated"
vinokuma926cb3e2023-03-29 11:41:06 +05301591 // MigrateSrvsReqCompleted constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301592 MigrateSrvsReqCompleted MigrateServicesReqStatus = "Update Complete"
1593)
1594
vinokuma926cb3e2023-03-29 11:41:06 +05301595// MigrateServicesRequest - update vnet request params
Naveen Sampath04696f72022-06-13 15:19:14 +05301596type MigrateServicesRequest struct {
1597 ID string
1598 OldVnetID string
1599 NewVnetID string
1600 ServicesList map[string]bool
1601 DeviceID string
1602 Status MigrateServicesReqStatus
1603 MigrateServicesLock sync.RWMutex
1604}
1605
1606func newMigrateServicesRequest(id string, oldVnetID string, newVnetID string, serviceMap map[string]bool, deviceID string) *MigrateServicesRequest {
Naveen Sampath04696f72022-06-13 15:19:14 +05301607 var msr MigrateServicesRequest
1608 msr.OldVnetID = oldVnetID
1609 msr.NewVnetID = newVnetID
1610 msr.ID = id
1611 msr.ServicesList = serviceMap
1612 msr.DeviceID = deviceID
1613 msr.Status = MigrateSrvsReqInit
1614 return &msr
1615}
1616
vinokuma926cb3e2023-03-29 11:41:06 +05301617// GetMsrKey - generates migrate service request key
Naveen Sampath04696f72022-06-13 15:19:14 +05301618func (msr *MigrateServicesRequest) GetMsrKey() string {
1619 return msr.OldVnetID + "-" + msr.ID
1620}
1621
1622// //isRequestComplete - return if all request has been processed and completed
1623// // RequestProcessed indicates that all the profile de-activation has been triggered
1624// // And the associated profiles indicates the profiles awaiting results
1625// func (msr *MigrateServicesRequest) isRequestComplete() bool {
1626// //return edr.RequestProcessed && (len(edr.AssociatedProfiles) == 0)
1627// return (len(edr.AssociatedProfiles) == 0)
1628// }
1629
vinokuma926cb3e2023-03-29 11:41:06 +05301630// WriteToDB - writes the udpate vnet request details ot DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301631func (msr *MigrateServicesRequest) WriteToDB(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301632 logger.Debugw(ctx, "Adding Migrate Service Request to DB", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID, "Device": msr.DeviceID, "RequestID": msr.ID, "ServiceCount": len(msr.ServicesList)})
1633 if b, err := json.Marshal(msr); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301634 if err = db.PutMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey(), string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301635 logger.Warnw(ctx, "PutMigrateServicesReq Failed", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID,
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05301636 "Device": msr.DeviceID, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301637 }
1638 }
1639}
1640
vinokuma926cb3e2023-03-29 11:41:06 +05301641// MigrateServices - updated vnet profile for services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301642func (va *VoltApplication) MigrateServices(cntx context.Context, serialNum string, reqID string, oldVnetID, newVnetID string, serviceList []string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301643 logger.Debugw(ctx, "Migrate Serviec Request Received", log.Fields{"SerialNum": serialNum, "RequestID": reqID, "OldVnet": oldVnetID, "NewVnet": newVnetID, "ServiceList": serviceList})
Naveen Sampath04696f72022-06-13 15:19:14 +05301644 if _, ok := va.VnetsByName.Load(oldVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301645 return errors.New("old vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301646 }
1647 if _, ok := va.VnetsByName.Load(newVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301648 return errors.New("new vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301649 }
1650
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301651 d, _ := va.GetDeviceBySerialNo(serialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301652 if d == nil {
1653 logger.Errorw(ctx, "Error Getting Device", log.Fields{"SerialNum": serialNum})
1654 return errorCodes.ErrDeviceNotFound
1655 }
1656
1657 serviceMap := make(map[string]bool)
1658
1659 for _, service := range serviceList {
1660 serviceMap[service] = false
1661 }
1662 msr := newMigrateServicesRequest(reqID, oldVnetID, newVnetID, serviceMap, d.Name)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301663 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301664
1665 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301666 go msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301667 return nil
1668}
1669
vinokuma926cb3e2023-03-29 11:41:06 +05301670// ProcessMigrateServicesProfRequest - collects all associated profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301671func (msr *MigrateServicesRequest) ProcessMigrateServicesProfRequest(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301672 logger.Debug(ctx, "Process Migrate Services Prof Request")
Naveen Sampath04696f72022-06-13 15:19:14 +05301673 va := GetApplication()
1674 for srv, processed := range msr.ServicesList {
vinokuma926cb3e2023-03-29 11:41:06 +05301675 // Indicates new service is already created and only deletion of old one is pending
Naveen Sampath04696f72022-06-13 15:19:14 +05301676 if processed {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301677 va.DelService(cntx, srv, true, nil, true)
1678 msr.serviceMigrated(cntx, srv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301679 continue
1680 }
1681
1682 logger.Infow(ctx, "Migrate Service Triggering", log.Fields{"Service": srv})
1683 if vsIntf, ok := va.ServiceByName.Load(srv); ok {
1684 vs := vsIntf.(*VoltService)
1685 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1686 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301687 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301688 continue
1689 }
1690 logger.Infow(ctx, "Migrating Service", log.Fields{"Service": vs.Name, "UsFlowApplied": vs.UsHSIAFlowsApplied})
1691 vpv.Blocked = true
1692
1693 // setDeactTrigger := func(key, value interface{}) bool {
1694 // vs := value.(*VoltService)
1695 vs.ServiceLock.Lock()
1696 vs.UpdateInProgress = true
1697 metadata := &MigrateServiceMetadata{
1698 NewVnetID: msr.NewVnetID,
1699 RequestID: msr.ID,
1700 }
1701 vs.Metadata = metadata
1702 vs.ServiceLock.Unlock()
1703
vinokuma926cb3e2023-03-29 11:41:06 +05301704 // vpv flows will be removed when last service is removed from it and
Naveen Sampath04696f72022-06-13 15:19:14 +05301705 // new vpv flows will be installed when new service is added
1706 if vs.UsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301707 vpv.DelTrapFlows(cntx)
1708 vs.DelHsiaFlows(cntx)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301709 logger.Infow(ctx, "Remove Service Flows Triggered", log.Fields{"Service": srv, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301710 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301711 vs.updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301712 }
1713 } else {
1714 logger.Warnw(ctx, "Migrate Service Failed: Service Not Found", log.Fields{"Service": srv, "Vnet": msr.OldVnetID})
1715 }
1716 }
1717}
1718
vinokuma926cb3e2023-03-29 11:41:06 +05301719// AddMigratingServices - store msr info to device obj
Naveen Sampath04696f72022-06-13 15:19:14 +05301720func (d *VoltDevice) AddMigratingServices(msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301721 logger.Infow(ctx, "Add Migrating Services", log.Fields{"Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301722 var msrMap *util.ConcurrentMap
1723 if msrMapIntf, ok := d.MigratingServices.Get(msr.OldVnetID); !ok {
1724 msrMap = util.NewConcurrentMap()
1725 } else {
1726 msrMap = msrMapIntf.(*util.ConcurrentMap)
1727 }
1728
1729 msrMap.Set(msr.ID, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301730 logger.Debugw(ctx, "1: MsrListLen", log.Fields{"Len": msrMap.Length(), "Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301731
1732 d.MigratingServices.Set(msr.OldVnetID, msrMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301733 logger.Debugw(ctx, "1: DeviceMsr", log.Fields{"Device": d.Name, "Vnet": msr.OldVnetID, "Len": d.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301734}
1735
vinokuma926cb3e2023-03-29 11:41:06 +05301736// getMigrateServicesRequest - fetches msr info from device
Naveen Sampath04696f72022-06-13 15:19:14 +05301737func (va *VoltApplication) getMigrateServicesRequest(deviceID string, oldVnetID string, requestID string) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301738 logger.Debugw(ctx, "Get Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301739 if vd := va.GetDevice(deviceID); vd != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301740 logger.Debugw(ctx, "2: DeviceMsr", log.Fields{"Device": deviceID, "Vnet": oldVnetID, "Len": vd.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301741 if msrListIntf, ok := vd.MigratingServices.Get(oldVnetID); ok {
1742 msrList := msrListIntf.(*util.ConcurrentMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301743 logger.Debugw(ctx, "2: MsrListLen", log.Fields{"Len": msrList.Length(), "Vnet": oldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301744 if msrObj, ok := msrList.Get(requestID); ok {
1745 return msrObj.(*MigrateServicesRequest)
1746 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301747 }
1748 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301749 logger.Warnw(ctx, "Device Not Found", log.Fields{"DeviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301750 return nil
1751}
1752
vinokuma926cb3e2023-03-29 11:41:06 +05301753// updateMigrateServicesRequest - Updates the device with updated msr
Naveen Sampath04696f72022-06-13 15:19:14 +05301754func (va *VoltApplication) updateMigrateServicesRequest(deviceID string, oldVnetID string, requestID string, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301755 logger.Debugw(ctx, "Update Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301756 if vd := va.GetDevice(deviceID); vd != nil {
1757 if msrList, ok := vd.MigratingServices.Get(oldVnetID); ok {
1758 if _, ok := msrList.(*util.ConcurrentMap).Get(requestID); ok {
1759 msrList.(*util.ConcurrentMap).Set(requestID, msr)
1760 }
1761 }
1762 }
1763}
1764
vinokuma926cb3e2023-03-29 11:41:06 +05301765// updateVnetProfile - Called on flow process completion
1766// Removes old service and creates new VPV & service with updated vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301767func (vs *VoltService) updateVnetProfile(cntx context.Context, deviceID string) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301768 logger.Infow(ctx, "Update Vnet Profile Triggering", log.Fields{"Service": vs.Name, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301769
1770 nvs := VoltService{}
1771 nvs.VoltServiceCfg = vs.VoltServiceCfg
1772 nvs.Device = vs.Device
1773 nvs.Ipv4Addr = vs.Ipv4Addr
1774 nvs.Ipv6Addr = vs.Ipv6Addr
1775 nvs.UsMeterID = vs.UsMeterID
1776 nvs.DsMeterID = vs.DsMeterID
1777 nvs.AggDsMeterID = vs.AggDsMeterID
1778 nvs.UsHSIAFlowsApplied = vs.UsHSIAFlowsApplied
1779 nvs.DsHSIAFlowsApplied = vs.DsHSIAFlowsApplied
1780 nvs.UsDhcpFlowsApplied = vs.UsDhcpFlowsApplied
1781 nvs.DsDhcpFlowsApplied = vs.DsDhcpFlowsApplied
1782 nvs.IgmpFlowsApplied = vs.IgmpFlowsApplied
1783 nvs.Icmpv6FlowsApplied = vs.Icmpv6FlowsApplied
1784 nvs.PendingFlows = vs.PendingFlows
1785 nvs.AssociatedFlows = vs.AssociatedFlows
1786 nvs.DeleteInProgress = vs.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301787 nvs.DeactivateInProgress = vs.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301788 nvs.ForceDelete = vs.ForceDelete
1789 nvs.BwAvailInfo = vs.BwAvailInfo
1790 nvs.UpdateInProgress = vs.UpdateInProgress
1791
1792 if nvs.DeleteInProgress {
1793 logger.Warnw(ctx, "Skipping Service Migration. Service Delete in Progress", log.Fields{"Device": deviceID, "Service": vs.Name, "Vnet": vs.VnetID})
1794 return
1795 }
1796
1797 metadata := vs.Metadata.(*MigrateServiceMetadata)
1798 oldVnetID := vs.VnetID
Naveen Sampath04696f72022-06-13 15:19:14 +05301799 oldSrvName := vs.Name
1800
1801 if metadata == nil || metadata.NewVnetID == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301802 logger.Warnw(ctx, "Migrate Service Metadata not found. Dropping vnet profile update request", log.Fields{"Service": vs.Name, "Vnet": vs.VnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301803 return
1804 }
1805
vinokuma926cb3e2023-03-29 11:41:06 +05301806 nvs.VnetID = metadata.NewVnetID
1807 id := metadata.RequestID
1808
1809 // First add the new service and then only delete the old service
Naveen Sampath04696f72022-06-13 15:19:14 +05301810 // Since if post del service in case of pod crash or reboot, the service data will be lost
1811 va := GetApplication()
1812 msr := va.getMigrateServicesRequest(deviceID, oldVnetID, id)
1813 vnets := strings.Split(metadata.NewVnetID, "-")
1814 svlan, _ := strconv.Atoi(vnets[0])
1815 nvs.SVlan = of.VlanType(svlan)
1816 nvs.UpdateInProgress = false
1817 nvs.Metadata = nil
1818 nvs.Trigger = ServiceVlanUpdate
1819
1820 svcName := vs.Port + "-" + strconv.FormatUint(uint64(nvs.SVlan), 10) + "-"
1821 svcName = svcName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1822 nvs.Name = svcName + strconv.FormatUint(uint64(vs.TechProfileID), 10)
1823
vinokuma926cb3e2023-03-29 11:41:06 +05301824 // TODO:Nav Pass a copy, not the pointer
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301825 logger.Debugw(ctx, "Add New Service Triggering", log.Fields{"Service": nvs.Name, "US": nvs.UsHSIAFlowsApplied, "DS": nvs.DsHSIAFlowsApplied, "DelFlag": nvs.DeleteInProgress})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301826 if err := va.AddService(cntx, nvs.VoltServiceCfg, &nvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301827 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": nvs.Name, "Error": err})
1828 }
1829 logger.Infow(ctx, "Add New Service Triggered", log.Fields{"Service": nvs.Name, "US": nvs.UsHSIAFlowsApplied, "DS": nvs.DsHSIAFlowsApplied, "DelFlag": nvs.DeleteInProgress})
1830
1831 msr.ServicesList[oldSrvName] = true
1832 va.updateMigrateServicesRequest(deviceID, oldVnetID, id, msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301833 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301834
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301835 logger.Debugw(ctx, "Del Old Service Triggering", log.Fields{"Service": oldSrvName, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied, "DelFlag": vs.DeleteInProgress})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301836 va.DelService(cntx, oldSrvName, true, nil, true)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301837 logger.Debugw(ctx, "Del Old Service Triggered", log.Fields{"Service": oldSrvName, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied, "DelFlag": vs.DeleteInProgress})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301838 msr.serviceMigrated(cntx, oldSrvName)
Naveen Sampath04696f72022-06-13 15:19:14 +05301839}
1840
vinokuma926cb3e2023-03-29 11:41:06 +05301841// serviceMigrated - called on successful service updation
Naveen Sampath04696f72022-06-13 15:19:14 +05301842// Removes the service entry from servicelist and deletes the request on process completion
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301843func (msr *MigrateServicesRequest) serviceMigrated(cntx context.Context, serviceName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301844 logger.Infow(ctx, "Service Migrated", log.Fields{"ServiceName": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05301845 msr.MigrateServicesLock.Lock()
1846 defer msr.MigrateServicesLock.Unlock()
1847
1848 delete(msr.ServicesList, serviceName)
1849
1850 if len(msr.ServicesList) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301851 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301852 return
1853 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301854 msr.WriteToDB(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +05301855 // TODO:Nav - Need for any Response to SubMgr?
Naveen Sampath04696f72022-06-13 15:19:14 +05301856}
1857
vinokuma926cb3e2023-03-29 11:41:06 +05301858// TriggerPendingMigrateServicesReq - trigger pending service request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301859func (va *VoltApplication) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
1860 va.FetchAndProcessAllMigrateServicesReq(cntx, device, storeAndProcessMigrateSrvRequest)
Naveen Sampath04696f72022-06-13 15:19:14 +05301861}
1862
vinokuma926cb3e2023-03-29 11:41:06 +05301863// FetchAndProcessAllMigrateServicesReq - fetch all pending migrate services req from DB and process based on provided func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301864func (va *VoltApplication) FetchAndProcessAllMigrateServicesReq(cntx context.Context, device string, msrAction func(context.Context, *MigrateServicesRequest)) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301865 logger.Infow(ctx, "Fetch all pending migrate services req from DB and process based on provided func", log.Fields{"Device": device})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301866 msrList, _ := db.GetAllMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301867 for _, msr := range msrList {
1868 b, ok := msr.Value.([]byte)
1869 if !ok {
1870 logger.Warn(ctx, "The value type is not []byte")
1871 continue
1872 }
1873 msr := va.createMigrateServicesFromString(b)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301874 msrAction(cntx, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301875 logger.Debugw(ctx, "Triggering Pending Migrate Services Req", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID, "Device": device, "PendingProfiles": len(msr.ServicesList)})
Naveen Sampath04696f72022-06-13 15:19:14 +05301876 }
1877}
1878
1879// createMigrateServicesFromString to create Service from string
1880func (va *VoltApplication) createMigrateServicesFromString(b []byte) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301881 logger.Info(ctx, "Create Migrate Services From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05301882 var msr MigrateServicesRequest
1883 if err := json.Unmarshal(b, &msr); err == nil {
1884 logger.Debugw(ctx, "Adding Migrate Services Request From Db", log.Fields{"Vlan": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301885 } else {
1886 logger.Warn(ctx, "Unmarshal failed")
1887 }
1888 return &msr
1889}
1890
vinokuma926cb3e2023-03-29 11:41:06 +05301891// storeAndProcessMigrateSrvRequest - stores the msr info in device obj and triggers req
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301892func storeAndProcessMigrateSrvRequest(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301893 logger.Infow(ctx, "Store And Process Migrate Srv Request", log.Fields{"MsrID": msr.DeviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301894 d := GetApplication().GetDevice(msr.DeviceID)
1895 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301896 msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301897}
1898
vinokuma926cb3e2023-03-29 11:41:06 +05301899// forceUpdateAllServices - force udpate services with new vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301900func forceUpdateAllServices(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301901 logger.Infow(ctx, "Force udpate services with new vnet profile", log.Fields{"MsrID": msr.NewVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301902 for srv := range msr.ServicesList {
1903 if vsIntf, ok := GetApplication().ServiceByName.Load(srv); ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301904 vsIntf.(*VoltService).updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301905 }
1906 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301907 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301908}
1909
vinokuma926cb3e2023-03-29 11:41:06 +05301910// nolint: gocyclo
1911// DeepEqualServicecfg - checks if the given service cfgs are same
Naveen Sampath04696f72022-06-13 15:19:14 +05301912func (va *VoltApplication) DeepEqualServicecfg(evs *VoltServiceCfg, nvs *VoltServiceCfg) bool {
1913 if nvs.Name != evs.Name {
1914 return false
1915 }
1916 if nvs.UniVlan != evs.UniVlan {
1917 return false
1918 }
1919 if nvs.CVlan != evs.CVlan {
1920 return false
1921 }
1922 if nvs.SVlan != evs.SVlan {
1923 return false
1924 }
1925 if nvs.SVlanTpid != 0 && nvs.SVlanTpid != evs.SVlanTpid {
1926 return false
1927 }
1928 if !util.IsPbitSliceSame(nvs.Pbits, evs.Pbits) {
1929 return false
1930 }
1931 if !reflect.DeepEqual(nvs.DsRemarkPbitsMap, evs.DsRemarkPbitsMap) {
1932 return false
1933 }
1934 if nvs.TechProfileID != evs.TechProfileID {
1935 return false
1936 }
1937 if nvs.CircuitID != evs.CircuitID {
1938 return false
1939 }
1940 if !bytes.Equal(nvs.RemoteID, evs.RemoteID) {
1941 return false
1942 }
1943 if nvs.Port != evs.Port {
1944 return false
1945 }
1946 if nvs.PonPort != evs.PonPort {
1947 return false
1948 }
1949 if evs.MacLearning == MacLearningNone && !util.MacAddrsMatch(nvs.MacAddr, evs.MacAddr) {
1950 return false
1951 }
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05301952 if nvs.IsOption82Enabled != evs.IsOption82Enabled {
Naveen Sampath04696f72022-06-13 15:19:14 +05301953 return false
1954 }
1955 if nvs.IgmpEnabled != evs.IgmpEnabled {
1956 return false
1957 }
1958 if nvs.McastService != evs.McastService {
1959 return false
1960 }
1961 if nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification {
1962 return false
1963 }
1964 if nvs.UsMeterProfile != evs.UsMeterProfile {
1965 return false
1966 }
1967 if nvs.DsMeterProfile != evs.DsMeterProfile {
1968 return false
1969 }
1970 if nvs.AggDsMeterProfile != evs.AggDsMeterProfile {
1971 return false
1972 }
1973 if nvs.VnetID != evs.VnetID {
1974 return false
1975 }
1976 if nvs.MvlanProfileName != evs.MvlanProfileName {
1977 return false
1978 }
1979 if nvs.RemoteIDType != evs.RemoteIDType {
1980 return false
1981 }
1982 if nvs.SchedID != evs.SchedID {
1983 return false
1984 }
1985 if nvs.AllowTransparent != evs.AllowTransparent {
1986 return false
1987 }
1988 if nvs.EnableMulticastKPI != evs.EnableMulticastKPI {
1989 return false
1990 }
1991 if nvs.DataRateAttr != evs.DataRateAttr {
1992 return false
1993 }
1994 if nvs.MinDataRateUs != evs.MinDataRateUs {
1995 return false
1996 }
1997 if nvs.MinDataRateDs != evs.MinDataRateDs {
1998 return false
1999 }
2000 if nvs.MaxDataRateUs != evs.MaxDataRateUs {
2001 return false
2002 }
2003 if nvs.MaxDataRateDs != evs.MaxDataRateDs {
2004 return false
2005 }
2006
2007 return true
2008}
2009
vinokuma926cb3e2023-03-29 11:41:06 +05302010// TriggerAssociatedFlowDelete - re-trigger service flow delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302011func (vs *VoltService) TriggerAssociatedFlowDelete(cntx context.Context) bool {
vinokuma926cb3e2023-03-29 11:41:06 +05302012 // Clear the Flows flag if already set
2013 // This case happens only in case of some race condition
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302014 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": vs.Device, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302015 if vs.UsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302016 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302017 logger.Warnw(ctx, "DelUsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302018 }
2019 }
2020
2021 if vs.DsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302022 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302023 logger.Warnw(ctx, "DelDsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302024 }
2025 }
2026
2027 vs.ServiceLock.Lock()
2028 cookieList := []uint64{}
2029 for cookie := range vs.AssociatedFlows {
2030 cookieList = append(cookieList, convertToUInt64(cookie))
2031 }
2032 vs.ServiceLock.Unlock()
2033
2034 if len(cookieList) == 0 {
2035 return false
2036 }
2037
vinokuma926cb3e2023-03-29 11:41:06 +05302038 // Trigger Flow Delete
Naveen Sampath04696f72022-06-13 15:19:14 +05302039 for _, cookie := range cookieList {
2040 if vd := GetApplication().GetDevice(vs.Device); vd != nil {
2041 flow := &of.VoltFlow{}
2042 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2043 subFlow := of.NewVoltSubFlow()
2044 subFlow.Cookie = cookie
2045 flow.SubFlows[cookie] = subFlow
2046 logger.Infow(ctx, "Retriggering Service Delete Flow", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302047 if err := vs.DelFlows(cntx, vd, flow, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302048 logger.Warnw(ctx, "DelFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302049 }
2050 }
2051 }
2052 return true
2053}
2054
vinokuma926cb3e2023-03-29 11:41:06 +05302055// triggerServiceInProgressInd - Indication is generated when Service is not provisioned after add serviec req from NB
Naveen Sampath04696f72022-06-13 15:19:14 +05302056func (vs *VoltService) triggerServiceInProgressInd() {
2057}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302058
vinokuma926cb3e2023-03-29 11:41:06 +05302059// JSONMarshal wrapper function for json Marshal VoltService
2060func (vs *VoltService) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302061 return json.Marshal(VoltService{
2062 VoltServiceCfg: vs.VoltServiceCfg,
2063 VoltServiceOper: VoltServiceOper{
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302064 Device: vs.VoltServiceOper.Device,
2065 Ipv4Addr: vs.VoltServiceOper.Ipv4Addr,
2066 Ipv6Addr: vs.VoltServiceOper.Ipv6Addr,
2067 UsMeterID: vs.VoltServiceOper.UsMeterID,
2068 DsMeterID: vs.VoltServiceOper.DsMeterID,
2069 AggDsMeterID: vs.VoltServiceOper.AggDsMeterID,
2070 UsHSIAFlowsApplied: vs.VoltServiceOper.UsHSIAFlowsApplied,
2071 DsHSIAFlowsApplied: vs.VoltServiceOper.DsHSIAFlowsApplied,
2072 UsDhcpFlowsApplied: vs.VoltServiceOper.UsDhcpFlowsApplied,
2073 DsDhcpFlowsApplied: vs.VoltServiceOper.DsDhcpFlowsApplied,
2074 IgmpFlowsApplied: vs.VoltServiceOper.IgmpFlowsApplied,
2075 Icmpv6FlowsApplied: vs.VoltServiceOper.Icmpv6FlowsApplied,
2076 PendingFlows: vs.VoltServiceOper.PendingFlows,
2077 AssociatedFlows: vs.VoltServiceOper.AssociatedFlows,
2078 DeleteInProgress: vs.VoltServiceOper.DeleteInProgress,
2079 DeactivateInProgress: vs.VoltServiceOper.DeactivateInProgress,
2080 ForceDelete: vs.VoltServiceOper.ForceDelete,
2081 BwAvailInfo: vs.VoltServiceOper.BwAvailInfo,
2082 UpdateInProgress: vs.VoltServiceOper.UpdateInProgress,
2083 Metadata: vs.VoltServiceOper.Metadata,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302084 },
2085 })
2086}
Tinoj Josephec742f62022-09-29 19:11:10 +05302087
2088// GetProgrammedSubscribers to get list of programmed subscribers
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302089func (va *VoltApplication) GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302090 var svcList []*VoltService
2091 logger.Infow(ctx, "GetProgrammedSubscribers Request ", log.Fields{"Device": deviceID, "Port": portNo})
2092 va.ServiceByName.Range(func(key, value interface{}) bool {
2093 vs := value.(*VoltService)
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302094 if len(deviceID) > 0 {
2095 if len(portNo) > 0 {
Tinoj Josephec742f62022-09-29 19:11:10 +05302096 if deviceID == vs.Device && portNo == vs.Port {
2097 svcList = append(svcList, vs)
2098 }
2099 } else {
2100 if deviceID == vs.Device {
2101 svcList = append(svcList, vs)
2102 }
2103 }
2104 } else {
2105 svcList = append(svcList, vs)
2106 }
2107 return true
2108 })
2109 return svcList, nil
2110}
2111
Akash Soni634d9bf2023-07-10 12:11:10 +05302112type FlowProvisionStatus struct {
2113 FlowProvisionStatus string
2114}
2115
2116// GetFlowProvisionStatus to get status of the subscriber and flow provisioned in controller
Akash Soni3c391e72023-08-16 12:21:33 +05302117func (va *VoltApplication) GetFlowProvisionStatus(portNo string) FlowProvisionStatus {
Akash Soni634d9bf2023-07-10 12:11:10 +05302118 logger.Infow(ctx, "GetFlowProvisionStatus Request ", log.Fields{"Port": portNo})
2119 flowProvisionStatus := FlowProvisionStatus{}
Akash Soni3c391e72023-08-16 12:21:33 +05302120 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
Akash Soni634d9bf2023-07-10 12:11:10 +05302121 va.ServiceByName.Range(func(key, value interface{}) bool {
2122 vs := value.(*VoltService)
2123 logger.Debugw(ctx, "Volt Service ", log.Fields{"VS": vs})
Akash Soni3c391e72023-08-16 12:21:33 +05302124 if portNo == vs.Port {
2125 if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() == 0 {
2126 flowProvisionStatus.FlowProvisionStatus = ALL_FLOWS_PROVISIONED
2127 return false
2128 } else if !vs.IsActivated {
2129 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_DISABLED_IN_CONTROLLER
2130 return false
2131 } else if !vs.DsHSIAFlowsApplied && !vs.UsHSIAFlowsApplied {
2132 flowProvisionStatus.FlowProvisionStatus = NO_FLOWS_PROVISIONED
2133 return false
Akash Soni230e6212023-10-16 10:46:07 +05302134 } else if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() > 0 {
Akash Soni3c391e72023-08-16 12:21:33 +05302135 flowProvisionStatus.FlowProvisionStatus = FLOWS_PROVISIONED_PARTIALLY
2136 return false
Akash Soni634d9bf2023-07-10 12:11:10 +05302137 }
2138 }
2139 return true
2140 })
Akash Soni634d9bf2023-07-10 12:11:10 +05302141 return flowProvisionStatus
2142}
2143
2144func (vs *VoltService) LenOfPendingFlows() int {
2145 vs.ServiceLock.RLock()
2146 lth := len(vs.PendingFlows)
2147 vs.ServiceLock.RUnlock()
2148 return lth
2149}
2150
Tinoj Josephec742f62022-09-29 19:11:10 +05302151// ActivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302152func (va *VoltApplication) ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302153 logger.Infow(ctx, "Service Activate Request ", log.Fields{"Device": deviceID, "Port": portNo, "Svaln": sVlan, "Cvlan": cVlan, "TpID": tpID})
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302154 device, err := va.GetDeviceFromPort(portNo)
2155 if err != nil {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302156 // Lets activate the service even though port was not found. We will push the flows once the port is added by voltha
2157 logger.Warnw(ctx, "Couldn't get device for port, continuing with service activation", log.Fields{"Reason": err.Error(), "Port": portNo})
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302158 }
2159 // If device id is not provided check only port number
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302160 if device != nil {
2161 if deviceID == DeviceAny {
2162 deviceID = device.Name
2163 } else if deviceID != device.Name {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302164 err := errorCodes.ErrDeviceNotFound
2165 return fmt.Errorf("wrong device id %s : %w", deviceID, err)
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302166 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302167 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302168 va.ServiceByName.Range(func(key, value interface{}) bool {
2169 vs := value.(*VoltService)
Tinoj Josephec742f62022-09-29 19:11:10 +05302170 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302171 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302172 logger.Warnw(ctx, "Service Activate Request Does not match", log.Fields{"Device": deviceID, "voltService": vs})
Tinoj Josephec742f62022-09-29 19:11:10 +05302173 return true
2174 }
2175 if portNo == vs.Port && !vs.IsActivated {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302176 // Mark the service as activated, so that we can push the flows later when the port is added by voltha
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302177 logger.Debugw(ctx, "Service Activate", log.Fields{"Name": vs.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05302178 vs.IsActivated = true
2179 va.ServiceByName.Store(vs.Name, vs)
2180 vs.WriteToDb(cntx)
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302181
2182 // Push the flows only if the port is already added and we have a valid device
2183 if device != nil {
2184 p := device.GetPort(vs.Port)
2185 if p == nil {
2186 logger.Warnw(ctx, "Wrong device or port", log.Fields{"Device": deviceID, "Port": portNo})
2187 return true
2188 }
2189 // If port is already up send indication to vpv
2190 if p.State == PortStateUp {
2191 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2192 // PortUp call initiates flow addition
2193 vpv.PortUpInd(cntx, device, portNo)
2194 } else {
2195 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2196 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302197 }
2198 }
2199 }
2200 return true
2201 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302202 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302203}
2204
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302205func (vs *VoltService) SetSvcDeactivationFlags(deactivateRsn SvcDeactivateReason) {
2206 vs.DeactivateInProgress = true
2207 vs.IsActivated = false
2208 vs.ServiceDeactivateReason = deactivateRsn
2209}
2210
Tinoj Josephec742f62022-09-29 19:11:10 +05302211// DeactivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302212func (va *VoltApplication) DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Akash Sonief452f12024-12-12 18:20:28 +05302213 logger.Debugw(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo, "Svaln": sVlan, "Cvlan": cVlan, "TpID": tpID})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302214
Tinoj Josephec742f62022-09-29 19:11:10 +05302215 va.ServiceByName.Range(func(key, value interface{}) bool {
2216 vs := value.(*VoltService)
2217 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302218 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302219 logger.Warnw(ctx, "condition not matched", log.Fields{"Device": deviceID, "Port": portNo, "sVlan": sVlan, "cVlan": cVlan, "tpID": tpID})
Tinoj Josephec742f62022-09-29 19:11:10 +05302220 return true
2221 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302222 if portNo == vs.Port && vs.IsActivated {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302223 vs.SetSvcDeactivationFlags(SvcDeacRsn_NB)
Tinoj Josephec742f62022-09-29 19:11:10 +05302224 va.ServiceByName.Store(vs.Name, vs)
2225 vs.WriteToDb(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302226 device, err := va.GetDeviceFromPort(portNo)
2227 if err != nil {
2228 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
2229 // So no error is returned
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302230 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portNo})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302231 return true
2232 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302233 p := device.GetPort(vs.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05302234 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302235 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2236 // Port down call internally deletes all the flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302237 vpv.PortDownInd(cntx, deviceID, portNo, true, false)
Tinoj Josephec742f62022-09-29 19:11:10 +05302238 if vpv.IgmpEnabled {
2239 va.ReceiverDownInd(cntx, deviceID, portNo)
2240 }
2241 } else {
2242 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2243 }
2244 }
Akash Sonief452f12024-12-12 18:20:28 +05302245 vs.DeactivateInProgress = false
2246 va.ServiceByName.Store(vs.Name, vs)
2247 vs.WriteToDb(cntx)
Tinoj Josephec742f62022-09-29 19:11:10 +05302248 }
2249 return true
2250 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302251 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302252}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302253
vinokuma926cb3e2023-03-29 11:41:06 +05302254// GetServicePbit to get first set bit in the pbit map
2255// returns -1 : If configured to match on all pbits
2256// returns 8 : If no pbits are configured
2257// returns first pbit if specific pbit is configured
Tinoj Josephec742f62022-09-29 19:11:10 +05302258func (vs *VoltService) GetServicePbit() int {
2259 if vs.IsPbitExist(of.PbitMatchAll) {
2260 return -1
2261 }
vinokuma926cb3e2023-03-29 11:41:06 +05302262 for pbit := 0; pbit < int(of.PbitMatchNone); pbit++ {
Tinoj Josephec742f62022-09-29 19:11:10 +05302263 if vs.IsPbitExist(of.PbitType(pbit)) {
2264 return pbit
2265 }
2266 }
2267 return int(of.PbitMatchNone)
2268}