blob: ae6f31352bfd91c409852a084d61cfb407443935 [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 Reddy Kankanala105581b2024-09-11 05:20:38 +053085 FlowPushCount map[string]int64 // Tracks the number of flow install/delete failure attempts per cookie in order to throttle flow auditing
86 DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
vinokuma926cb3e2023-03-29 11:41:06 +053087 Name string
Naveen Sampath04696f72022-06-13 15:19:14 +053088 CircuitID string
Naveen Sampath04696f72022-06-13 15:19:14 +053089 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +053090 UsMeterProfile string
91 DsMeterProfile string
92 AggDsMeterProfile string
93 VnetID string
94 MvlanProfileName string
95 RemoteIDType string
Naveen Sampath04696f72022-06-13 15:19:14 +053096 DataRateAttr string
vinokuma926cb3e2023-03-29 11:41:06 +053097 ServiceType string
Akash Sonief452f12024-12-12 18:20:28 +053098 Pbits []of.PbitType
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +053099 RemoteID []byte
100 MacAddr net.HardwareAddr
vinokuma926cb3e2023-03-29 11:41:06 +0530101 Trigger ServiceTrigger
102 MacLearning MacLearningType
Akash Sonief452f12024-12-12 18:20:28 +0530103 ONTEtherTypeClassification int
104 SchedID int
vinokuma926cb3e2023-03-29 11:41:06 +0530105 PonPort uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530106 MinDataRateUs uint32
107 MinDataRateDs uint32
108 MaxDataRateUs uint32
109 MaxDataRateDs uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530110 SVlanTpid layers.EthernetType
Akash Sonief452f12024-12-12 18:20:28 +0530111 TechProfileID uint16
vinokuma926cb3e2023-03-29 11:41:06 +0530112 UniVlan of.VlanType
113 CVlan of.VlanType
114 SVlan of.VlanType
115 UsPonCTagPriority of.PbitType
116 UsPonSTagPriority of.PbitType
117 DsPonSTagPriority of.PbitType
118 DsPonCTagPriority of.PbitType
Akash Sonief452f12024-12-12 18:20:28 +0530119 ServiceDeactivateReason SvcDeactivateReason // Mentions why the service was deactivated
vinokuma926cb3e2023-03-29 11:41:06 +0530120 VlanControl VlanControl
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530121 IsOption82Enabled bool
vinokuma926cb3e2023-03-29 11:41:06 +0530122 IgmpEnabled bool
123 McastService bool
124 AllowTransparent bool
125 EnableMulticastKPI bool
Tinoj Josephec742f62022-09-29 19:11:10 +0530126 IsActivated bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530127}
128
129// VoltServiceOper structure
130type VoltServiceOper struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530131 Metadata interface{}
132 PendingFlows map[string]bool
133 AssociatedFlows map[string]bool
134 BwAvailInfo string
Naveen Sampath04696f72022-06-13 15:19:14 +0530135 //MacLearning bool
136 //MacAddr net.HardwareAddr
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530137 Device string
138 Ipv4Addr net.IP
139 Ipv6Addr net.IP
140 ServiceLock sync.RWMutex `json:"-"`
141 UsMeterID uint32
142 DsMeterID uint32
143 AggDsMeterID uint32
144 UpdateInProgress bool
145 DeleteInProgress bool
146 DeactivateInProgress bool
147 ForceDelete bool
vinokuma926cb3e2023-03-29 11:41:06 +0530148 // Multiservice-Fix
Naveen Sampath04696f72022-06-13 15:19:14 +0530149 UsHSIAFlowsApplied bool
150 DsHSIAFlowsApplied bool
151 UsDhcpFlowsApplied bool
152 DsDhcpFlowsApplied bool
153 IgmpFlowsApplied bool
154 Icmpv6FlowsApplied bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530155}
156
157// VoltService structure
158type VoltService struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530159 Version string
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530160 VoltServiceOper
vinokuma926cb3e2023-03-29 11:41:06 +0530161 VoltServiceCfg
Naveen Sampath04696f72022-06-13 15:19:14 +0530162}
163
vinokuma926cb3e2023-03-29 11:41:06 +0530164// ServiceTrigger - Service activation trigger
Naveen Sampath04696f72022-06-13 15:19:14 +0530165type ServiceTrigger int
166
167const (
vinokuma926cb3e2023-03-29 11:41:06 +0530168 // NBActivate - Service added due to NB Action
Naveen Sampath04696f72022-06-13 15:19:14 +0530169 NBActivate ServiceTrigger = 0
vinokuma926cb3e2023-03-29 11:41:06 +0530170 // ServiceVlanUpdate - Service added due to Svlan Update
Naveen Sampath04696f72022-06-13 15:19:14 +0530171 ServiceVlanUpdate ServiceTrigger = 1
172)
173
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530174// SvcDeactivateReason - Reason for service deactivation
175type SvcDeactivateReason uint8
176
177const (
178 // Service deactivated reason - none
179 SvcDeacRsn_None SvcDeactivateReason = 0
180 // Service deactivate reason - NB
181 SvcDeacRsn_NB SvcDeactivateReason = 1
182 // Service deactivate reason - Controller
183 SvcDeacRsn_Controller SvcDeactivateReason = 2
184)
185
Naveen Sampath04696f72022-06-13 15:19:14 +0530186// AppMutexes structure
187type AppMutexes struct {
188 ServiceDataMutex sync.Mutex `json:"-"`
189 VnetMutex sync.Mutex `json:"-"`
190}
191
vinokuma926cb3e2023-03-29 11:41:06 +0530192// MigrateServiceMetadata - migrate services request metadata
Naveen Sampath04696f72022-06-13 15:19:14 +0530193type MigrateServiceMetadata struct {
194 NewVnetID string
195 RequestID string
196}
197
198// AppMutex variable
199var AppMutex AppMutexes
200
201// NewVoltService for constructor for volt service
202func NewVoltService(cfg *VoltServiceCfg) *VoltService {
203 var vs VoltService
204 vs.VoltServiceCfg = *cfg
205 vs.UsHSIAFlowsApplied = false
206 vs.DsHSIAFlowsApplied = false
207 vs.DeleteInProgress = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530208 vs.DeactivateInProgress = false
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530209 vs.ServiceDeactivateReason = SvcDeacRsn_None
Naveen Sampath04696f72022-06-13 15:19:14 +0530210 //vs.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Sridhar Ravindra3ec14232024-01-01 19:11:48 +0530211
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530212 vs.IsOption82Enabled = cfg.IsOption82Enabled
Naveen Sampath04696f72022-06-13 15:19:14 +0530213 vs.MacAddr = cfg.MacAddr
214 vs.Ipv4Addr = net.ParseIP("0.0.0.0")
215 vs.Ipv6Addr = net.ParseIP("::")
216 vs.PendingFlows = make(map[string]bool)
217 vs.AssociatedFlows = make(map[string]bool)
Akash Reddy Kankanala105581b2024-09-11 05:20:38 +0530218 vs.FlowPushCount = make(map[string]int64)
Naveen Sampath04696f72022-06-13 15:19:14 +0530219 return &vs
220}
221
222// WriteToDb commit a service to the DB if service delete is not in-progress
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530223func (vs *VoltService) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530224 vs.ServiceLock.RLock()
225 defer vs.ServiceLock.RUnlock()
226
227 if vs.DeleteInProgress {
228 logger.Warnw(ctx, "Skipping Redis Update for Service, Service delete in progress", log.Fields{"Service": vs.Name})
229 return
230 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530231 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530232}
233
vinokuma926cb3e2023-03-29 11:41:06 +0530234// ForceWriteToDb force commit a service to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530235func (vs *VoltService) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530236 b, err := json.Marshal(vs)
237
238 if err != nil {
239 logger.Errorw(ctx, "Json Marshal Failed for Service", log.Fields{"Service": vs.Name})
240 return
241 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530242 if err1 := db.PutService(cntx, vs.Name, string(b)); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530243 logger.Errorw(ctx, "DB write oper failed for Service", log.Fields{"Service": vs.Name})
244 }
245}
246
247// isDataRateAttrPresent to check if data attribute is present
248func (vs *VoltService) isDataRateAttrPresent() bool {
249 return vs.DataRateAttr == DSLAttrEnabled
250}
251
252// DelFromDb delete a service from DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530253func (vs *VoltService) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530254 logger.Debugw(ctx, "Deleting Service from DB", log.Fields{"Name": vs.Name})
vinokuma926cb3e2023-03-29 11:41:06 +0530255 // TODO - Need to understand and delete the second call
256 // Calling twice has worked though don't know why
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530257 _ = db.DelService(cntx, vs.Name)
258 _ = db.DelService(cntx, vs.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530259}
260
261// MatchesVlans find the service that matches the VLANs. In this case it is
262// purely based on CVLAN. The CVLAN can sufficiently be used to
263// match a service
264func (vs *VoltService) MatchesVlans(vlans []of.VlanType) bool {
265 if len(vlans) != 1 {
266 return false
267 }
268
269 if vlans[0] == vs.CVlan {
270 return true
271 }
272 return false
273}
274
275// MatchesPbits allows matching a service to a pbit. This is used
276// to search for a service matching the pbits, typically to identify
277// attributes for other flows such as DHCP, IGMP, etc.
278func (vs *VoltService) MatchesPbits(pbits []of.PbitType) bool {
279 for _, pbit := range pbits {
280 for _, pb := range vs.Pbits {
281 if pb == pbit {
282 return true
283 }
284 }
285 }
286 return false
287}
288
289// IsPbitExist allows matching a service to a pbit. This is used
290// to search for a service matching the pbit
291func (vs *VoltService) IsPbitExist(pbit of.PbitType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530292 logger.Debugw(ctx, "Request for IsPbitExist", log.Fields{"pbit": pbit})
Naveen Sampath04696f72022-06-13 15:19:14 +0530293 for _, pb := range vs.Pbits {
294 if pb == pbit {
295 return true
296 }
297 }
298 return false
299}
300
301// AddHsiaFlows - Adds US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530302func (vs *VoltService) AddHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530303 logger.Debugw(ctx, "Add US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530304 if err := vs.AddUsHsiaFlows(cntx); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530305 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 +0530306 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
307 vs.triggerServiceFailureInd(statusCode, statusMessage)
308 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530309 if err := vs.AddDsHsiaFlows(cntx); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530310 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 +0530311 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
312 vs.triggerServiceFailureInd(statusCode, statusMessage)
313 }
314}
315
vinokuma926cb3e2023-03-29 11:41:06 +0530316// DelHsiaFlows - Deletes US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530317func (vs *VoltService) DelHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530318 logger.Debugw(ctx, "Delete US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530319 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530320 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 +0530321 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
322 vs.triggerServiceFailureInd(statusCode, statusMessage)
323 }
324
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530325 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530326 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 +0530327 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
328 vs.triggerServiceFailureInd(statusCode, statusMessage)
329 }
330}
331
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530332func (vs *VoltService) AddMeterToDevice(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530333 logger.Debugw(ctx, "Add Meter To Device for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530334 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530335 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 +0530336 }
337 va := GetApplication()
338 logger.Infow(ctx, "Configuring Meters for FTTB", log.Fields{"ServiceName": vs.Name})
339 device, err := va.GetDeviceFromPort(vs.Port)
340 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530341 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 +0530342 } else if device.State != controller.DeviceStateUP {
343 logger.Warnw(ctx, "Device state Down. Ignoring Meter Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
344 return nil
345 }
346 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
347 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
348 return nil
349}
350
Naveen Sampath04696f72022-06-13 15:19:14 +0530351// AddUsHsiaFlows - Add US HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530352func (vs *VoltService) AddUsHsiaFlows(cntx context.Context) error {
Akash Sonief452f12024-12-12 18:20:28 +0530353 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 +0530354 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530355 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 +0530356 return nil
357 }
358
359 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530360 if !vs.UsHSIAFlowsApplied || vgcRebooted {
361 device, err := va.GetDeviceFromPort(vs.Port)
362 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530363 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 +0530364 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 +0530365 } else if device.State != controller.DeviceStateUP {
366 logger.Warnw(ctx, "Device state Down. Ignoring US HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
367 return nil
368 }
369
370 vs.Device = device.Name
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530371 /* In case of DPU_MGMT_TRAFFIC the meters will be configured before US flow creation*/
vinokuma926cb3e2023-03-29 11:41:06 +0530372 if vs.ServiceType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530373 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
374 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
375 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530376 pBits := vs.Pbits
377
vinokuma926cb3e2023-03-29 11:41:06 +0530378 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530379 if len(vs.Pbits) == 0 {
380 pBits = append(pBits, PbitMatchNone)
381 }
382 for _, pbits := range pBits {
383 usflows, err := vs.BuildUsHsiaFlows(pbits)
384 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530385 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 +0530386 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
387 vs.triggerServiceFailureInd(statusCode, statusMessage)
388 continue
389 }
390 usflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530391 if err := vs.AddFlows(cntx, device, usflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530392 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 +0530393 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
394 vs.triggerServiceFailureInd(statusCode, statusMessage)
395 }
396 }
397 vs.UsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530398 logger.Debugw(ctx, "Pushed US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530399 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530400 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530401 return nil
402}
403
404// AddDsHsiaFlows - Add DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530405func (vs *VoltService) AddDsHsiaFlows(cntx context.Context) error {
Akash Sonief452f12024-12-12 18:20:28 +0530406 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 +0530407 if vs.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530408 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 +0530409 return nil
410 }
411
412 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530413 if !vs.DsHSIAFlowsApplied || vgcRebooted {
414 device, err := va.GetDeviceFromPort(vs.Port)
415 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530416 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 +0530417 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 +0530418 } else if device.State != controller.DeviceStateUP {
419 logger.Warnw(ctx, "Device state Down. Ignoring DS HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
420 return nil
421 }
422
423 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530424
425 //If no pbits configured for service, hence add PbitNone for flows
426 if len(vs.DsRemarkPbitsMap) == 0 {
427 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchNone))
428 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530429 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 +0530430 }
431 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530432 if err = vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530433 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 +0530434 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
435 vs.triggerServiceFailureInd(statusCode, statusMessage)
436 }
437 } else {
438 // if all 8 p-bits are to be remarked to one-pbit, configure all-to-one remarking flow
439 if _, ok := vs.DsRemarkPbitsMap[int(of.PbitMatchAll)]; ok {
440 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchAll))
441 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530442 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 +0530443 }
444 logger.Debug(ctx, "Add-one-match-all-pbit-flow")
445 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530446 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530447 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 +0530448 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
449 vs.triggerServiceFailureInd(statusCode, statusMessage)
450 }
451 } else {
452 for matchPbit := range vs.DsRemarkPbitsMap {
453 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
454 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530455 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 +0530456 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
457 vs.triggerServiceFailureInd(statusCode, statusMessage)
458 continue
459 }
460 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530461 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530462 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 +0530463 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
464 vs.triggerServiceFailureInd(statusCode, statusMessage)
465 }
466 }
467 }
468 }
469 vs.DsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530470 logger.Debugw(ctx, "Pushed DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530471 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530472 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530473 return nil
474}
475
476// DelUsHsiaFlows - Deletes US HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530477func (vs *VoltService) DelUsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530478 logger.Infow(ctx, "Removing US HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530479 if vs.UsHSIAFlowsApplied || vgcRebooted {
480 device, err := GetApplication().GetDeviceFromPort(vs.Port)
481 if err != nil {
Akash Sonief452f12024-12-12 18:20:28 +0530482 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 +0530483 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 +0530484 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530485 pBits := vs.Pbits
486
vinokuma926cb3e2023-03-29 11:41:06 +0530487 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530488 if len(vs.Pbits) == 0 {
489 pBits = append(pBits, PbitMatchNone)
490 }
491 for _, pbits := range pBits {
492 usflows, err := vs.BuildUsHsiaFlows(pbits)
493 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530494 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 +0530495 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
496 vs.triggerServiceFailureInd(statusCode, statusMessage)
497 continue
498 }
499 usflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530500 if err = vs.DelFlows(cntx, device, usflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530501 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 +0530502 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
503 vs.triggerServiceFailureInd(statusCode, statusMessage)
504 }
505 }
506 vs.UsHSIAFlowsApplied = false
507 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530508 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530509 return nil
510}
511
512// DelDsHsiaFlows - Deletes DS HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530513func (vs *VoltService) DelDsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530514 logger.Infow(ctx, "Removing DS HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530515 if vs.DsHSIAFlowsApplied || vgcRebooted {
516 device, err := GetApplication().GetDeviceFromPort(vs.Port)
517 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530518 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 +0530519 }
520
Naveen Sampath04696f72022-06-13 15:19:14 +0530521 var matchPbit int
vinokuma926cb3e2023-03-29 11:41:06 +0530522 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530523 if len(vs.DsRemarkPbitsMap) == 0 {
524 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(PbitMatchNone))
525 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530526 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 +0530527 }
528 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530529 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530530 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 +0530531 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
532 vs.triggerServiceFailureInd(statusCode, statusMessage)
533 }
534 } else if _, ok := vs.DsRemarkPbitsMap[int(PbitMatchAll)]; ok {
535 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(int(PbitMatchAll)))
536 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530537 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 +0530538 }
539 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530540 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530541 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 +0530542 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
543 vs.triggerServiceFailureInd(statusCode, statusMessage)
544 }
545 } else {
546 for matchPbit = range vs.DsRemarkPbitsMap {
547 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
548 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530549 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 +0530550 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
551 vs.triggerServiceFailureInd(statusCode, statusMessage)
552 continue
553 }
554 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530555 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530556 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 +0530557 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
558 vs.triggerServiceFailureInd(statusCode, statusMessage)
559 }
560 }
561 }
562 vs.DsHSIAFlowsApplied = false
563 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530564 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 +0530565 // Post HSIA configuration success indication on message bus
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530566 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530567 return nil
568}
569
570// BuildDsHsiaFlows build the DS HSIA flows
571// Called for add/delete HSIA flows
572func (vs *VoltService) BuildDsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530573 logger.Debugw(ctx, "Building DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530574 flow := &of.VoltFlow{}
575 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
576
577 // Get the out and in ports for the flows
578 device, err := GetApplication().GetDeviceFromPort(vs.Port)
579 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530580 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 +0530581 }
582 inport, _ := GetApplication().GetPortID(device.NniPort)
583 outport, _ := GetApplication().GetPortID(vs.Port)
584 // PortName and PortID to be used for validation of port before flow pushing
585 flow.PortID = outport
586 flow.PortName = vs.Port
587 allowTransparent := 0
588 if vs.AllowTransparent {
589 allowTransparent = 1
590 }
591
592 // initialized actnPbit to 0 for cookie genration backward compatibility.
593 var actnPbit of.PbitType
594 remarkPbit, remarkExists := vs.DsRemarkPbitsMap[int(pbits)]
595
596 generateDSCookie := func(vlan of.VlanType, valToShift uint64) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530597 // | 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 +0530598 cookie := uint64(vlan)<<52 + uint64(actnPbit)<<48 + uint64(outport)<<16 | of.HsiaFlowMask
599 cookie = cookie | of.DsFlowMask
600 cookie = cookie + (valToShift << 4) + uint64(pbits)
601 return cookie
602 }
603
604 l2ProtoValue, err := GetMetadataForL2Protocol(vs.SVlanTpid)
605 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530606 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 +0530607 }
608
609 // Add Table-0 flow that deals with the outer VLAN in pOLT
610 {
611 subflow1 := of.NewVoltSubFlow()
612 subflow1.SetTableID(0)
613 subflow1.SetGoToTable(1)
614 subflow1.SetInPort(inport)
615
616 if pbits != PbitMatchNone {
617 subflow1.SetMatchPbit(pbits)
618 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530619 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
620 subflow1.SetPcp(of.PbitType(remarkPbit))
621 // match & action pbits are different, set remark-pbit action
622 actnPbit = of.PbitType(remarkPbit)
623 // mask remark p-bit to 4bits
624 actnPbit = actnPbit & 0x0F
625 }
626
627 if err := vs.setDSMatchActionVlanT0(subflow1); err != nil {
628 return nil, err
629 }
Tinoj Joseph1d108322022-07-13 10:07:39 +0530630 logger.Infow(ctx, "HSIA DS flows MAC Learning & MAC", log.Fields{"ML": vs.MacLearning, "Mac": vs.MacAddr})
Naveen Sampath04696f72022-06-13 15:19:14 +0530631 if NonZeroMacAddress(vs.MacAddr) {
632 subflow1.SetMatchDstMac(vs.MacAddr)
633 }
634 subflow1.Priority = of.HsiaFlowPriority
635 subflow1.SetMeterID(vs.DsMeterID)
636
637 /* WriteMetaData 8 Byte(uint64) usage:
638 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
639 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
640 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530641 if vs.ServiceType == FttbSubscriberTraffic {
642 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
643 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530644 subflow1.SetWriteMetadata(metadata)
645
646 /* TableMetaData 8 Byte(uint64) Voltha usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
647 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
648 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
649 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | unitag | unitag | ctag | ctag | */
650
651 //TODO-COMM:
652 /* TableMetaData 8 Byte(uint64) Community usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
653 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
654 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
655 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | ctag | ctag | ctag | ctag | */
656
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530657 if vs.ServiceType != FttbSubscriberTraffic {
658 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
659 subflow1.SetTableMetadata(metadata)
660 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530661 // TODO - We are using cookie as key and must come up with better cookie
662 // allocation algorithm
663 /**
664 * Cokies may clash when -
665 * on same uni-port we have two sub-service
666 * 1. U=10, C=100, S=310, p-bit=4 - VLAN_Control = OLT_CVLAN_OLT_SVLAN
667 * 2. U=10, C=10, S=320, p-bit=4 - VLAN_control = ONU_CVLAN_ONU_SVLAN
668 * However, this p-bit re-use will not be allowed by sub-mgr.
669 */
670 if vs.VlanControl == OLTCVlanOLTSVlan {
671 /**
672 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
673 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
674 * use old cookie.
675 */
676 subflow1.Cookie = generateDSCookie(vs.UniVlan, 0)
677 if vgcRebooted {
678 subflow1.OldCookie = generateDSCookie(vs.CVlan, 0)
679 }
680 } else {
681 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
682 subflow1.Cookie = generateDSCookie(vs.CVlan, 0)
683 }
684
685 flow.SubFlows[subflow1.Cookie] = subflow1
686 logger.Infow(ctx, "Building downstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie,
687 "subflow": subflow1})
688 }
689
vinokuma926cb3e2023-03-29 11:41:06 +0530690 // Add Table-1 flow that deals with inner VLAN at the ONU
Naveen Sampath04696f72022-06-13 15:19:14 +0530691 {
692 subflow2 := of.NewVoltSubFlow()
693 subflow2.SetTableID(1)
694 subflow2.SetInPort(inport)
695 if NonZeroMacAddress(vs.MacAddr) {
696 subflow2.SetMatchDstMac(vs.MacAddr)
697 }
698
699 if err := vs.setDSMatchActionVlanT1(subflow2); err != nil {
700 return nil, err
701 }
702 if pbits != PbitMatchNone {
703 subflow2.SetMatchPbit(pbits)
704 }
705
706 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
707 subflow2.SetPcp(of.PbitType(remarkPbit))
708 }
709
710 subflow2.SetOutPort(outport)
711 subflow2.SetMeterID(vs.DsMeterID)
712
713 // refer Table-0 flow generation for byte information
714 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530715 if vs.ServiceType == FttbSubscriberTraffic {
716 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
717 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530718 subflow2.SetWriteMetadata(metadata)
719
720 // Table-1 and inport is NNI: It is a DS flow for ONU, add uniport in metadata to make it unique
721 if util.IsNniPort(inport) {
722 metadata = uint64(outport)
723 } else {
724 // refer Table-0 flow generation for byte information
725 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
726 }
727 subflow2.SetTableMetadata(metadata)
728 // Setting of Cookie - TODO - Improve the allocation algorithm
729 if vs.VlanControl == OLTCVlanOLTSVlan {
730 /**
731 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
732 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
733 * use old cookie.
734 */
735 subflow2.Cookie = generateDSCookie(vs.UniVlan, 1)
736 if vgcRebooted {
737 subflow2.OldCookie = generateDSCookie(vs.CVlan, 1)
738 }
739 } else {
740 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
741 subflow2.Cookie = generateDSCookie(vs.CVlan, 1)
742 }
743
744 subflow2.Priority = of.HsiaFlowPriority
745 flow.SubFlows[subflow2.Cookie] = subflow2
746 logger.Infow(ctx, "Building downstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie,
747 "subflow": subflow2})
748 }
749
750 return flow, nil
751}
752
753// BuildUsHsiaFlows build the US HSIA flows
754// Called for add/delete HSIA flows
755func (vs *VoltService) BuildUsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Akash Sonief452f12024-12-12 18:20:28 +0530756 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 +0530757 flow := &of.VoltFlow{}
758 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
759
760 // Get the out and in ports for the flows
761 device, err := GetApplication().GetDeviceFromPort(vs.Port)
762 if err != nil {
763 return nil, errorCodes.ErrDeviceNotFound
764 }
765 outport, _ := GetApplication().GetPortID(device.NniPort)
766 inport, _ := GetApplication().GetPortID(vs.Port)
767 // PortName and PortID to be used for validation of port before flow pushing
768 flow.PortID = inport
769 flow.PortName = vs.Port
Naveen Sampath04696f72022-06-13 15:19:14 +0530770
771 // Add Table-0 flow that deals with the inner VLAN in ONU
772 {
773 subflow1 := of.NewVoltSubFlow()
774 subflow1.SetTableID(0)
775 subflow1.SetGoToTable(1)
776 subflow1.SetInPort(inport)
777
vinokuma926cb3e2023-03-29 11:41:06 +0530778 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530779 subflow1.SetMatchPbit(vs.UsPonCTagPriority)
780 subflow1.SetPcp(vs.UsPonSTagPriority)
vinokuma926cb3e2023-03-29 11:41:06 +0530781 } else if vs.ServiceType == DpuAncpTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530782 subflow1.SetPcp(vs.UsPonSTagPriority)
783 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530784 if err := vs.setUSMatchActionVlanT0(subflow1); err != nil {
785 return nil, err
786 }
787 subflow1.SetMeterID(vs.UsMeterID)
788
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530789 /* WriteMetaData 8 Byte(uint64) usage:
790 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
791 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
792 //metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
793 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530794 if vs.ServiceType == FttbSubscriberTraffic {
795 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
796 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530797 subflow1.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530798
Naveen Sampath04696f72022-06-13 15:19:14 +0530799 if vs.VlanControl == OLTCVlanOLTSVlan {
800 /**
801 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
802 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
803 * use old cookie.
804 */
805 subflow1.Cookie = vs.generateUSCookie(vs.UniVlan, 0, inport, pbits)
806 if vgcRebooted {
807 subflow1.OldCookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
808 }
809 } else {
810 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
811 subflow1.Cookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
812 }
813 subflow1.Priority = of.HsiaFlowPriority
814 flow.SubFlows[subflow1.Cookie] = subflow1
815 logger.Infow(ctx, "Building upstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie, "subflow": subflow1})
816 }
817
vinokuma926cb3e2023-03-29 11:41:06 +0530818 // Add Table-1 flow that deals with the outer vlan in pOLT
Naveen Sampath04696f72022-06-13 15:19:14 +0530819 {
820 subflow2 := of.NewVoltSubFlow()
821 subflow2.SetTableID(1)
822 subflow2.SetInPort(inport)
823
Naveen Sampath04696f72022-06-13 15:19:14 +0530824 if err := vs.setUSMatchActionVlanT1(subflow2); err != nil {
825 return nil, err
826 }
vinokuma926cb3e2023-03-29 11:41:06 +0530827 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530828 subflow2.SetMatchSrcMac(vs.MacAddr)
829 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530830 subflow2.SetInPort(inport)
831 subflow2.SetOutPort(outport)
832 subflow2.SetMeterID(vs.UsMeterID)
833
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530834 // refer Table-0 flow generation for byte information
835 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530836 if vs.ServiceType == FttbSubscriberTraffic {
837 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
838 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530839 subflow2.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530840
Naveen Sampath04696f72022-06-13 15:19:14 +0530841 if vs.VlanControl == OLTCVlanOLTSVlan {
842 /**
843 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
844 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
845 * use old cookie.
846 */
847 subflow2.Cookie = vs.generateUSCookie(vs.UniVlan, 1, inport, pbits)
848 if vgcRebooted {
849 subflow2.OldCookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
850 }
851 } else {
852 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
853 subflow2.Cookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
854 }
855 subflow2.Priority = of.HsiaFlowPriority
856
857 flow.SubFlows[subflow2.Cookie] = subflow2
858 logger.Infow(ctx, "Building upstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie, "subflow": subflow2})
859 }
860
861 return flow, nil
862}
863
864func (vs *VoltService) generateUSCookie(vlan of.VlanType, valToShift uint64, inport uint32, pbits of.PbitType) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530865 // | 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 +0530866 logger.Debugw(ctx, "Generate US Cookie", log.Fields{"Vlan": vlan, "ValToShift": vlan, "Inport": inport, "Pbits": pbits})
Naveen Sampath04696f72022-06-13 15:19:14 +0530867 cookie := uint64(vlan)<<52 + uint64(inport)<<16 | of.HsiaFlowMask
868 cookie = cookie | of.UsFlowMask
869 cookie = cookie + (valToShift << 4) + uint64(pbits)
870 return cookie
871}
872
873// setUSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for US Table-1
874// based on different Vlan Controls
875func (vs *VoltService) setUSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530876 logger.Debugw(ctx, "Set US Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530877 switch vs.VlanControl {
878 case None:
879 flow.SetMatchVlan(vs.SVlan)
880 case ONUCVlanOLTSVlan:
881 flow.SetMatchVlan(vs.CVlan)
882 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
883 case OLTCVlanOLTSVlan:
884 flow.SetMatchVlan(vs.UniVlan)
885 flow.SetSetVlan(vs.CVlan)
886 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
887 case ONUCVlan:
888 flow.SetMatchVlan(vs.SVlan)
889 case OLTSVlan:
890 if vs.UniVlan != of.VlanAny && vs.UniVlan != of.VlanNone {
891 flow.SetMatchVlan(vs.UniVlan)
892 flow.SetSetVlan(vs.SVlan)
893 } else if vs.UniVlan != of.VlanNone {
894 flow.SetMatchVlan(vs.UniVlan)
895 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
896 } else {
897 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
898 }
899 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530900 err := errorCodes.ErrInvalidParamInRequest
901 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530902 }
903 return nil
904}
905
906// setDSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for DS Table-0
907// based on different Vlan Controls
908func (vs *VoltService) setDSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530909 logger.Debugw(ctx, "Set DS Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530910 switch vs.VlanControl {
911 case None:
912 flow.SetMatchVlan(vs.SVlan)
913 case ONUCVlanOLTSVlan:
914 flow.SetMatchVlan(vs.SVlan)
915 flow.SetPopVlan()
916 case OLTCVlanOLTSVlan:
917 flow.SetMatchVlan(vs.SVlan)
918 flow.SetPopVlan()
919 flow.SetSetVlan(vs.UniVlan)
920 case ONUCVlan:
921 flow.SetMatchVlan(vs.SVlan)
922 case OLTSVlan:
923 flow.SetMatchVlan(vs.SVlan)
924 if vs.UniVlan != of.VlanNone && vs.UniVlan != of.VlanAny {
925 flow.SetSetVlan(vs.UniVlan)
926 } else {
927 flow.SetPopVlan()
928 }
929 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530930 err := errorCodes.ErrInvalidParamInRequest
931 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530932 }
933 return nil
934}
935
936// setUSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for US Table-0
937// based on different Vlan Controls
938func (vs *VoltService) setUSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530939 logger.Debugw(ctx, "Set US Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530940 switch vs.VlanControl {
941 case None:
942 flow.SetMatchVlan(vs.SVlan)
943 case ONUCVlanOLTSVlan:
944 if vs.UniVlan != of.VlanNone {
945 flow.SetMatchVlan(vs.UniVlan)
946 flow.SetSetVlan(vs.CVlan)
947 } else {
948 flow.SetPushVlan(vs.CVlan, layers.EthernetTypeDot1Q)
949 }
950 case OLTCVlanOLTSVlan:
951 flow.SetMatchVlan(vs.UniVlan)
952 case ONUCVlan:
953 if vs.UniVlan != of.VlanNone {
954 flow.SetMatchVlan(vs.UniVlan)
955 flow.SetSetVlan(vs.SVlan)
956 } else {
957 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
958 }
959 case OLTSVlan:
960 flow.SetMatchVlan(vs.UniVlan)
961 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530962 err := errorCodes.ErrInvalidParamInRequest
963 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530964 }
965 return nil
966}
967
968// setDSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for DS Table-1
969// based on different Vlan Controls
970func (vs *VoltService) setDSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530971 logger.Debugw(ctx, "Set DS Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530972 switch vs.VlanControl {
973 case None:
974 flow.SetMatchVlan(vs.SVlan)
975 case ONUCVlanOLTSVlan:
976 flow.SetMatchVlan(vs.CVlan)
977 if vs.UniVlan != of.VlanNone {
978 flow.SetSetVlan(vs.UniVlan)
979 } else {
980 flow.SetPopVlan()
981 }
982 case OLTCVlanOLTSVlan:
983 flow.SetMatchVlan(vs.UniVlan)
984 case ONUCVlan:
985 flow.SetMatchVlan(vs.SVlan)
986 if vs.UniVlan != of.VlanNone {
987 flow.SetSetVlan(vs.UniVlan)
988 } else {
989 flow.SetPopVlan()
990 }
991 case OLTSVlan:
992 flow.SetMatchVlan(vs.UniVlan)
993 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530994 err := errorCodes.ErrInvalidParamInRequest
995 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530996 }
997 return nil
998}
999
1000// SvcUpInd for service up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301001func (vs *VoltService) SvcUpInd(cntx context.Context) {
1002 vs.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301003}
1004
1005// SvcDownInd for service down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301006func (vs *VoltService) SvcDownInd(cntx context.Context) {
1007 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301008}
1009
1010// SetIpv4Addr to set ipv4 address
1011func (vs *VoltService) SetIpv4Addr(addr net.IP) {
1012 vs.Ipv4Addr = addr
1013}
1014
1015// SetIpv6Addr to set ipv6 address
1016func (vs *VoltService) SetIpv6Addr(addr net.IP) {
1017 vs.Ipv6Addr = addr
1018}
1019
1020// SetMacAddr to set mac address
1021func (vs *VoltService) SetMacAddr(addr net.HardwareAddr) {
1022 vs.MacAddr = addr
1023}
1024
1025// ----------------------------------------------
1026// VOLT Application - Related to services
1027// ---------------------------------------------
1028// ---------------------------------------------------------------
1029// Service CRUD functions. These are exposed to the overall binary
1030// to be invoked from the point where the CRUD operations are received
1031// from the external entities
1032
1033// AddService : A service in the context of VOLT is a subscriber or service of a
1034// subscriber which is uniquely identified by a combination of MAC
1035// address, VLAN tags, 802.1p bits. However, in the context of the
1036// current implementation, a service is an entity that is identified by a
1037// unique L2 (MAC address + VLANs) or unique L3 (VLANs + IP address)
1038// FUNC: Add Service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301039func (va *VoltApplication) AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301040 logger.Infow(ctx, "Service to be configured", log.Fields{"Cfg": cfg})
Naveen Sampath04696f72022-06-13 15:19:14 +05301041 var mmUs, mmDs *VoltMeter
1042 var err error
1043
vinokuma926cb3e2023-03-29 11:41:06 +05301044 // Take the Device lock only in case of NB add request.
Naveen Sampath04696f72022-06-13 15:19:14 +05301045 // Allow internal adds since internal add happen only under
1046 // 1. Restore Service from DB
1047 // 2. Service Migration
1048 if oper == nil {
1049 if svc := va.GetService(cfg.Name); svc != nil {
1050 logger.Warnw(ctx, "Service Already Exists. Ignoring Add Service Request", log.Fields{"Name": cfg.Name})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301051 return errors.New("service already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301052 }
1053 }
1054
Naveen Sampath04696f72022-06-13 15:19:14 +05301055 // Service doesn't exist. So create it and add to the port
1056 vs := NewVoltService(&cfg)
1057 if oper != nil {
1058 vs.UsHSIAFlowsApplied = oper.UsHSIAFlowsApplied
1059 vs.DsHSIAFlowsApplied = oper.DsHSIAFlowsApplied
1060 vs.Ipv4Addr = oper.Ipv4Addr
1061 vs.Ipv6Addr = oper.Ipv6Addr
1062 vs.MacLearning = cfg.MacLearning
1063 vs.PendingFlows = oper.PendingFlows
1064 vs.AssociatedFlows = oper.AssociatedFlows
1065 vs.DeleteInProgress = oper.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301066 vs.DeactivateInProgress = oper.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301067 vs.BwAvailInfo = oper.BwAvailInfo
1068 vs.Device = oper.Device
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301069 vs.ServiceDeactivateReason = cfg.ServiceDeactivateReason
Naveen Sampath04696f72022-06-13 15:19:14 +05301070 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301071 // Sorting Pbit from highest
Naveen Sampath04696f72022-06-13 15:19:14 +05301072 sort.Slice(vs.Pbits, func(i, j int) bool {
1073 return vs.Pbits[i] > vs.Pbits[j]
1074 })
Akash Sonief452f12024-12-12 18:20:28 +05301075 logger.Debugw(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
Naveen Sampath04696f72022-06-13 15:19:14 +05301076 }
1077 logger.Infow(ctx, "VolthService...", log.Fields{"vs": vs.Name})
1078
1079 // The bandwidth and shaper profile combined into meter
1080 if mmDs, err = va.GetMeter(cfg.DsMeterProfile); err == nil {
1081 vs.DsMeterID = mmDs.ID
1082 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301083 return errors.New("downStream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301084 }
1085
1086 // The aggregated downstream meter profile
1087 // if mmAg, err = va.GetMeter(cfg.AggDsMeterProfile); err == nil {
1088 // vs.AggDsMeterID = mmAg.ID
1089 // } else {
1090 // return errors.New("Aggregated meter profile not found")
1091 // }
1092
1093 // if cfg.AggDsMeterProfile == cfg.UsMeterProfile {
1094 // vs.UsMeterID = mmAg.ID
1095 // } else {
1096 // The bandwidth and shaper profile combined into meter
1097 if mmUs, err = va.GetMeter(cfg.UsMeterProfile); err == nil {
1098 vs.UsMeterID = mmUs.ID
1099 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301100 return errors.New("upstream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301101 }
1102 //}
1103
1104 AppMutex.ServiceDataMutex.Lock()
1105 defer AppMutex.ServiceDataMutex.Unlock()
1106
1107 // Add the service to the VNET
1108 vnet := va.GetVnet(cfg.SVlan, cfg.CVlan, cfg.UniVlan)
1109 if vnet != nil {
1110 if vpv := va.GetVnetByPort(vs.Port, cfg.SVlan, cfg.CVlan, cfg.UniVlan); vpv != nil {
1111 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301112 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301113 vpv.VpvLock.Unlock()
1114 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301115 va.AddVnetToPort(cntx, vs.Port, vnet, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301116 }
1117 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301118 logger.Warnw(ctx, "VNET-does-not-exist-for-service", log.Fields{"ServiceName": cfg.Name})
1119 return errors.New("vnet doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301120 }
1121
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301122 // If the device is already discovered, update the device name in service
1123 d, err := va.GetDeviceFromPort(vs.Port)
1124 if err == nil {
1125 vs.Device = d.Name
1126 }
1127
Naveen Sampath04696f72022-06-13 15:19:14 +05301128 vs.Version = database.PresentVersionMap[database.ServicePath]
1129 // Add the service to the volt application
1130 va.ServiceByName.Store(vs.Name, vs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301131 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301132
1133 if nil == oper {
Naveen Sampath04696f72022-06-13 15:19:14 +05301134 if !vs.UsHSIAFlowsApplied {
1135 vs.triggerServiceInProgressInd()
1136 }
1137
vinokuma926cb3e2023-03-29 11:41:06 +05301138 // Update meter profiles service count if service is being added from northbound
Naveen Sampath04696f72022-06-13 15:19:14 +05301139 mmDs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301140 va.UpdateMeterProf(cntx, *mmDs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301141 if mmUs != nil {
1142 mmUs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301143 va.UpdateMeterProf(cntx, *mmUs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301144 }
1145 //mmAg.AssociatedServices++
1146 //va.UpdateMeterProf(*mmAg)
vinokuma926cb3e2023-03-29 11:41:06 +05301147 logger.Debugw(ctx, "northbound-service-add-successful", log.Fields{"ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301148 }
1149
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301150 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 +05301151 return nil
1152}
1153
vinokuma926cb3e2023-03-29 11:41:06 +05301154// DelServiceWithPrefix - Deletes service with the provided prefix.
Naveen Sampath04696f72022-06-13 15:19:14 +05301155// Added for DT/TT usecase with sadis replica interface
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301156func (va *VoltApplication) DelServiceWithPrefix(cntx context.Context, prefix string) error {
Akash Sonief452f12024-12-12 18:20:28 +05301157 logger.Debugw(ctx, "Delete Service With provided Prefix", log.Fields{"Prefix": prefix})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301158 var isServiceExist bool
Naveen Sampath04696f72022-06-13 15:19:14 +05301159 va.ServiceByName.Range(func(key, value interface{}) bool {
1160 srvName := key.(string)
1161 vs := value.(*VoltService)
1162 if strings.Contains(srvName, prefix) {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301163 isServiceExist = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301164 va.DelService(cntx, srvName, true, nil, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301165
1166 vnetName := strconv.FormatUint(uint64(vs.SVlan), 10) + "-"
1167 vnetName = vnetName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1168 vnetName = vnetName + strconv.FormatUint(uint64(vs.UniVlan), 10)
1169
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301170 if err := va.DelVnet(cntx, vnetName, ""); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301171 logger.Warnw(ctx, "Delete Vnet Failed", log.Fields{"Name": vnetName, "Error": err})
1172 }
1173 }
1174 return true
1175 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301176
1177 if !isServiceExist {
1178 return errorCodes.ErrServiceNotFound
1179 }
1180 return nil
Naveen Sampath04696f72022-06-13 15:19:14 +05301181}
1182
1183// DelService delete a service form the application
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301184func (va *VoltApplication) DelService(cntx context.Context, name string, forceDelete bool, newSvc *VoltServiceCfg, serviceMigration bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301185 AppMutex.ServiceDataMutex.Lock()
1186 defer AppMutex.ServiceDataMutex.Unlock()
1187
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301188 logger.Infow(ctx, "Delete Service Request", log.Fields{"Service": name, "ForceDelete": forceDelete, "serviceMigration": serviceMigration})
Naveen Sampath04696f72022-06-13 15:19:14 +05301189 var noFlowsPresent bool
1190
1191 vsIntf, ok := va.ServiceByName.Load(name)
1192 if !ok {
1193 logger.Warnw(ctx, "Service doesn't exist", log.Fields{"ServiceName": name})
1194 return
1195 }
1196 vs := vsIntf.(*VoltService)
1197 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1198 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301199 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301200 return
1201 }
1202
vinokuma926cb3e2023-03-29 11:41:06 +05301203 // Set this to avoid race-condition during flow result processing
Naveen Sampath04696f72022-06-13 15:19:14 +05301204 vs.DeleteInProgress = true
1205 vs.ForceDelete = forceDelete
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301206 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301207
Akash Sonief452f12024-12-12 18:20:28 +05301208 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301209 if len(vs.AssociatedFlows) == 0 {
1210 noFlowsPresent = true
1211 }
Akash Sonief452f12024-12-12 18:20:28 +05301212 vs.ServiceLock.RUnlock()
1213
Naveen Sampath04696f72022-06-13 15:19:14 +05301214 vpv.VpvLock.Lock()
1215 defer vpv.VpvLock.Unlock()
1216
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301217 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301218
1219 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301220 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301221 }
1222 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 +05301223 vpv.DelService(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301224 if vpv.servicesCount.Load() == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301225 va.DelVnetFromPort(cntx, vs.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301226 }
1227
1228 // Delete the service immediately in case of Force Delete
1229 // This will be enabled when profile reconciliation happens after restore
1230 // of backedup data
1231 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301232 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301233 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301234 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 }
1236
Naveen Sampath04696f72022-06-13 15:19:14 +05301237 if nil != newSvc {
1238 logger.Infow(ctx, "Old Service meter profiles", log.Fields{"AGG": vs.AggDsMeterProfile, "DS": vs.DsMeterProfile, "US": vs.UsMeterProfile})
1239 logger.Infow(ctx, "New Service meter profiles", log.Fields{"AGG": newSvc.AggDsMeterProfile, "DS": newSvc.DsMeterProfile, "US": newSvc.UsMeterProfile})
1240 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301241
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301242 logger.Infow(ctx, "About to mark meter for deletion\n", log.Fields{"serviceName": vs.Name})
1243
1244 if aggMeter, ok := va.MeterMgr.GetMeterByID(vs.AggDsMeterID); ok {
1245 if nil == newSvc || (nil != newSvc && aggMeter.Name != newSvc.AggDsMeterProfile) {
vinokuma926cb3e2023-03-29 11:41:06 +05301246 if aggMeter.AssociatedServices > 0 {
1247 aggMeter.AssociatedServices--
1248 logger.Infow(ctx, "Agg Meter associated services updated\n", log.Fields{"MeterID": aggMeter})
1249 va.UpdateMeterProf(cntx, *aggMeter)
1250 }
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301251 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301252 }
1253 if dsMeter, ok := va.MeterMgr.GetMeterByID(vs.DsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301254 if nil == newSvc || (nil != newSvc && dsMeter.Name != newSvc.DsMeterProfile) {
1255 if dsMeter.AssociatedServices > 0 {
1256 dsMeter.AssociatedServices--
1257 logger.Infow(ctx, "DS Meter associated services updated\n", log.Fields{"MeterID": dsMeter})
1258 va.UpdateMeterProf(cntx, *dsMeter)
1259 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301260 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301261 }
1262 if vs.AggDsMeterID != vs.UsMeterID {
1263 if usMeter, ok := va.MeterMgr.GetMeterByID(vs.UsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301264 if nil == newSvc || (nil != newSvc && usMeter.Name != newSvc.UsMeterProfile) {
1265 if usMeter.AssociatedServices > 0 {
1266 usMeter.AssociatedServices--
1267 logger.Infow(ctx, "US Meter associated services updated\n", log.Fields{"MeterID": usMeter})
1268 va.UpdateMeterProf(cntx, *usMeter)
1269 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301270 }
1271 }
1272 }
1273
1274 if noFlowsPresent || vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301275 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301276 }
1277
vinokuma926cb3e2023-03-29 11:41:06 +05301278 // Delete the per service counter too
Naveen Sampath04696f72022-06-13 15:19:14 +05301279 va.ServiceCounters.Delete(name)
1280 if vs.IgmpEnabled && vs.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301281 _ = db.DelAllServiceChannelCounter(cntx, name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301282 }
1283}
1284
vinokuma926cb3e2023-03-29 11:41:06 +05301285// AddFlows - Adds the flow to the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301286// Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301287func (vs *VoltService) AddFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301288 // Using locks instead of concurrent map for PendingFlows to avoid
1289 // race condition during flow response indication processing
1290 vs.ServiceLock.Lock()
1291 defer vs.ServiceLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301292 logger.Debugw(ctx, "Adds the flow to the service", log.Fields{"Port": vs.Port, "Device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301293
1294 for cookie := range flow.SubFlows {
1295 cookie := strconv.FormatUint(cookie, 10)
1296 fe := &FlowEvent{
1297 eType: EventTypeServiceFlowAdded,
1298 device: device.Name,
1299 cookie: cookie,
1300 eventData: vs,
1301 }
1302 device.RegisterFlowAddEvent(cookie, fe)
1303 vs.PendingFlows[cookie] = true
1304 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301305 return cntlr.GetController().AddFlows(cntx, vs.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301306}
1307
vinokuma926cb3e2023-03-29 11:41:06 +05301308// FlowInstallSuccess - Called when corresponding service flow installation is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301309// If no more pending flows, HSIA indication wil be triggered
Akash Sonief452f12024-12-12 18:20:28 +05301310func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301311 logger.Debugw(ctx, "Flow Add Success Notification", log.Fields{"Cookie": cookie, "bwAvailInfo": bwAvailInfo, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 if vs.DeleteInProgress {
1313 logger.Warnw(ctx, "Skipping Flow Add Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1314 return
1315 }
1316 vs.ServiceLock.Lock()
1317
1318 if _, ok := vs.PendingFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301319 logger.Warnw(ctx, "Flow Add Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301320 vs.ServiceLock.Unlock()
1321 return
1322 }
1323
1324 delete(vs.PendingFlows, cookie)
1325 vs.AssociatedFlows[cookie] = true
1326 vs.ServiceLock.Unlock()
1327 var prevBwAvail, presentBwAvail string
1328 if bwAvailInfo.PrevBw != "" && bwAvailInfo.PresentBw != "" {
1329 prevBwAvail = bwAvailInfo.PrevBw
1330 presentBwAvail = bwAvailInfo.PresentBw
1331 vs.BwAvailInfo = prevBwAvail + "," + presentBwAvail
Tinoj Joseph1d108322022-07-13 10:07:39 +05301332 logger.Debugw(ctx, "Bandwidth-value-formed", log.Fields{"BwAvailInfo": vs.BwAvailInfo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301333 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301334 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301335
Akash Sonief452f12024-12-12 18:20:28 +05301336 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301337 if len(vs.PendingFlows) == 0 && vs.DsHSIAFlowsApplied {
Akash Sonief452f12024-12-12 18:20:28 +05301338 vs.ServiceLock.RUnlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301339 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1340 if err != nil {
1341 logger.Errorw(ctx, "Error Getting Device. Dropping HSIA Success indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1342 return
1343 } else if device.State != controller.DeviceStateUP {
1344 logger.Warnw(ctx, "Device state Down. Dropping HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1345 return
1346 }
1347
1348 if vs.Trigger == ServiceVlanUpdate {
1349 vs.Trigger = NBActivate
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301350 defer vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301351 }
1352 logger.Infow(ctx, "All Flows installed for Service", log.Fields{"Service": vs.Name})
1353 return
1354 }
Akash Sonief452f12024-12-12 18:20:28 +05301355 vs.ServiceLock.RUnlock()
1356 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 +05301357}
1358
vinokuma926cb3e2023-03-29 11:41:06 +05301359// FlowInstallFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301360// Trigger service failure indication to NB
Akash Sonief452f12024-12-12 18:20:28 +05301361func (vs *VoltService) FlowInstallFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301362 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 +05301363 vs.ServiceLock.RLock()
Akash Sonief452f12024-12-12 18:20:28 +05301364
Naveen Sampath04696f72022-06-13 15:19:14 +05301365 if _, ok := vs.PendingFlows[cookie]; !ok {
1366 logger.Errorw(ctx, "Flow Add Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1367 vs.ServiceLock.RUnlock()
1368 return
1369 }
1370 vs.ServiceLock.RUnlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301371 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 +05301372 vs.triggerServiceFailureInd(errorCode, errReason)
1373}
1374
vinokuma926cb3e2023-03-29 11:41:06 +05301375// DelFlows - Deletes the flow from the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301376// Triggers flow deletion after registering for flow indication event
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301377func (vs *VoltService) DelFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow, delFlowsInDevice bool) error {
Akash Sonief452f12024-12-12 18:20:28 +05301378 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 +05301379 if !vs.ForceDelete {
1380 // Using locks instead of concurrent map for AssociatedFlows to avoid
1381 // race condition during flow response indication processing
1382 vs.ServiceLock.Lock()
1383 defer vs.ServiceLock.Unlock()
1384
1385 for cookie := range flow.SubFlows {
1386 cookie := strconv.FormatUint(cookie, 10)
1387 fe := &FlowEvent{
1388 eType: EventTypeServiceFlowRemoved,
1389 cookie: cookie,
1390 eventData: vs,
1391 }
1392 device.RegisterFlowDelEvent(cookie, fe)
1393 }
1394 }
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301395 return cntlr.GetController().DelFlows(cntx, vs.Port, device.Name, flow, delFlowsInDevice)
Naveen Sampath04696f72022-06-13 15:19:14 +05301396}
1397
vinokuma926cb3e2023-03-29 11:41:06 +05301398// CheckAndDeleteService - remove service from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301399func (vs *VoltService) CheckAndDeleteService(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301400 logger.Debugw(ctx, "Delete service from DB/Cache", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301401 if vs.DeleteInProgress && len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301402 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301403 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301404 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301405 }
1406}
1407
vinokuma926cb3e2023-03-29 11:41:06 +05301408// FlowRemoveSuccess - Called when corresponding service flow removal is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301409// If no more associated flows, DelHSIA indication wil be triggered
Akash Sonief452f12024-12-12 18:20:28 +05301410func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301411 // if vs.DeleteInProgress {
1412 // logger.Warnw(ctx, "Skipping Flow Remove Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1413 // return
1414 // }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301415
Naveen Sampath04696f72022-06-13 15:19:14 +05301416 vs.ServiceLock.Lock()
Akash Sonief452f12024-12-12 18:20:28 +05301417 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 +05301418
1419 if _, ok := vs.AssociatedFlows[cookie]; ok {
1420 delete(vs.AssociatedFlows, cookie)
1421 } else if _, ok := vs.PendingFlows[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301422 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 +05301423 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301424 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 +05301425 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301426 vs.ServiceLock.Unlock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301427 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301428
Akash Sonief452f12024-12-12 18:20:28 +05301429 vs.ServiceLock.RLock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301430 if len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Akash Sonief452f12024-12-12 18:20:28 +05301431 vs.ServiceLock.RUnlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301432 device := GetApplication().GetDevice(vs.Device)
1433 if device == nil {
1434 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1435 return
1436 } else if device.State != controller.DeviceStateUP {
1437 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1438 return
1439 }
1440
1441 if vs.UpdateInProgress {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301442 vs.updateVnetProfile(cntx, vs.Device)
vinokuma926cb3e2023-03-29 11:41:06 +05301443 // Not sending DEL_HSIA Indication since it wil be generated internally by SubMgr
Naveen Sampath04696f72022-06-13 15:19:14 +05301444 return
1445 }
1446 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 +05301447 // Get the service from application before proceeding to delete, as the service might have been activated
1448 // by the time the flow removal response is received from SB
1449 svc := GetApplication().GetService(vs.Name)
1450 if svc != nil {
1451 svc.CheckAndDeleteService(cntx)
1452 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301453
1454 return
1455 }
Akash Sonief452f12024-12-12 18:20:28 +05301456 vs.ServiceLock.RUnlock()
1457 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 +05301458}
1459
vinokuma926cb3e2023-03-29 11:41:06 +05301460// FlowRemoveFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301461// Trigger service failure indication to NB
Akash Sonief452f12024-12-12 18:20:28 +05301462func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301463 vs.ServiceLock.Lock()
Akash Sonief452f12024-12-12 18:20:28 +05301464 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 +05301465
1466 if _, ok := vs.AssociatedFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301467 logger.Warnw(ctx, "Flow Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301468 vs.ServiceLock.Unlock()
Naveen Sampath04696f72022-06-13 15:19:14 +05301469 return
1470 }
1471 if vs.DeleteInProgress {
1472 delete(vs.AssociatedFlows, cookie)
1473 }
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05301474 vs.ServiceLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301475 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 +05301476
1477 vs.triggerServiceFailureInd(errorCode, errReason)
Akash Sonief452f12024-12-12 18:20:28 +05301478 // Get the service from application before proceeding to delete, as the service might have been activated
1479 // by the time the flow removal response is received from SB
1480 svc := GetApplication().GetService(vs.Name)
1481 if svc != nil {
1482 svc.CheckAndDeleteService(cntx)
1483 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301484}
1485
1486func (vs *VoltService) triggerServiceFailureInd(errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301487 logger.Debugw(ctx, "Trigger Service Failure Ind", log.Fields{"Service": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301488 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1489 if err != nil {
1490 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1491 return
1492 } else if device.State != controller.DeviceStateUP {
1493 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1494 return
1495 }
1496}
1497
1498// RestoreSvcsFromDb read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301499func (va *VoltApplication) RestoreSvcsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301500 // VNETS must be learnt first
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301501 logger.Debug(ctx, "Restore Svcs From Db")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301502 vss, _ := db.GetServices(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301503 for _, vs := range vss {
1504 b, ok := vs.Value.([]byte)
1505 if !ok {
1506 logger.Warn(ctx, "The value type is not []byte")
1507 continue
1508 }
1509 var vvs VoltService
1510 err := json.Unmarshal(b, &vvs)
1511 if err != nil {
1512 logger.Warn(ctx, "Unmarshal of VNET failed")
1513 continue
1514 }
1515 logger.Debugw(ctx, "Retrieved Service", log.Fields{"Service": vvs.VoltServiceCfg})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301516 if err := va.AddService(cntx, vvs.VoltServiceCfg, &vvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301517 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": vvs.Name, "Error": err})
1518 }
1519
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301520 if vvs.VoltServiceOper.DeactivateInProgress {
Akash Sonief452f12024-12-12 18:20:28 +05301521 va.ServicesToDeactivate.Store(vvs.VoltServiceCfg.Name, true)
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301522 logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
1523 }
1524
Naveen Sampath04696f72022-06-13 15:19:14 +05301525 if vvs.VoltServiceOper.DeleteInProgress {
Akash Sonief452f12024-12-12 18:20:28 +05301526 va.ServicesToDelete.Store(vvs.VoltServiceCfg.Name, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301527 logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
1528 }
1529 }
1530}
1531
1532// GetService to get service
1533func (va *VoltApplication) GetService(name string) *VoltService {
1534 if vs, ok := va.ServiceByName.Load(name); ok {
1535 return vs.(*VoltService)
1536 }
1537 return nil
1538}
1539
1540// GetCircuitID to get circuit id
1541func (vs *VoltService) GetCircuitID() []byte {
1542 return []byte(vs.CircuitID)
1543}
1544
1545// GetRemoteID to get remote id
1546func (vs *VoltService) GetRemoteID() []byte {
1547 return []byte(vs.RemoteID)
1548}
1549
1550// IPAssigned to check if ip is assigned
1551func (vs *VoltService) IPAssigned() bool {
1552 if vs.Ipv4Addr != nil && !vs.Ipv4Addr.Equal(net.ParseIP("0.0.0.0")) {
1553 return true
1554 } else if vs.Ipv6Addr != nil && !vs.Ipv6Addr.Equal(net.ParseIP("0:0:0:0:0:0:0:0")) {
1555 return true
1556 }
1557 return false
1558}
1559
1560// GetServiceNameFromCookie to get service name from cookie
1561func (va *VoltApplication) GetServiceNameFromCookie(cookie uint64, portName string, pbit uint8, device string, tableMetadata uint64) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301562 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 +05301563 var vlan uint64
1564 vlanControl := (tableMetadata >> 32) & 0xF
1565
1566 if vlanControl == uint64(OLTCVlanOLTSVlan) {
1567 // Fetching UniVlan for vlanControl OLTCVLANOLTSVLAN
1568 vlan = (tableMetadata >> 16) & 0xFFFF
1569 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301570 // Fetching CVlan for other vlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301571 vlan = cookie >> 52
1572 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301573 logger.Debugw(ctx, "Configured Params", log.Fields{"VlanControl": vlanControl, "vlan": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301574 var vlans []of.VlanType
1575 vlans = append(vlans, of.VlanType(vlan))
1576 service := GetApplication().GetServiceFromCvlan(device, portName, vlans, uint8(pbit))
1577 if nil != service {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301578 logger.Infow(ctx, "Service Found for", log.Fields{"serviceName": service.Name, "portName": portName, "ctag": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301579 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301580 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 +05301581 }
1582 return service
1583}
1584
vinokuma926cb3e2023-03-29 11:41:06 +05301585// MigrateServicesReqStatus - update vnet request status
Naveen Sampath04696f72022-06-13 15:19:14 +05301586type MigrateServicesReqStatus string
1587
1588const (
vinokuma926cb3e2023-03-29 11:41:06 +05301589 // MigrateSrvsReqInit constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301590 MigrateSrvsReqInit MigrateServicesReqStatus = "Init"
vinokuma926cb3e2023-03-29 11:41:06 +05301591 // MigrateSrvsReqDeactTriggered constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301592 MigrateSrvsReqDeactTriggered MigrateServicesReqStatus = "Profiles Deactivated"
vinokuma926cb3e2023-03-29 11:41:06 +05301593 // MigrateSrvsReqCompleted constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301594 MigrateSrvsReqCompleted MigrateServicesReqStatus = "Update Complete"
1595)
1596
vinokuma926cb3e2023-03-29 11:41:06 +05301597// MigrateServicesRequest - update vnet request params
Naveen Sampath04696f72022-06-13 15:19:14 +05301598type MigrateServicesRequest struct {
1599 ID string
1600 OldVnetID string
1601 NewVnetID string
1602 ServicesList map[string]bool
1603 DeviceID string
1604 Status MigrateServicesReqStatus
1605 MigrateServicesLock sync.RWMutex
1606}
1607
1608func newMigrateServicesRequest(id string, oldVnetID string, newVnetID string, serviceMap map[string]bool, deviceID string) *MigrateServicesRequest {
Naveen Sampath04696f72022-06-13 15:19:14 +05301609 var msr MigrateServicesRequest
1610 msr.OldVnetID = oldVnetID
1611 msr.NewVnetID = newVnetID
1612 msr.ID = id
1613 msr.ServicesList = serviceMap
1614 msr.DeviceID = deviceID
1615 msr.Status = MigrateSrvsReqInit
1616 return &msr
1617}
1618
vinokuma926cb3e2023-03-29 11:41:06 +05301619// GetMsrKey - generates migrate service request key
Naveen Sampath04696f72022-06-13 15:19:14 +05301620func (msr *MigrateServicesRequest) GetMsrKey() string {
1621 return msr.OldVnetID + "-" + msr.ID
1622}
1623
1624// //isRequestComplete - return if all request has been processed and completed
1625// // RequestProcessed indicates that all the profile de-activation has been triggered
1626// // And the associated profiles indicates the profiles awaiting results
1627// func (msr *MigrateServicesRequest) isRequestComplete() bool {
1628// //return edr.RequestProcessed && (len(edr.AssociatedProfiles) == 0)
1629// return (len(edr.AssociatedProfiles) == 0)
1630// }
1631
vinokuma926cb3e2023-03-29 11:41:06 +05301632// WriteToDB - writes the udpate vnet request details ot DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301633func (msr *MigrateServicesRequest) WriteToDB(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301634 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)})
1635 if b, err := json.Marshal(msr); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301636 if err = db.PutMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey(), string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301637 logger.Warnw(ctx, "PutMigrateServicesReq Failed", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID,
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05301638 "Device": msr.DeviceID, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301639 }
1640 }
1641}
1642
vinokuma926cb3e2023-03-29 11:41:06 +05301643// MigrateServices - updated vnet profile for services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301644func (va *VoltApplication) MigrateServices(cntx context.Context, serialNum string, reqID string, oldVnetID, newVnetID string, serviceList []string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301645 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 +05301646 if _, ok := va.VnetsByName.Load(oldVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301647 return errors.New("old vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301648 }
1649 if _, ok := va.VnetsByName.Load(newVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301650 return errors.New("new vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301651 }
1652
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301653 d, _ := va.GetDeviceBySerialNo(serialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301654 if d == nil {
1655 logger.Errorw(ctx, "Error Getting Device", log.Fields{"SerialNum": serialNum})
1656 return errorCodes.ErrDeviceNotFound
1657 }
1658
1659 serviceMap := make(map[string]bool)
1660
1661 for _, service := range serviceList {
1662 serviceMap[service] = false
1663 }
1664 msr := newMigrateServicesRequest(reqID, oldVnetID, newVnetID, serviceMap, d.Name)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301665 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301666
1667 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301668 go msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301669 return nil
1670}
1671
vinokuma926cb3e2023-03-29 11:41:06 +05301672// ProcessMigrateServicesProfRequest - collects all associated profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301673func (msr *MigrateServicesRequest) ProcessMigrateServicesProfRequest(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301674 logger.Debug(ctx, "Process Migrate Services Prof Request")
Naveen Sampath04696f72022-06-13 15:19:14 +05301675 va := GetApplication()
1676 for srv, processed := range msr.ServicesList {
vinokuma926cb3e2023-03-29 11:41:06 +05301677 // Indicates new service is already created and only deletion of old one is pending
Naveen Sampath04696f72022-06-13 15:19:14 +05301678 if processed {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301679 va.DelService(cntx, srv, true, nil, true)
1680 msr.serviceMigrated(cntx, srv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301681 continue
1682 }
1683
1684 logger.Infow(ctx, "Migrate Service Triggering", log.Fields{"Service": srv})
1685 if vsIntf, ok := va.ServiceByName.Load(srv); ok {
1686 vs := vsIntf.(*VoltService)
1687 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1688 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301689 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 +05301690 continue
1691 }
1692 logger.Infow(ctx, "Migrating Service", log.Fields{"Service": vs.Name, "UsFlowApplied": vs.UsHSIAFlowsApplied})
1693 vpv.Blocked = true
1694
1695 // setDeactTrigger := func(key, value interface{}) bool {
1696 // vs := value.(*VoltService)
1697 vs.ServiceLock.Lock()
1698 vs.UpdateInProgress = true
1699 metadata := &MigrateServiceMetadata{
1700 NewVnetID: msr.NewVnetID,
1701 RequestID: msr.ID,
1702 }
1703 vs.Metadata = metadata
1704 vs.ServiceLock.Unlock()
1705
vinokuma926cb3e2023-03-29 11:41:06 +05301706 // vpv flows will be removed when last service is removed from it and
Naveen Sampath04696f72022-06-13 15:19:14 +05301707 // new vpv flows will be installed when new service is added
1708 if vs.UsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301709 vpv.DelTrapFlows(cntx)
1710 vs.DelHsiaFlows(cntx)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301711 logger.Infow(ctx, "Remove Service Flows Triggered", log.Fields{"Service": srv, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301712 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301713 vs.updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301714 }
1715 } else {
1716 logger.Warnw(ctx, "Migrate Service Failed: Service Not Found", log.Fields{"Service": srv, "Vnet": msr.OldVnetID})
1717 }
1718 }
1719}
1720
vinokuma926cb3e2023-03-29 11:41:06 +05301721// AddMigratingServices - store msr info to device obj
Naveen Sampath04696f72022-06-13 15:19:14 +05301722func (d *VoltDevice) AddMigratingServices(msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301723 logger.Infow(ctx, "Add Migrating Services", log.Fields{"Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301724 var msrMap *util.ConcurrentMap
1725 if msrMapIntf, ok := d.MigratingServices.Get(msr.OldVnetID); !ok {
1726 msrMap = util.NewConcurrentMap()
1727 } else {
1728 msrMap = msrMapIntf.(*util.ConcurrentMap)
1729 }
1730
1731 msrMap.Set(msr.ID, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301732 logger.Debugw(ctx, "1: MsrListLen", log.Fields{"Len": msrMap.Length(), "Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301733
1734 d.MigratingServices.Set(msr.OldVnetID, msrMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301735 logger.Debugw(ctx, "1: DeviceMsr", log.Fields{"Device": d.Name, "Vnet": msr.OldVnetID, "Len": d.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301736}
1737
vinokuma926cb3e2023-03-29 11:41:06 +05301738// getMigrateServicesRequest - fetches msr info from device
Naveen Sampath04696f72022-06-13 15:19:14 +05301739func (va *VoltApplication) getMigrateServicesRequest(deviceID string, oldVnetID string, requestID string) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301740 logger.Debugw(ctx, "Get Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301741 if vd := va.GetDevice(deviceID); vd != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301742 logger.Debugw(ctx, "2: DeviceMsr", log.Fields{"Device": deviceID, "Vnet": oldVnetID, "Len": vd.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301743 if msrListIntf, ok := vd.MigratingServices.Get(oldVnetID); ok {
1744 msrList := msrListIntf.(*util.ConcurrentMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301745 logger.Debugw(ctx, "2: MsrListLen", log.Fields{"Len": msrList.Length(), "Vnet": oldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301746 if msrObj, ok := msrList.Get(requestID); ok {
1747 return msrObj.(*MigrateServicesRequest)
1748 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301749 }
1750 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301751 logger.Warnw(ctx, "Device Not Found", log.Fields{"DeviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301752 return nil
1753}
1754
vinokuma926cb3e2023-03-29 11:41:06 +05301755// updateMigrateServicesRequest - Updates the device with updated msr
Naveen Sampath04696f72022-06-13 15:19:14 +05301756func (va *VoltApplication) updateMigrateServicesRequest(deviceID string, oldVnetID string, requestID string, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301757 logger.Debugw(ctx, "Update Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301758 if vd := va.GetDevice(deviceID); vd != nil {
1759 if msrList, ok := vd.MigratingServices.Get(oldVnetID); ok {
1760 if _, ok := msrList.(*util.ConcurrentMap).Get(requestID); ok {
1761 msrList.(*util.ConcurrentMap).Set(requestID, msr)
1762 }
1763 }
1764 }
1765}
1766
vinokuma926cb3e2023-03-29 11:41:06 +05301767// updateVnetProfile - Called on flow process completion
1768// Removes old service and creates new VPV & service with updated vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301769func (vs *VoltService) updateVnetProfile(cntx context.Context, deviceID string) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301770 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 +05301771
1772 nvs := VoltService{}
1773 nvs.VoltServiceCfg = vs.VoltServiceCfg
1774 nvs.Device = vs.Device
1775 nvs.Ipv4Addr = vs.Ipv4Addr
1776 nvs.Ipv6Addr = vs.Ipv6Addr
1777 nvs.UsMeterID = vs.UsMeterID
1778 nvs.DsMeterID = vs.DsMeterID
1779 nvs.AggDsMeterID = vs.AggDsMeterID
1780 nvs.UsHSIAFlowsApplied = vs.UsHSIAFlowsApplied
1781 nvs.DsHSIAFlowsApplied = vs.DsHSIAFlowsApplied
1782 nvs.UsDhcpFlowsApplied = vs.UsDhcpFlowsApplied
1783 nvs.DsDhcpFlowsApplied = vs.DsDhcpFlowsApplied
1784 nvs.IgmpFlowsApplied = vs.IgmpFlowsApplied
1785 nvs.Icmpv6FlowsApplied = vs.Icmpv6FlowsApplied
1786 nvs.PendingFlows = vs.PendingFlows
1787 nvs.AssociatedFlows = vs.AssociatedFlows
1788 nvs.DeleteInProgress = vs.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301789 nvs.DeactivateInProgress = vs.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301790 nvs.ForceDelete = vs.ForceDelete
1791 nvs.BwAvailInfo = vs.BwAvailInfo
1792 nvs.UpdateInProgress = vs.UpdateInProgress
1793
1794 if nvs.DeleteInProgress {
1795 logger.Warnw(ctx, "Skipping Service Migration. Service Delete in Progress", log.Fields{"Device": deviceID, "Service": vs.Name, "Vnet": vs.VnetID})
1796 return
1797 }
1798
1799 metadata := vs.Metadata.(*MigrateServiceMetadata)
1800 oldVnetID := vs.VnetID
Naveen Sampath04696f72022-06-13 15:19:14 +05301801 oldSrvName := vs.Name
1802
1803 if metadata == nil || metadata.NewVnetID == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301804 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 +05301805 return
1806 }
1807
vinokuma926cb3e2023-03-29 11:41:06 +05301808 nvs.VnetID = metadata.NewVnetID
1809 id := metadata.RequestID
1810
1811 // First add the new service and then only delete the old service
Naveen Sampath04696f72022-06-13 15:19:14 +05301812 // Since if post del service in case of pod crash or reboot, the service data will be lost
1813 va := GetApplication()
1814 msr := va.getMigrateServicesRequest(deviceID, oldVnetID, id)
1815 vnets := strings.Split(metadata.NewVnetID, "-")
1816 svlan, _ := strconv.Atoi(vnets[0])
1817 nvs.SVlan = of.VlanType(svlan)
1818 nvs.UpdateInProgress = false
1819 nvs.Metadata = nil
1820 nvs.Trigger = ServiceVlanUpdate
1821
1822 svcName := vs.Port + "-" + strconv.FormatUint(uint64(nvs.SVlan), 10) + "-"
1823 svcName = svcName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1824 nvs.Name = svcName + strconv.FormatUint(uint64(vs.TechProfileID), 10)
1825
vinokuma926cb3e2023-03-29 11:41:06 +05301826 // TODO:Nav Pass a copy, not the pointer
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301827 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 +05301828 if err := va.AddService(cntx, nvs.VoltServiceCfg, &nvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301829 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": nvs.Name, "Error": err})
1830 }
1831 logger.Infow(ctx, "Add New Service Triggered", log.Fields{"Service": nvs.Name, "US": nvs.UsHSIAFlowsApplied, "DS": nvs.DsHSIAFlowsApplied, "DelFlag": nvs.DeleteInProgress})
1832
1833 msr.ServicesList[oldSrvName] = true
1834 va.updateMigrateServicesRequest(deviceID, oldVnetID, id, msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301835 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301836
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301837 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 +05301838 va.DelService(cntx, oldSrvName, true, nil, true)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301839 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 +05301840 msr.serviceMigrated(cntx, oldSrvName)
Naveen Sampath04696f72022-06-13 15:19:14 +05301841}
1842
vinokuma926cb3e2023-03-29 11:41:06 +05301843// serviceMigrated - called on successful service updation
Naveen Sampath04696f72022-06-13 15:19:14 +05301844// Removes the service entry from servicelist and deletes the request on process completion
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301845func (msr *MigrateServicesRequest) serviceMigrated(cntx context.Context, serviceName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301846 logger.Infow(ctx, "Service Migrated", log.Fields{"ServiceName": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05301847 msr.MigrateServicesLock.Lock()
1848 defer msr.MigrateServicesLock.Unlock()
1849
1850 delete(msr.ServicesList, serviceName)
1851
1852 if len(msr.ServicesList) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301853 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301854 return
1855 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301856 msr.WriteToDB(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +05301857 // TODO:Nav - Need for any Response to SubMgr?
Naveen Sampath04696f72022-06-13 15:19:14 +05301858}
1859
vinokuma926cb3e2023-03-29 11:41:06 +05301860// TriggerPendingMigrateServicesReq - trigger pending service request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301861func (va *VoltApplication) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
1862 va.FetchAndProcessAllMigrateServicesReq(cntx, device, storeAndProcessMigrateSrvRequest)
Naveen Sampath04696f72022-06-13 15:19:14 +05301863}
1864
vinokuma926cb3e2023-03-29 11:41:06 +05301865// FetchAndProcessAllMigrateServicesReq - fetch all pending migrate services req from DB and process based on provided func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301866func (va *VoltApplication) FetchAndProcessAllMigrateServicesReq(cntx context.Context, device string, msrAction func(context.Context, *MigrateServicesRequest)) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301867 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 +05301868 msrList, _ := db.GetAllMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301869 for _, msr := range msrList {
1870 b, ok := msr.Value.([]byte)
1871 if !ok {
1872 logger.Warn(ctx, "The value type is not []byte")
1873 continue
1874 }
1875 msr := va.createMigrateServicesFromString(b)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301876 msrAction(cntx, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301877 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 +05301878 }
1879}
1880
1881// createMigrateServicesFromString to create Service from string
1882func (va *VoltApplication) createMigrateServicesFromString(b []byte) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301883 logger.Info(ctx, "Create Migrate Services From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05301884 var msr MigrateServicesRequest
1885 if err := json.Unmarshal(b, &msr); err == nil {
1886 logger.Debugw(ctx, "Adding Migrate Services Request From Db", log.Fields{"Vlan": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301887 } else {
1888 logger.Warn(ctx, "Unmarshal failed")
1889 }
1890 return &msr
1891}
1892
vinokuma926cb3e2023-03-29 11:41:06 +05301893// storeAndProcessMigrateSrvRequest - stores the msr info in device obj and triggers req
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301894func storeAndProcessMigrateSrvRequest(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301895 logger.Infow(ctx, "Store And Process Migrate Srv Request", log.Fields{"MsrID": msr.DeviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301896 d := GetApplication().GetDevice(msr.DeviceID)
1897 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301898 msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301899}
1900
vinokuma926cb3e2023-03-29 11:41:06 +05301901// forceUpdateAllServices - force udpate services with new vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301902func forceUpdateAllServices(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301903 logger.Infow(ctx, "Force udpate services with new vnet profile", log.Fields{"MsrID": msr.NewVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301904 for srv := range msr.ServicesList {
1905 if vsIntf, ok := GetApplication().ServiceByName.Load(srv); ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301906 vsIntf.(*VoltService).updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301907 }
1908 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301909 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301910}
1911
vinokuma926cb3e2023-03-29 11:41:06 +05301912// nolint: gocyclo
1913// DeepEqualServicecfg - checks if the given service cfgs are same
Naveen Sampath04696f72022-06-13 15:19:14 +05301914func (va *VoltApplication) DeepEqualServicecfg(evs *VoltServiceCfg, nvs *VoltServiceCfg) bool {
1915 if nvs.Name != evs.Name {
1916 return false
1917 }
1918 if nvs.UniVlan != evs.UniVlan {
1919 return false
1920 }
1921 if nvs.CVlan != evs.CVlan {
1922 return false
1923 }
1924 if nvs.SVlan != evs.SVlan {
1925 return false
1926 }
1927 if nvs.SVlanTpid != 0 && nvs.SVlanTpid != evs.SVlanTpid {
1928 return false
1929 }
1930 if !util.IsPbitSliceSame(nvs.Pbits, evs.Pbits) {
1931 return false
1932 }
1933 if !reflect.DeepEqual(nvs.DsRemarkPbitsMap, evs.DsRemarkPbitsMap) {
1934 return false
1935 }
1936 if nvs.TechProfileID != evs.TechProfileID {
1937 return false
1938 }
1939 if nvs.CircuitID != evs.CircuitID {
1940 return false
1941 }
1942 if !bytes.Equal(nvs.RemoteID, evs.RemoteID) {
1943 return false
1944 }
1945 if nvs.Port != evs.Port {
1946 return false
1947 }
1948 if nvs.PonPort != evs.PonPort {
1949 return false
1950 }
1951 if evs.MacLearning == MacLearningNone && !util.MacAddrsMatch(nvs.MacAddr, evs.MacAddr) {
1952 return false
1953 }
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05301954 if nvs.IsOption82Enabled != evs.IsOption82Enabled {
Naveen Sampath04696f72022-06-13 15:19:14 +05301955 return false
1956 }
1957 if nvs.IgmpEnabled != evs.IgmpEnabled {
1958 return false
1959 }
1960 if nvs.McastService != evs.McastService {
1961 return false
1962 }
1963 if nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification {
1964 return false
1965 }
1966 if nvs.UsMeterProfile != evs.UsMeterProfile {
1967 return false
1968 }
1969 if nvs.DsMeterProfile != evs.DsMeterProfile {
1970 return false
1971 }
1972 if nvs.AggDsMeterProfile != evs.AggDsMeterProfile {
1973 return false
1974 }
1975 if nvs.VnetID != evs.VnetID {
1976 return false
1977 }
1978 if nvs.MvlanProfileName != evs.MvlanProfileName {
1979 return false
1980 }
1981 if nvs.RemoteIDType != evs.RemoteIDType {
1982 return false
1983 }
1984 if nvs.SchedID != evs.SchedID {
1985 return false
1986 }
1987 if nvs.AllowTransparent != evs.AllowTransparent {
1988 return false
1989 }
1990 if nvs.EnableMulticastKPI != evs.EnableMulticastKPI {
1991 return false
1992 }
1993 if nvs.DataRateAttr != evs.DataRateAttr {
1994 return false
1995 }
1996 if nvs.MinDataRateUs != evs.MinDataRateUs {
1997 return false
1998 }
1999 if nvs.MinDataRateDs != evs.MinDataRateDs {
2000 return false
2001 }
2002 if nvs.MaxDataRateUs != evs.MaxDataRateUs {
2003 return false
2004 }
2005 if nvs.MaxDataRateDs != evs.MaxDataRateDs {
2006 return false
2007 }
2008
2009 return true
2010}
2011
vinokuma926cb3e2023-03-29 11:41:06 +05302012// TriggerAssociatedFlowDelete - re-trigger service flow delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05302013func (vs *VoltService) TriggerAssociatedFlowDelete(cntx context.Context) bool {
vinokuma926cb3e2023-03-29 11:41:06 +05302014 // Clear the Flows flag if already set
2015 // This case happens only in case of some race condition
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302016 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": vs.Device, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05302017 if vs.UsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302018 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302019 logger.Warnw(ctx, "DelUsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302020 }
2021 }
2022
2023 if vs.DsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302024 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302025 logger.Warnw(ctx, "DelDsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302026 }
2027 }
2028
2029 vs.ServiceLock.Lock()
2030 cookieList := []uint64{}
2031 for cookie := range vs.AssociatedFlows {
2032 cookieList = append(cookieList, convertToUInt64(cookie))
2033 }
2034 vs.ServiceLock.Unlock()
2035
2036 if len(cookieList) == 0 {
2037 return false
2038 }
2039
vinokuma926cb3e2023-03-29 11:41:06 +05302040 // Trigger Flow Delete
Naveen Sampath04696f72022-06-13 15:19:14 +05302041 for _, cookie := range cookieList {
2042 if vd := GetApplication().GetDevice(vs.Device); vd != nil {
2043 flow := &of.VoltFlow{}
2044 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
2045 subFlow := of.NewVoltSubFlow()
2046 subFlow.Cookie = cookie
2047 flow.SubFlows[cookie] = subFlow
2048 logger.Infow(ctx, "Retriggering Service Delete Flow", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302049 if err := vs.DelFlows(cntx, vd, flow, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302050 logger.Warnw(ctx, "DelFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302051 }
2052 }
2053 }
2054 return true
2055}
2056
vinokuma926cb3e2023-03-29 11:41:06 +05302057// triggerServiceInProgressInd - Indication is generated when Service is not provisioned after add serviec req from NB
Naveen Sampath04696f72022-06-13 15:19:14 +05302058func (vs *VoltService) triggerServiceInProgressInd() {
2059}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302060
vinokuma926cb3e2023-03-29 11:41:06 +05302061// JSONMarshal wrapper function for json Marshal VoltService
2062func (vs *VoltService) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302063 return json.Marshal(VoltService{
2064 VoltServiceCfg: vs.VoltServiceCfg,
2065 VoltServiceOper: VoltServiceOper{
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302066 Device: vs.VoltServiceOper.Device,
2067 Ipv4Addr: vs.VoltServiceOper.Ipv4Addr,
2068 Ipv6Addr: vs.VoltServiceOper.Ipv6Addr,
2069 UsMeterID: vs.VoltServiceOper.UsMeterID,
2070 DsMeterID: vs.VoltServiceOper.DsMeterID,
2071 AggDsMeterID: vs.VoltServiceOper.AggDsMeterID,
2072 UsHSIAFlowsApplied: vs.VoltServiceOper.UsHSIAFlowsApplied,
2073 DsHSIAFlowsApplied: vs.VoltServiceOper.DsHSIAFlowsApplied,
2074 UsDhcpFlowsApplied: vs.VoltServiceOper.UsDhcpFlowsApplied,
2075 DsDhcpFlowsApplied: vs.VoltServiceOper.DsDhcpFlowsApplied,
2076 IgmpFlowsApplied: vs.VoltServiceOper.IgmpFlowsApplied,
2077 Icmpv6FlowsApplied: vs.VoltServiceOper.Icmpv6FlowsApplied,
2078 PendingFlows: vs.VoltServiceOper.PendingFlows,
2079 AssociatedFlows: vs.VoltServiceOper.AssociatedFlows,
2080 DeleteInProgress: vs.VoltServiceOper.DeleteInProgress,
2081 DeactivateInProgress: vs.VoltServiceOper.DeactivateInProgress,
2082 ForceDelete: vs.VoltServiceOper.ForceDelete,
2083 BwAvailInfo: vs.VoltServiceOper.BwAvailInfo,
2084 UpdateInProgress: vs.VoltServiceOper.UpdateInProgress,
2085 Metadata: vs.VoltServiceOper.Metadata,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302086 },
2087 })
2088}
Tinoj Josephec742f62022-09-29 19:11:10 +05302089
2090// GetProgrammedSubscribers to get list of programmed subscribers
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302091func (va *VoltApplication) GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302092 var svcList []*VoltService
2093 logger.Infow(ctx, "GetProgrammedSubscribers Request ", log.Fields{"Device": deviceID, "Port": portNo})
2094 va.ServiceByName.Range(func(key, value interface{}) bool {
2095 vs := value.(*VoltService)
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302096 if len(deviceID) > 0 {
2097 if len(portNo) > 0 {
Tinoj Josephec742f62022-09-29 19:11:10 +05302098 if deviceID == vs.Device && portNo == vs.Port {
2099 svcList = append(svcList, vs)
2100 }
2101 } else {
2102 if deviceID == vs.Device {
2103 svcList = append(svcList, vs)
2104 }
2105 }
2106 } else {
2107 svcList = append(svcList, vs)
2108 }
2109 return true
2110 })
2111 return svcList, nil
2112}
2113
Akash Soni634d9bf2023-07-10 12:11:10 +05302114type FlowProvisionStatus struct {
2115 FlowProvisionStatus string
2116}
2117
2118// GetFlowProvisionStatus to get status of the subscriber and flow provisioned in controller
Akash Soni3c391e72023-08-16 12:21:33 +05302119func (va *VoltApplication) GetFlowProvisionStatus(portNo string) FlowProvisionStatus {
Akash Soni634d9bf2023-07-10 12:11:10 +05302120 logger.Infow(ctx, "GetFlowProvisionStatus Request ", log.Fields{"Port": portNo})
2121 flowProvisionStatus := FlowProvisionStatus{}
Akash Soni3c391e72023-08-16 12:21:33 +05302122 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
Akash Soni634d9bf2023-07-10 12:11:10 +05302123 va.ServiceByName.Range(func(key, value interface{}) bool {
2124 vs := value.(*VoltService)
2125 logger.Debugw(ctx, "Volt Service ", log.Fields{"VS": vs})
Akash Soni3c391e72023-08-16 12:21:33 +05302126 if portNo == vs.Port {
2127 if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() == 0 {
2128 flowProvisionStatus.FlowProvisionStatus = ALL_FLOWS_PROVISIONED
2129 return false
2130 } else if !vs.IsActivated {
2131 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_DISABLED_IN_CONTROLLER
2132 return false
2133 } else if !vs.DsHSIAFlowsApplied && !vs.UsHSIAFlowsApplied {
2134 flowProvisionStatus.FlowProvisionStatus = NO_FLOWS_PROVISIONED
2135 return false
Akash Soni230e6212023-10-16 10:46:07 +05302136 } else if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() > 0 {
Akash Soni3c391e72023-08-16 12:21:33 +05302137 flowProvisionStatus.FlowProvisionStatus = FLOWS_PROVISIONED_PARTIALLY
2138 return false
Akash Soni634d9bf2023-07-10 12:11:10 +05302139 }
2140 }
2141 return true
2142 })
Akash Soni634d9bf2023-07-10 12:11:10 +05302143 return flowProvisionStatus
2144}
2145
2146func (vs *VoltService) LenOfPendingFlows() int {
2147 vs.ServiceLock.RLock()
2148 lth := len(vs.PendingFlows)
2149 vs.ServiceLock.RUnlock()
2150 return lth
2151}
2152
Tinoj Josephec742f62022-09-29 19:11:10 +05302153// ActivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302154func (va *VoltApplication) ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302155 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 +05302156 device, err := va.GetDeviceFromPort(portNo)
2157 if err != nil {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302158 // Lets activate the service even though port was not found. We will push the flows once the port is added by voltha
2159 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 +05302160 }
2161 // If device id is not provided check only port number
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302162 if device != nil {
2163 if deviceID == DeviceAny {
2164 deviceID = device.Name
2165 } else if deviceID != device.Name {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302166 err := errorCodes.ErrDeviceNotFound
2167 return fmt.Errorf("wrong device id %s : %w", deviceID, err)
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302168 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302169 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302170 va.ServiceByName.Range(func(key, value interface{}) bool {
2171 vs := value.(*VoltService)
Tinoj Josephec742f62022-09-29 19:11:10 +05302172 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302173 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302174 logger.Warnw(ctx, "Service Activate Request Does not match", log.Fields{"Device": deviceID, "voltService": vs})
Tinoj Josephec742f62022-09-29 19:11:10 +05302175 return true
2176 }
2177 if portNo == vs.Port && !vs.IsActivated {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302178 // 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 +05302179 logger.Debugw(ctx, "Service Activate", log.Fields{"Name": vs.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05302180 vs.IsActivated = true
2181 va.ServiceByName.Store(vs.Name, vs)
2182 vs.WriteToDb(cntx)
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302183
2184 // Push the flows only if the port is already added and we have a valid device
2185 if device != nil {
2186 p := device.GetPort(vs.Port)
2187 if p == nil {
2188 logger.Warnw(ctx, "Wrong device or port", log.Fields{"Device": deviceID, "Port": portNo})
2189 return true
2190 }
2191 // If port is already up send indication to vpv
2192 if p.State == PortStateUp {
2193 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2194 // PortUp call initiates flow addition
2195 vpv.PortUpInd(cntx, device, portNo)
2196 } else {
2197 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2198 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302199 }
2200 }
2201 }
2202 return true
2203 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302204 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302205}
2206
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302207func (vs *VoltService) SetSvcDeactivationFlags(deactivateRsn SvcDeactivateReason) {
2208 vs.DeactivateInProgress = true
2209 vs.IsActivated = false
2210 vs.ServiceDeactivateReason = deactivateRsn
2211}
2212
Tinoj Josephec742f62022-09-29 19:11:10 +05302213// DeactivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302214func (va *VoltApplication) DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Akash Sonief452f12024-12-12 18:20:28 +05302215 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 +05302216
Tinoj Josephec742f62022-09-29 19:11:10 +05302217 va.ServiceByName.Range(func(key, value interface{}) bool {
2218 vs := value.(*VoltService)
2219 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302220 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302221 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 +05302222 return true
2223 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302224 if portNo == vs.Port && vs.IsActivated {
Sridhar Ravindra3ec14232024-01-01 19:11:48 +05302225 vs.SetSvcDeactivationFlags(SvcDeacRsn_NB)
Tinoj Josephec742f62022-09-29 19:11:10 +05302226 va.ServiceByName.Store(vs.Name, vs)
2227 vs.WriteToDb(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302228 device, err := va.GetDeviceFromPort(portNo)
2229 if err != nil {
2230 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
2231 // So no error is returned
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302232 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portNo})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302233 return true
2234 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302235 p := device.GetPort(vs.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05302236 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302237 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2238 // Port down call internally deletes all the flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302239 vpv.PortDownInd(cntx, deviceID, portNo, true, false)
Tinoj Josephec742f62022-09-29 19:11:10 +05302240 if vpv.IgmpEnabled {
2241 va.ReceiverDownInd(cntx, deviceID, portNo)
2242 }
2243 } else {
2244 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2245 }
2246 }
Akash Sonief452f12024-12-12 18:20:28 +05302247 vs.DeactivateInProgress = false
2248 va.ServiceByName.Store(vs.Name, vs)
2249 vs.WriteToDb(cntx)
Tinoj Josephec742f62022-09-29 19:11:10 +05302250 }
2251 return true
2252 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302253 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302254}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302255
vinokuma926cb3e2023-03-29 11:41:06 +05302256// GetServicePbit to get first set bit in the pbit map
2257// returns -1 : If configured to match on all pbits
2258// returns 8 : If no pbits are configured
2259// returns first pbit if specific pbit is configured
Tinoj Josephec742f62022-09-29 19:11:10 +05302260func (vs *VoltService) GetServicePbit() int {
2261 if vs.IsPbitExist(of.PbitMatchAll) {
2262 return -1
2263 }
vinokuma926cb3e2023-03-29 11:41:06 +05302264 for pbit := 0; pbit < int(of.PbitMatchNone); pbit++ {
Tinoj Josephec742f62022-09-29 19:11:10 +05302265 if vs.IsPbitExist(of.PbitType(pbit)) {
2266 return pbit
2267 }
2268 }
2269 return int(of.PbitMatchNone)
2270}