blob: 6c44450443f240070d2b595df049387768d8c62a [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053014 */
Naveen Sampath04696f72022-06-13 15:19:14 +053015
16package application
17
18import (
19 "bytes"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053020 "context"
Naveen Sampath04696f72022-06-13 15:19:14 +053021 "encoding/json"
22 "errors"
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +053023 "fmt"
Naveen Sampath04696f72022-06-13 15:19:14 +053024 "net"
25 "reflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053026 "sort"
27 "strconv"
28 "strings"
29 "sync"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053030 infraerrorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053031
32 "github.com/google/gopacket/layers"
33
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053034 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053035 "voltha-go-controller/internal/pkg/controller"
36 cntlr "voltha-go-controller/internal/pkg/controller"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053037 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053038 "voltha-go-controller/internal/pkg/of"
39 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053040 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053041)
42
43const (
44 // DSLAttrEnabled constant
45 DSLAttrEnabled string = "ENABLED"
Tinoj Josephec742f62022-09-29 19:11:10 +053046 // DeviceAny constant
47 DeviceAny string = "DEVICE-ANY"
Akash Soni634d9bf2023-07-10 12:11:10 +053048
49 ALL_FLOWS_PROVISIONED string = "ALL_FLOWS_PROVISIONED"
50
51 NO_FLOWS_PROVISIONED string = "NO_FLOWS_PROVISIONED"
52
53 FLOWS_PROVISIONED_PARTIALLY string = "FLOWS_PROVISIONED_PARTIALLY"
54
55 SUBSCRIBER_DISABLED_IN_CONTROLLER string = "DISABLED_IN_CONTROLLER"
56
57 SUBSCRIBER_NOT_IN_CONTROLLER string = "NOT_IN_CONTROLLER"
58
59 ONT_FLOWS_PROVISION_STATE_UNUSED string = "ONT_FLOWS_PROVISION_STATE_UNUSED"
Naveen Sampath04696f72022-06-13 15:19:14 +053060)
61
62// VoltServiceCfg structure
63// Name - Uniquely identifies a service across the entire application
64// UniVlan - The VLAN of the packets entering the UNI of ONU
65// CVlan - The VLAN to transalate to/from on the PON link
66// SVlan - The outer VLAN to be used on the NNI of OLT.
vinokuma926cb3e2023-03-29 11:41:06 +053067// - In general, 4096 is used as NO VLAN for all the above
68// SVlanTpid - SVlan Tag Protocol Identifier
Naveen Sampath04696f72022-06-13 15:19:14 +053069// Pbits - Each bit of uint8 represents one p-bit. MSB is pbit 7
70// DhcpRelay - Whether it is turned on/off
71// CircuitId - The circuit id to be used with DHCP relay. Unused otherwise
72// RemoveId - Same as above
73// Port - The access port for the service. Each service has a single access
vinokuma926cb3e2023-03-29 11:41:06 +053074// port. The converse is not always true
Naveen Sampath04696f72022-06-13 15:19:14 +053075// MacLearning - If MAC learning is turned on, the MAC address learned from the
vinokuma926cb3e2023-03-29 11:41:06 +053076// the service activation is used in programming flows
Naveen Sampath04696f72022-06-13 15:19:14 +053077// MacAddress - The MAC hardware address learnt on the UNI interface
78// MacAddresses - Not yet implemented. To be used to learn more MAC addresses
79type VoltServiceCfg struct {
Naveen Sampath04696f72022-06-13 15:19:14 +053080 Pbits []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +053081 Name string
Naveen Sampath04696f72022-06-13 15:19:14 +053082 CircuitID string
Naveen Sampath04696f72022-06-13 15:19:14 +053083 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +053084 UsMeterProfile string
85 DsMeterProfile string
86 AggDsMeterProfile string
87 VnetID string
88 MvlanProfileName string
89 RemoteIDType string
Naveen Sampath04696f72022-06-13 15:19:14 +053090 DataRateAttr string
vinokuma926cb3e2023-03-29 11:41:06 +053091 ServiceType string
92 DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
93 RemoteID []byte
94 MacAddr net.HardwareAddr
95 ONTEtherTypeClassification int
96 SchedID int
97 Trigger ServiceTrigger
98 MacLearning MacLearningType
99 PonPort uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530100 MinDataRateUs uint32
101 MinDataRateDs uint32
102 MaxDataRateUs uint32
103 MaxDataRateDs uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530104 TechProfileID uint16
105 SVlanTpid layers.EthernetType
106 UniVlan of.VlanType
107 CVlan of.VlanType
108 SVlan of.VlanType
109 UsPonCTagPriority of.PbitType
110 UsPonSTagPriority of.PbitType
111 DsPonSTagPriority of.PbitType
112 DsPonCTagPriority of.PbitType
113 VlanControl VlanControl
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530114 IsOption82Enabled bool
vinokuma926cb3e2023-03-29 11:41:06 +0530115 IgmpEnabled bool
116 McastService bool
117 AllowTransparent bool
118 EnableMulticastKPI bool
Tinoj Josephec742f62022-09-29 19:11:10 +0530119 IsActivated bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530120}
121
122// VoltServiceOper structure
123type VoltServiceOper struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530124 Metadata interface{}
125 PendingFlows map[string]bool
126 AssociatedFlows map[string]bool
127 BwAvailInfo string
Naveen Sampath04696f72022-06-13 15:19:14 +0530128 //MacLearning bool
129 //MacAddr net.HardwareAddr
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530130 Device string
131 Ipv4Addr net.IP
132 Ipv6Addr net.IP
133 ServiceLock sync.RWMutex `json:"-"`
134 UsMeterID uint32
135 DsMeterID uint32
136 AggDsMeterID uint32
137 UpdateInProgress bool
138 DeleteInProgress bool
139 DeactivateInProgress bool
140 ForceDelete bool
vinokuma926cb3e2023-03-29 11:41:06 +0530141 // Multiservice-Fix
Naveen Sampath04696f72022-06-13 15:19:14 +0530142 UsHSIAFlowsApplied bool
143 DsHSIAFlowsApplied bool
144 UsDhcpFlowsApplied bool
145 DsDhcpFlowsApplied bool
146 IgmpFlowsApplied bool
147 Icmpv6FlowsApplied bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530148}
149
150// VoltService structure
151type VoltService struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530152 VoltServiceOper
153 Version string
vinokuma926cb3e2023-03-29 11:41:06 +0530154 VoltServiceCfg
Naveen Sampath04696f72022-06-13 15:19:14 +0530155}
156
vinokuma926cb3e2023-03-29 11:41:06 +0530157// ServiceTrigger - Service activation trigger
Naveen Sampath04696f72022-06-13 15:19:14 +0530158type ServiceTrigger int
159
160const (
vinokuma926cb3e2023-03-29 11:41:06 +0530161 // NBActivate - Service added due to NB Action
Naveen Sampath04696f72022-06-13 15:19:14 +0530162 NBActivate ServiceTrigger = 0
vinokuma926cb3e2023-03-29 11:41:06 +0530163 // ServiceVlanUpdate - Service added due to Svlan Update
Naveen Sampath04696f72022-06-13 15:19:14 +0530164 ServiceVlanUpdate ServiceTrigger = 1
165)
166
167// AppMutexes structure
168type AppMutexes struct {
169 ServiceDataMutex sync.Mutex `json:"-"`
170 VnetMutex sync.Mutex `json:"-"`
171}
172
vinokuma926cb3e2023-03-29 11:41:06 +0530173// MigrateServiceMetadata - migrate services request metadata
Naveen Sampath04696f72022-06-13 15:19:14 +0530174type MigrateServiceMetadata struct {
175 NewVnetID string
176 RequestID string
177}
178
179// AppMutex variable
180var AppMutex AppMutexes
181
182// NewVoltService for constructor for volt service
183func NewVoltService(cfg *VoltServiceCfg) *VoltService {
184 var vs VoltService
185 vs.VoltServiceCfg = *cfg
186 vs.UsHSIAFlowsApplied = false
187 vs.DsHSIAFlowsApplied = false
188 vs.DeleteInProgress = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530189 vs.DeactivateInProgress = false
Naveen Sampath04696f72022-06-13 15:19:14 +0530190 //vs.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530191 vs.IsOption82Enabled = cfg.IsOption82Enabled
Naveen Sampath04696f72022-06-13 15:19:14 +0530192 vs.MacAddr = cfg.MacAddr
193 vs.Ipv4Addr = net.ParseIP("0.0.0.0")
194 vs.Ipv6Addr = net.ParseIP("::")
195 vs.PendingFlows = make(map[string]bool)
196 vs.AssociatedFlows = make(map[string]bool)
197 return &vs
198}
199
200// WriteToDb commit a service to the DB if service delete is not in-progress
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530201func (vs *VoltService) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530202 vs.ServiceLock.RLock()
203 defer vs.ServiceLock.RUnlock()
204
205 if vs.DeleteInProgress {
206 logger.Warnw(ctx, "Skipping Redis Update for Service, Service delete in progress", log.Fields{"Service": vs.Name})
207 return
208 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530209 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530210}
211
vinokuma926cb3e2023-03-29 11:41:06 +0530212// ForceWriteToDb force commit a service to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530213func (vs *VoltService) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530214 b, err := json.Marshal(vs)
215
216 if err != nil {
217 logger.Errorw(ctx, "Json Marshal Failed for Service", log.Fields{"Service": vs.Name})
218 return
219 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530220 if err1 := db.PutService(cntx, vs.Name, string(b)); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530221 logger.Errorw(ctx, "DB write oper failed for Service", log.Fields{"Service": vs.Name})
222 }
223}
224
225// isDataRateAttrPresent to check if data attribute is present
226func (vs *VoltService) isDataRateAttrPresent() bool {
227 return vs.DataRateAttr == DSLAttrEnabled
228}
229
230// DelFromDb delete a service from DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530231func (vs *VoltService) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530232 logger.Debugw(ctx, "Deleting Service from DB", log.Fields{"Name": vs.Name})
vinokuma926cb3e2023-03-29 11:41:06 +0530233 // TODO - Need to understand and delete the second call
234 // Calling twice has worked though don't know why
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530235 _ = db.DelService(cntx, vs.Name)
236 _ = db.DelService(cntx, vs.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530237}
238
239// MatchesVlans find the service that matches the VLANs. In this case it is
240// purely based on CVLAN. The CVLAN can sufficiently be used to
241// match a service
242func (vs *VoltService) MatchesVlans(vlans []of.VlanType) bool {
243 if len(vlans) != 1 {
244 return false
245 }
246
247 if vlans[0] == vs.CVlan {
248 return true
249 }
250 return false
251}
252
253// MatchesPbits allows matching a service to a pbit. This is used
254// to search for a service matching the pbits, typically to identify
255// attributes for other flows such as DHCP, IGMP, etc.
256func (vs *VoltService) MatchesPbits(pbits []of.PbitType) bool {
257 for _, pbit := range pbits {
258 for _, pb := range vs.Pbits {
259 if pb == pbit {
260 return true
261 }
262 }
263 }
264 return false
265}
266
267// IsPbitExist allows matching a service to a pbit. This is used
268// to search for a service matching the pbit
269func (vs *VoltService) IsPbitExist(pbit of.PbitType) bool {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530270 logger.Debugw(ctx, "Request for IsPbitExist", log.Fields{"pbit": pbit})
Naveen Sampath04696f72022-06-13 15:19:14 +0530271 for _, pb := range vs.Pbits {
272 if pb == pbit {
273 return true
274 }
275 }
276 return false
277}
278
279// AddHsiaFlows - Adds US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530280func (vs *VoltService) AddHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530281 logger.Debugw(ctx, "Add US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530282 if err := vs.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530283 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
284 vs.triggerServiceFailureInd(statusCode, statusMessage)
285 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530286 if err := vs.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530287 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
288 vs.triggerServiceFailureInd(statusCode, statusMessage)
289 }
290}
291
vinokuma926cb3e2023-03-29 11:41:06 +0530292// DelHsiaFlows - Deletes US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530293func (vs *VoltService) DelHsiaFlows(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530294 logger.Debugw(ctx, "Delete US & DS HSIA Flows for the service", log.Fields{"ServiceName": vs.Name})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530295 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530296 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
297 vs.triggerServiceFailureInd(statusCode, statusMessage)
298 }
299
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530300 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530301 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
302 vs.triggerServiceFailureInd(statusCode, statusMessage)
303 }
304}
305
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530306func (vs *VoltService) AddMeterToDevice(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530307 logger.Debugw(ctx, "Add Meter To Device for the service", log.Fields{"ServiceName": vs.Name})
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530308 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530309 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 +0530310 }
311 va := GetApplication()
312 logger.Infow(ctx, "Configuring Meters for FTTB", log.Fields{"ServiceName": vs.Name})
313 device, err := va.GetDeviceFromPort(vs.Port)
314 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530315 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 +0530316 } else if device.State != controller.DeviceStateUP {
317 logger.Warnw(ctx, "Device state Down. Ignoring Meter Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
318 return nil
319 }
320 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
321 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
322 return nil
323}
324
Naveen Sampath04696f72022-06-13 15:19:14 +0530325// AddUsHsiaFlows - Add US HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530326func (vs *VoltService) AddUsHsiaFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530327 logger.Infow(ctx, "Configuring US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530328 if vs.DeleteInProgress || vs.UpdateInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530329 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 +0530330 return nil
331 }
332
333 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530334 if !vs.UsHSIAFlowsApplied || vgcRebooted {
335 device, err := va.GetDeviceFromPort(vs.Port)
336 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530337 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 +0530338 } else if device.State != controller.DeviceStateUP {
339 logger.Warnw(ctx, "Device state Down. Ignoring US HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
340 return nil
341 }
342
343 vs.Device = device.Name
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530344 /* In case of DPU_MGMT_TRAFFIC the meters will be configured before US flow creation*/
vinokuma926cb3e2023-03-29 11:41:06 +0530345 if vs.ServiceType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530346 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
347 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
348 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530349 pBits := vs.Pbits
350
vinokuma926cb3e2023-03-29 11:41:06 +0530351 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530352 if len(vs.Pbits) == 0 {
353 pBits = append(pBits, PbitMatchNone)
354 }
355 for _, pbits := range pBits {
356 usflows, err := vs.BuildUsHsiaFlows(pbits)
357 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530358 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 +0530359 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
360 vs.triggerServiceFailureInd(statusCode, statusMessage)
361 continue
362 }
363 usflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530364 if err := vs.AddFlows(cntx, device, usflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530365 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 +0530366 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
367 vs.triggerServiceFailureInd(statusCode, statusMessage)
368 }
369 }
370 vs.UsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530371 logger.Debugw(ctx, "Pushed US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530372 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530373 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530374 return nil
375}
376
377// AddDsHsiaFlows - Add DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530378func (vs *VoltService) AddDsHsiaFlows(cntx context.Context) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530379 logger.Infow(ctx, "Configuring DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530380 if vs.DeleteInProgress {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530381 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 +0530382 return nil
383 }
384
385 va := GetApplication()
Naveen Sampath04696f72022-06-13 15:19:14 +0530386 if !vs.DsHSIAFlowsApplied || vgcRebooted {
387 device, err := va.GetDeviceFromPort(vs.Port)
388 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530389 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 +0530390 } else if device.State != controller.DeviceStateUP {
391 logger.Warnw(ctx, "Device state Down. Ignoring DS HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
392 return nil
393 }
394
395 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
Naveen Sampath04696f72022-06-13 15:19:14 +0530396
397 //If no pbits configured for service, hence add PbitNone for flows
398 if len(vs.DsRemarkPbitsMap) == 0 {
399 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchNone))
400 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530401 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 +0530402 }
403 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530404 if err = vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530405 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 +0530406 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
407 vs.triggerServiceFailureInd(statusCode, statusMessage)
408 }
409 } else {
410 // if all 8 p-bits are to be remarked to one-pbit, configure all-to-one remarking flow
411 if _, ok := vs.DsRemarkPbitsMap[int(of.PbitMatchAll)]; ok {
412 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchAll))
413 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530414 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 +0530415 }
416 logger.Debug(ctx, "Add-one-match-all-pbit-flow")
417 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530418 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530419 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 +0530420 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
421 vs.triggerServiceFailureInd(statusCode, statusMessage)
422 }
423 } else {
424 for matchPbit := range vs.DsRemarkPbitsMap {
425 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
426 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530427 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 +0530428 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
429 vs.triggerServiceFailureInd(statusCode, statusMessage)
430 continue
431 }
432 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530433 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530434 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 +0530435 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
436 vs.triggerServiceFailureInd(statusCode, statusMessage)
437 }
438 }
439 }
440 }
441 vs.DsHSIAFlowsApplied = true
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530442 logger.Debugw(ctx, "Pushed DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530443 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530444 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530445 return nil
446}
447
448// DelUsHsiaFlows - Deletes US HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530449func (vs *VoltService) DelUsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530450 logger.Infow(ctx, "Removing US HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530451 if vs.UsHSIAFlowsApplied || vgcRebooted {
452 device, err := GetApplication().GetDeviceFromPort(vs.Port)
453 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530454 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 +0530455 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530456 pBits := vs.Pbits
457
vinokuma926cb3e2023-03-29 11:41:06 +0530458 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530459 if len(vs.Pbits) == 0 {
460 pBits = append(pBits, PbitMatchNone)
461 }
462 for _, pbits := range pBits {
463 usflows, err := vs.BuildUsHsiaFlows(pbits)
464 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530465 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 +0530466 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
467 vs.triggerServiceFailureInd(statusCode, statusMessage)
468 continue
469 }
470 usflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530471 if err = vs.DelFlows(cntx, device, usflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530472 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 +0530473 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
474 vs.triggerServiceFailureInd(statusCode, statusMessage)
475 }
476 }
477 vs.UsHSIAFlowsApplied = false
478 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530479 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530480 return nil
481}
482
483// DelDsHsiaFlows - Deletes DS HSIA Flows for the service
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530484func (vs *VoltService) DelDsHsiaFlows(cntx context.Context, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530485 logger.Infow(ctx, "Removing DS HSIA Services", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530486 if vs.DsHSIAFlowsApplied || vgcRebooted {
487 device, err := GetApplication().GetDeviceFromPort(vs.Port)
488 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530489 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 +0530490 }
491
Naveen Sampath04696f72022-06-13 15:19:14 +0530492 var matchPbit int
vinokuma926cb3e2023-03-29 11:41:06 +0530493 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530494 if len(vs.DsRemarkPbitsMap) == 0 {
495 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(PbitMatchNone))
496 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530497 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 +0530498 }
499 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530500 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530501 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 +0530502 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
503 vs.triggerServiceFailureInd(statusCode, statusMessage)
504 }
505 } else if _, ok := vs.DsRemarkPbitsMap[int(PbitMatchAll)]; ok {
506 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(int(PbitMatchAll)))
507 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530508 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 +0530509 }
510 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530511 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530512 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 +0530513 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
514 vs.triggerServiceFailureInd(statusCode, statusMessage)
515 }
516 } else {
517 for matchPbit = range vs.DsRemarkPbitsMap {
518 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
519 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530520 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 +0530521 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
522 vs.triggerServiceFailureInd(statusCode, statusMessage)
523 continue
524 }
525 dsflows.MigrateCookie = vgcRebooted
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +0530526 if err = vs.DelFlows(cntx, device, dsflows, delFlowsInDevice); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530527 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 +0530528 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
529 vs.triggerServiceFailureInd(statusCode, statusMessage)
530 }
531 }
532 }
533 vs.DsHSIAFlowsApplied = false
534 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530535 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 +0530536 // Post HSIA configuration success indication on message bus
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530537 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530538 return nil
539}
540
541// BuildDsHsiaFlows build the DS HSIA flows
542// Called for add/delete HSIA flows
543func (vs *VoltService) BuildDsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530544 logger.Debugw(ctx, "Building DS HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530545 flow := &of.VoltFlow{}
546 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
547
548 // Get the out and in ports for the flows
549 device, err := GetApplication().GetDeviceFromPort(vs.Port)
550 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530551 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 +0530552 }
553 inport, _ := GetApplication().GetPortID(device.NniPort)
554 outport, _ := GetApplication().GetPortID(vs.Port)
555 // PortName and PortID to be used for validation of port before flow pushing
556 flow.PortID = outport
557 flow.PortName = vs.Port
558 allowTransparent := 0
559 if vs.AllowTransparent {
560 allowTransparent = 1
561 }
562
563 // initialized actnPbit to 0 for cookie genration backward compatibility.
564 var actnPbit of.PbitType
565 remarkPbit, remarkExists := vs.DsRemarkPbitsMap[int(pbits)]
566
567 generateDSCookie := func(vlan of.VlanType, valToShift uint64) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530568 // | 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 +0530569 cookie := uint64(vlan)<<52 + uint64(actnPbit)<<48 + uint64(outport)<<16 | of.HsiaFlowMask
570 cookie = cookie | of.DsFlowMask
571 cookie = cookie + (valToShift << 4) + uint64(pbits)
572 return cookie
573 }
574
575 l2ProtoValue, err := GetMetadataForL2Protocol(vs.SVlanTpid)
576 if err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530577 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 +0530578 }
579
580 // Add Table-0 flow that deals with the outer VLAN in pOLT
581 {
582 subflow1 := of.NewVoltSubFlow()
583 subflow1.SetTableID(0)
584 subflow1.SetGoToTable(1)
585 subflow1.SetInPort(inport)
586
587 if pbits != PbitMatchNone {
588 subflow1.SetMatchPbit(pbits)
589 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530590 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
591 subflow1.SetPcp(of.PbitType(remarkPbit))
592 // match & action pbits are different, set remark-pbit action
593 actnPbit = of.PbitType(remarkPbit)
594 // mask remark p-bit to 4bits
595 actnPbit = actnPbit & 0x0F
596 }
597
598 if err := vs.setDSMatchActionVlanT0(subflow1); err != nil {
599 return nil, err
600 }
Tinoj Joseph1d108322022-07-13 10:07:39 +0530601 logger.Infow(ctx, "HSIA DS flows MAC Learning & MAC", log.Fields{"ML": vs.MacLearning, "Mac": vs.MacAddr})
Naveen Sampath04696f72022-06-13 15:19:14 +0530602 if NonZeroMacAddress(vs.MacAddr) {
603 subflow1.SetMatchDstMac(vs.MacAddr)
604 }
605 subflow1.Priority = of.HsiaFlowPriority
606 subflow1.SetMeterID(vs.DsMeterID)
607
608 /* WriteMetaData 8 Byte(uint64) usage:
609 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
610 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
611 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530612 if vs.ServiceType == FttbSubscriberTraffic {
613 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
614 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530615 subflow1.SetWriteMetadata(metadata)
616
617 /* TableMetaData 8 Byte(uint64) Voltha usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
618 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
619 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
620 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | unitag | unitag | ctag | ctag | */
621
622 //TODO-COMM:
623 /* TableMetaData 8 Byte(uint64) Community usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
624 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
625 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
626 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | ctag | ctag | ctag | ctag | */
627
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530628 if vs.ServiceType != FttbSubscriberTraffic {
629 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
630 subflow1.SetTableMetadata(metadata)
631 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530632 // TODO - We are using cookie as key and must come up with better cookie
633 // allocation algorithm
634 /**
635 * Cokies may clash when -
636 * on same uni-port we have two sub-service
637 * 1. U=10, C=100, S=310, p-bit=4 - VLAN_Control = OLT_CVLAN_OLT_SVLAN
638 * 2. U=10, C=10, S=320, p-bit=4 - VLAN_control = ONU_CVLAN_ONU_SVLAN
639 * However, this p-bit re-use will not be allowed by sub-mgr.
640 */
641 if vs.VlanControl == OLTCVlanOLTSVlan {
642 /**
643 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
644 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
645 * use old cookie.
646 */
647 subflow1.Cookie = generateDSCookie(vs.UniVlan, 0)
648 if vgcRebooted {
649 subflow1.OldCookie = generateDSCookie(vs.CVlan, 0)
650 }
651 } else {
652 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
653 subflow1.Cookie = generateDSCookie(vs.CVlan, 0)
654 }
655
656 flow.SubFlows[subflow1.Cookie] = subflow1
657 logger.Infow(ctx, "Building downstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie,
658 "subflow": subflow1})
659 }
660
vinokuma926cb3e2023-03-29 11:41:06 +0530661 // Add Table-1 flow that deals with inner VLAN at the ONU
Naveen Sampath04696f72022-06-13 15:19:14 +0530662 {
663 subflow2 := of.NewVoltSubFlow()
664 subflow2.SetTableID(1)
665 subflow2.SetInPort(inport)
666 if NonZeroMacAddress(vs.MacAddr) {
667 subflow2.SetMatchDstMac(vs.MacAddr)
668 }
669
670 if err := vs.setDSMatchActionVlanT1(subflow2); err != nil {
671 return nil, err
672 }
673 if pbits != PbitMatchNone {
674 subflow2.SetMatchPbit(pbits)
675 }
676
677 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
678 subflow2.SetPcp(of.PbitType(remarkPbit))
679 }
680
681 subflow2.SetOutPort(outport)
682 subflow2.SetMeterID(vs.DsMeterID)
683
684 // refer Table-0 flow generation for byte information
685 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530686 if vs.ServiceType == FttbSubscriberTraffic {
687 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
688 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530689 subflow2.SetWriteMetadata(metadata)
690
691 // Table-1 and inport is NNI: It is a DS flow for ONU, add uniport in metadata to make it unique
692 if util.IsNniPort(inport) {
693 metadata = uint64(outport)
694 } else {
695 // refer Table-0 flow generation for byte information
696 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
697 }
698 subflow2.SetTableMetadata(metadata)
699 // Setting of Cookie - TODO - Improve the allocation algorithm
700 if vs.VlanControl == OLTCVlanOLTSVlan {
701 /**
702 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
703 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
704 * use old cookie.
705 */
706 subflow2.Cookie = generateDSCookie(vs.UniVlan, 1)
707 if vgcRebooted {
708 subflow2.OldCookie = generateDSCookie(vs.CVlan, 1)
709 }
710 } else {
711 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
712 subflow2.Cookie = generateDSCookie(vs.CVlan, 1)
713 }
714
715 subflow2.Priority = of.HsiaFlowPriority
716 flow.SubFlows[subflow2.Cookie] = subflow2
717 logger.Infow(ctx, "Building downstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie,
718 "subflow": subflow2})
719 }
720
721 return flow, nil
722}
723
724// BuildUsHsiaFlows build the US HSIA flows
725// Called for add/delete HSIA flows
726func (vs *VoltService) BuildUsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530727 logger.Debugw(ctx, "Building US HSIA Service Flows", log.Fields{"Device": vs.Device, "ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530728 flow := &of.VoltFlow{}
729 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
730
731 // Get the out and in ports for the flows
732 device, err := GetApplication().GetDeviceFromPort(vs.Port)
733 if err != nil {
734 return nil, errorCodes.ErrDeviceNotFound
735 }
736 outport, _ := GetApplication().GetPortID(device.NniPort)
737 inport, _ := GetApplication().GetPortID(vs.Port)
738 // PortName and PortID to be used for validation of port before flow pushing
739 flow.PortID = inport
740 flow.PortName = vs.Port
Naveen Sampath04696f72022-06-13 15:19:14 +0530741
742 // Add Table-0 flow that deals with the inner VLAN in ONU
743 {
744 subflow1 := of.NewVoltSubFlow()
745 subflow1.SetTableID(0)
746 subflow1.SetGoToTable(1)
747 subflow1.SetInPort(inport)
748
vinokuma926cb3e2023-03-29 11:41:06 +0530749 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530750 subflow1.SetMatchPbit(vs.UsPonCTagPriority)
751 subflow1.SetPcp(vs.UsPonSTagPriority)
vinokuma926cb3e2023-03-29 11:41:06 +0530752 } else if vs.ServiceType == DpuAncpTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530753 subflow1.SetPcp(vs.UsPonSTagPriority)
754 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530755 if err := vs.setUSMatchActionVlanT0(subflow1); err != nil {
756 return nil, err
757 }
758 subflow1.SetMeterID(vs.UsMeterID)
759
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530760 /* WriteMetaData 8 Byte(uint64) usage:
761 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
762 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
763 //metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
764 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530765 if vs.ServiceType == FttbSubscriberTraffic {
766 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
767 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530768 subflow1.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530769
Naveen Sampath04696f72022-06-13 15:19:14 +0530770 if vs.VlanControl == OLTCVlanOLTSVlan {
771 /**
772 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
773 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
774 * use old cookie.
775 */
776 subflow1.Cookie = vs.generateUSCookie(vs.UniVlan, 0, inport, pbits)
777 if vgcRebooted {
778 subflow1.OldCookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
779 }
780 } else {
781 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
782 subflow1.Cookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
783 }
784 subflow1.Priority = of.HsiaFlowPriority
785 flow.SubFlows[subflow1.Cookie] = subflow1
786 logger.Infow(ctx, "Building upstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie, "subflow": subflow1})
787 }
788
vinokuma926cb3e2023-03-29 11:41:06 +0530789 // Add Table-1 flow that deals with the outer vlan in pOLT
Naveen Sampath04696f72022-06-13 15:19:14 +0530790 {
791 subflow2 := of.NewVoltSubFlow()
792 subflow2.SetTableID(1)
793 subflow2.SetInPort(inport)
794
Naveen Sampath04696f72022-06-13 15:19:14 +0530795 if err := vs.setUSMatchActionVlanT1(subflow2); err != nil {
796 return nil, err
797 }
vinokuma926cb3e2023-03-29 11:41:06 +0530798 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530799 subflow2.SetMatchSrcMac(vs.MacAddr)
800 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530801 subflow2.SetInPort(inport)
802 subflow2.SetOutPort(outport)
803 subflow2.SetMeterID(vs.UsMeterID)
804
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530805 // refer Table-0 flow generation for byte information
806 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530807 if vs.ServiceType == FttbSubscriberTraffic {
808 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
809 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530810 subflow2.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530811
Naveen Sampath04696f72022-06-13 15:19:14 +0530812 if vs.VlanControl == OLTCVlanOLTSVlan {
813 /**
814 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
815 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
816 * use old cookie.
817 */
818 subflow2.Cookie = vs.generateUSCookie(vs.UniVlan, 1, inport, pbits)
819 if vgcRebooted {
820 subflow2.OldCookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
821 }
822 } else {
823 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
824 subflow2.Cookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
825 }
826 subflow2.Priority = of.HsiaFlowPriority
827
828 flow.SubFlows[subflow2.Cookie] = subflow2
829 logger.Infow(ctx, "Building upstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie, "subflow": subflow2})
830 }
831
832 return flow, nil
833}
834
835func (vs *VoltService) generateUSCookie(vlan of.VlanType, valToShift uint64, inport uint32, pbits of.PbitType) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530836 // | 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 +0530837 logger.Debugw(ctx, "Generate US Cookie", log.Fields{"Vlan": vlan, "ValToShift": vlan, "Inport": inport, "Pbits": pbits})
Naveen Sampath04696f72022-06-13 15:19:14 +0530838 cookie := uint64(vlan)<<52 + uint64(inport)<<16 | of.HsiaFlowMask
839 cookie = cookie | of.UsFlowMask
840 cookie = cookie + (valToShift << 4) + uint64(pbits)
841 return cookie
842}
843
844// setUSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for US Table-1
845// based on different Vlan Controls
846func (vs *VoltService) setUSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530847 logger.Debugw(ctx, "Set US Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530848 switch vs.VlanControl {
849 case None:
850 flow.SetMatchVlan(vs.SVlan)
851 case ONUCVlanOLTSVlan:
852 flow.SetMatchVlan(vs.CVlan)
853 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
854 case OLTCVlanOLTSVlan:
855 flow.SetMatchVlan(vs.UniVlan)
856 flow.SetSetVlan(vs.CVlan)
857 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
858 case ONUCVlan:
859 flow.SetMatchVlan(vs.SVlan)
860 case OLTSVlan:
861 if vs.UniVlan != of.VlanAny && vs.UniVlan != of.VlanNone {
862 flow.SetMatchVlan(vs.UniVlan)
863 flow.SetSetVlan(vs.SVlan)
864 } else if vs.UniVlan != of.VlanNone {
865 flow.SetMatchVlan(vs.UniVlan)
866 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
867 } else {
868 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
869 }
870 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530871 err := errorCodes.ErrInvalidParamInRequest
872 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530873 }
874 return nil
875}
876
877// setDSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for DS Table-0
878// based on different Vlan Controls
879func (vs *VoltService) setDSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530880 logger.Debugw(ctx, "Set DS Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530881 switch vs.VlanControl {
882 case None:
883 flow.SetMatchVlan(vs.SVlan)
884 case ONUCVlanOLTSVlan:
885 flow.SetMatchVlan(vs.SVlan)
886 flow.SetPopVlan()
887 case OLTCVlanOLTSVlan:
888 flow.SetMatchVlan(vs.SVlan)
889 flow.SetPopVlan()
890 flow.SetSetVlan(vs.UniVlan)
891 case ONUCVlan:
892 flow.SetMatchVlan(vs.SVlan)
893 case OLTSVlan:
894 flow.SetMatchVlan(vs.SVlan)
895 if vs.UniVlan != of.VlanNone && vs.UniVlan != of.VlanAny {
896 flow.SetSetVlan(vs.UniVlan)
897 } else {
898 flow.SetPopVlan()
899 }
900 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530901 err := errorCodes.ErrInvalidParamInRequest
902 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530903 }
904 return nil
905}
906
907// setUSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for US Table-0
908// based on different Vlan Controls
909func (vs *VoltService) setUSMatchActionVlanT0(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530910 logger.Debugw(ctx, "Set US Match Action Vlan T0", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530911 switch vs.VlanControl {
912 case None:
913 flow.SetMatchVlan(vs.SVlan)
914 case ONUCVlanOLTSVlan:
915 if vs.UniVlan != of.VlanNone {
916 flow.SetMatchVlan(vs.UniVlan)
917 flow.SetSetVlan(vs.CVlan)
918 } else {
919 flow.SetPushVlan(vs.CVlan, layers.EthernetTypeDot1Q)
920 }
921 case OLTCVlanOLTSVlan:
922 flow.SetMatchVlan(vs.UniVlan)
923 case ONUCVlan:
924 if vs.UniVlan != of.VlanNone {
925 flow.SetMatchVlan(vs.UniVlan)
926 flow.SetSetVlan(vs.SVlan)
927 } else {
928 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
929 }
930 case OLTSVlan:
931 flow.SetMatchVlan(vs.UniVlan)
932 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530933 err := errorCodes.ErrInvalidParamInRequest
934 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530935 }
936 return nil
937}
938
939// setDSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for DS Table-1
940// based on different Vlan Controls
941func (vs *VoltService) setDSMatchActionVlanT1(flow *of.VoltSubFlow) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530942 logger.Debugw(ctx, "Set DS Match Action Vlan T1", log.Fields{"Value": vs.VlanControl})
Naveen Sampath04696f72022-06-13 15:19:14 +0530943 switch vs.VlanControl {
944 case None:
945 flow.SetMatchVlan(vs.SVlan)
946 case ONUCVlanOLTSVlan:
947 flow.SetMatchVlan(vs.CVlan)
948 if vs.UniVlan != of.VlanNone {
949 flow.SetSetVlan(vs.UniVlan)
950 } else {
951 flow.SetPopVlan()
952 }
953 case OLTCVlanOLTSVlan:
954 flow.SetMatchVlan(vs.UniVlan)
955 case ONUCVlan:
956 flow.SetMatchVlan(vs.SVlan)
957 if vs.UniVlan != of.VlanNone {
958 flow.SetSetVlan(vs.UniVlan)
959 } else {
960 flow.SetPopVlan()
961 }
962 case OLTSVlan:
963 flow.SetMatchVlan(vs.UniVlan)
964 default:
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530965 err := errorCodes.ErrInvalidParamInRequest
966 return fmt.Errorf("Invalid Vlan Control Option %d : %w", vs.VlanControl, err)
Naveen Sampath04696f72022-06-13 15:19:14 +0530967 }
968 return nil
969}
970
971// SvcUpInd for service up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530972func (vs *VoltService) SvcUpInd(cntx context.Context) {
973 vs.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530974}
975
976// SvcDownInd for service down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530977func (vs *VoltService) SvcDownInd(cntx context.Context) {
978 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530979}
980
981// SetIpv4Addr to set ipv4 address
982func (vs *VoltService) SetIpv4Addr(addr net.IP) {
983 vs.Ipv4Addr = addr
984}
985
986// SetIpv6Addr to set ipv6 address
987func (vs *VoltService) SetIpv6Addr(addr net.IP) {
988 vs.Ipv6Addr = addr
989}
990
991// SetMacAddr to set mac address
992func (vs *VoltService) SetMacAddr(addr net.HardwareAddr) {
993 vs.MacAddr = addr
994}
995
996// ----------------------------------------------
997// VOLT Application - Related to services
998// ---------------------------------------------
999// ---------------------------------------------------------------
1000// Service CRUD functions. These are exposed to the overall binary
1001// to be invoked from the point where the CRUD operations are received
1002// from the external entities
1003
1004// AddService : A service in the context of VOLT is a subscriber or service of a
1005// subscriber which is uniquely identified by a combination of MAC
1006// address, VLAN tags, 802.1p bits. However, in the context of the
1007// current implementation, a service is an entity that is identified by a
1008// unique L2 (MAC address + VLANs) or unique L3 (VLANs + IP address)
1009// FUNC: Add Service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301010func (va *VoltApplication) AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301011 logger.Infow(ctx, "Service to be configured", log.Fields{"Cfg": cfg})
Naveen Sampath04696f72022-06-13 15:19:14 +05301012 var mmUs, mmDs *VoltMeter
1013 var err error
1014
vinokuma926cb3e2023-03-29 11:41:06 +05301015 // Take the Device lock only in case of NB add request.
Naveen Sampath04696f72022-06-13 15:19:14 +05301016 // Allow internal adds since internal add happen only under
1017 // 1. Restore Service from DB
1018 // 2. Service Migration
1019 if oper == nil {
1020 if svc := va.GetService(cfg.Name); svc != nil {
1021 logger.Warnw(ctx, "Service Already Exists. Ignoring Add Service Request", log.Fields{"Name": cfg.Name})
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301022 return errors.New("service already exists")
Naveen Sampath04696f72022-06-13 15:19:14 +05301023 }
1024 }
1025
Naveen Sampath04696f72022-06-13 15:19:14 +05301026 // Service doesn't exist. So create it and add to the port
1027 vs := NewVoltService(&cfg)
1028 if oper != nil {
1029 vs.UsHSIAFlowsApplied = oper.UsHSIAFlowsApplied
1030 vs.DsHSIAFlowsApplied = oper.DsHSIAFlowsApplied
1031 vs.Ipv4Addr = oper.Ipv4Addr
1032 vs.Ipv6Addr = oper.Ipv6Addr
1033 vs.MacLearning = cfg.MacLearning
1034 vs.PendingFlows = oper.PendingFlows
1035 vs.AssociatedFlows = oper.AssociatedFlows
1036 vs.DeleteInProgress = oper.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301037 vs.DeactivateInProgress = oper.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301038 vs.BwAvailInfo = oper.BwAvailInfo
1039 vs.Device = oper.Device
1040 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301041 // Sorting Pbit from highest
Naveen Sampath04696f72022-06-13 15:19:14 +05301042 sort.Slice(vs.Pbits, func(i, j int) bool {
1043 return vs.Pbits[i] > vs.Pbits[j]
1044 })
1045 logger.Infow(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
1046 }
1047 logger.Infow(ctx, "VolthService...", log.Fields{"vs": vs.Name})
1048
1049 // The bandwidth and shaper profile combined into meter
1050 if mmDs, err = va.GetMeter(cfg.DsMeterProfile); err == nil {
1051 vs.DsMeterID = mmDs.ID
1052 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301053 return errors.New("downStream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301054 }
1055
1056 // The aggregated downstream meter profile
1057 // if mmAg, err = va.GetMeter(cfg.AggDsMeterProfile); err == nil {
1058 // vs.AggDsMeterID = mmAg.ID
1059 // } else {
1060 // return errors.New("Aggregated meter profile not found")
1061 // }
1062
1063 // if cfg.AggDsMeterProfile == cfg.UsMeterProfile {
1064 // vs.UsMeterID = mmAg.ID
1065 // } else {
1066 // The bandwidth and shaper profile combined into meter
1067 if mmUs, err = va.GetMeter(cfg.UsMeterProfile); err == nil {
1068 vs.UsMeterID = mmUs.ID
1069 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301070 return errors.New("upstream meter profile not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301071 }
1072 //}
1073
1074 AppMutex.ServiceDataMutex.Lock()
1075 defer AppMutex.ServiceDataMutex.Unlock()
1076
1077 // Add the service to the VNET
1078 vnet := va.GetVnet(cfg.SVlan, cfg.CVlan, cfg.UniVlan)
1079 if vnet != nil {
1080 if vpv := va.GetVnetByPort(vs.Port, cfg.SVlan, cfg.CVlan, cfg.UniVlan); vpv != nil {
1081 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301082 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301083 vpv.VpvLock.Unlock()
1084 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301085 va.AddVnetToPort(cntx, vs.Port, vnet, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301086 }
1087 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301088 logger.Warnw(ctx, "VNET-does-not-exist-for-service", log.Fields{"ServiceName": cfg.Name})
1089 return errors.New("vnet doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +05301090 }
1091
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301092 // If the device is already discovered, update the device name in service
1093 d, err := va.GetDeviceFromPort(vs.Port)
1094 if err == nil {
1095 vs.Device = d.Name
1096 }
1097
Naveen Sampath04696f72022-06-13 15:19:14 +05301098 vs.Version = database.PresentVersionMap[database.ServicePath]
1099 // Add the service to the volt application
1100 va.ServiceByName.Store(vs.Name, vs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301101 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301102
1103 if nil == oper {
Naveen Sampath04696f72022-06-13 15:19:14 +05301104 if !vs.UsHSIAFlowsApplied {
1105 vs.triggerServiceInProgressInd()
1106 }
1107
vinokuma926cb3e2023-03-29 11:41:06 +05301108 // Update meter profiles service count if service is being added from northbound
Naveen Sampath04696f72022-06-13 15:19:14 +05301109 mmDs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301110 va.UpdateMeterProf(cntx, *mmDs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301111 if mmUs != nil {
1112 mmUs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301113 va.UpdateMeterProf(cntx, *mmUs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301114 }
1115 //mmAg.AssociatedServices++
1116 //va.UpdateMeterProf(*mmAg)
vinokuma926cb3e2023-03-29 11:41:06 +05301117 logger.Debugw(ctx, "northbound-service-add-successful", log.Fields{"ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301118 }
1119
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301120 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 +05301121 return nil
1122}
1123
vinokuma926cb3e2023-03-29 11:41:06 +05301124// DelServiceWithPrefix - Deletes service with the provided prefix.
Naveen Sampath04696f72022-06-13 15:19:14 +05301125// Added for DT/TT usecase with sadis replica interface
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301126func (va *VoltApplication) DelServiceWithPrefix(cntx context.Context, prefix string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301127 logger.Infow(ctx, "Delete Service With provided Prefix", log.Fields{"Prefix": prefix})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301128 var isServiceExist bool
Naveen Sampath04696f72022-06-13 15:19:14 +05301129 va.ServiceByName.Range(func(key, value interface{}) bool {
1130 srvName := key.(string)
1131 vs := value.(*VoltService)
1132 if strings.Contains(srvName, prefix) {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301133 isServiceExist = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301134 va.DelService(cntx, srvName, true, nil, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301135
1136 vnetName := strconv.FormatUint(uint64(vs.SVlan), 10) + "-"
1137 vnetName = vnetName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1138 vnetName = vnetName + strconv.FormatUint(uint64(vs.UniVlan), 10)
1139
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301140 if err := va.DelVnet(cntx, vnetName, ""); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301141 logger.Warnw(ctx, "Delete Vnet Failed", log.Fields{"Name": vnetName, "Error": err})
1142 }
1143 }
1144 return true
1145 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301146
1147 if !isServiceExist {
1148 return errorCodes.ErrServiceNotFound
1149 }
1150 return nil
Naveen Sampath04696f72022-06-13 15:19:14 +05301151}
1152
1153// DelService delete a service form the application
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301154func (va *VoltApplication) DelService(cntx context.Context, name string, forceDelete bool, newSvc *VoltServiceCfg, serviceMigration bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301155 AppMutex.ServiceDataMutex.Lock()
1156 defer AppMutex.ServiceDataMutex.Unlock()
1157
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301158 logger.Infow(ctx, "Delete Service Request", log.Fields{"Service": name, "ForceDelete": forceDelete, "serviceMigration": serviceMigration})
Naveen Sampath04696f72022-06-13 15:19:14 +05301159 var noFlowsPresent bool
1160
1161 vsIntf, ok := va.ServiceByName.Load(name)
1162 if !ok {
1163 logger.Warnw(ctx, "Service doesn't exist", log.Fields{"ServiceName": name})
1164 return
1165 }
1166 vs := vsIntf.(*VoltService)
1167 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1168 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301169 logger.Warnw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301170 return
1171 }
1172
vinokuma926cb3e2023-03-29 11:41:06 +05301173 // Set this to avoid race-condition during flow result processing
Naveen Sampath04696f72022-06-13 15:19:14 +05301174 vs.DeleteInProgress = true
1175 vs.ForceDelete = forceDelete
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301176 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301177
1178 if len(vs.AssociatedFlows) == 0 {
1179 noFlowsPresent = true
1180 }
1181 vpv.VpvLock.Lock()
1182 defer vpv.VpvLock.Unlock()
1183
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301184 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301185
1186 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301187 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301188 }
1189 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 +05301190 vpv.DelService(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301191 if vpv.servicesCount.Load() == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301192 va.DelVnetFromPort(cntx, vs.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301193 }
1194
1195 // Delete the service immediately in case of Force Delete
1196 // This will be enabled when profile reconciliation happens after restore
1197 // of backedup data
1198 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301199 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301200 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301201 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301202 }
1203
Naveen Sampath04696f72022-06-13 15:19:14 +05301204 if nil != newSvc {
1205 logger.Infow(ctx, "Old Service meter profiles", log.Fields{"AGG": vs.AggDsMeterProfile, "DS": vs.DsMeterProfile, "US": vs.UsMeterProfile})
1206 logger.Infow(ctx, "New Service meter profiles", log.Fields{"AGG": newSvc.AggDsMeterProfile, "DS": newSvc.DsMeterProfile, "US": newSvc.UsMeterProfile})
1207 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301208
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301209 logger.Infow(ctx, "About to mark meter for deletion\n", log.Fields{"serviceName": vs.Name})
1210
1211 if aggMeter, ok := va.MeterMgr.GetMeterByID(vs.AggDsMeterID); ok {
1212 if nil == newSvc || (nil != newSvc && aggMeter.Name != newSvc.AggDsMeterProfile) {
vinokuma926cb3e2023-03-29 11:41:06 +05301213 if aggMeter.AssociatedServices > 0 {
1214 aggMeter.AssociatedServices--
1215 logger.Infow(ctx, "Agg Meter associated services updated\n", log.Fields{"MeterID": aggMeter})
1216 va.UpdateMeterProf(cntx, *aggMeter)
1217 }
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301218 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301219 }
1220 if dsMeter, ok := va.MeterMgr.GetMeterByID(vs.DsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301221 if nil == newSvc || (nil != newSvc && dsMeter.Name != newSvc.DsMeterProfile) {
1222 if dsMeter.AssociatedServices > 0 {
1223 dsMeter.AssociatedServices--
1224 logger.Infow(ctx, "DS Meter associated services updated\n", log.Fields{"MeterID": dsMeter})
1225 va.UpdateMeterProf(cntx, *dsMeter)
1226 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301227 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301228 }
1229 if vs.AggDsMeterID != vs.UsMeterID {
1230 if usMeter, ok := va.MeterMgr.GetMeterByID(vs.UsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301231 if nil == newSvc || (nil != newSvc && usMeter.Name != newSvc.UsMeterProfile) {
1232 if usMeter.AssociatedServices > 0 {
1233 usMeter.AssociatedServices--
1234 logger.Infow(ctx, "US Meter associated services updated\n", log.Fields{"MeterID": usMeter})
1235 va.UpdateMeterProf(cntx, *usMeter)
1236 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301237 }
1238 }
1239 }
1240
1241 if noFlowsPresent || vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301242 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301243 }
1244
vinokuma926cb3e2023-03-29 11:41:06 +05301245 // Delete the per service counter too
Naveen Sampath04696f72022-06-13 15:19:14 +05301246 va.ServiceCounters.Delete(name)
1247 if vs.IgmpEnabled && vs.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301248 _ = db.DelAllServiceChannelCounter(cntx, name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301249 }
1250}
1251
vinokuma926cb3e2023-03-29 11:41:06 +05301252// AddFlows - Adds the flow to the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301253// Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301254func (vs *VoltService) AddFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301255 // Using locks instead of concurrent map for PendingFlows to avoid
1256 // race condition during flow response indication processing
1257 vs.ServiceLock.Lock()
1258 defer vs.ServiceLock.Unlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301259 logger.Debugw(ctx, "Adds the flow to the service", log.Fields{"Port": vs.Port, "Device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301260
1261 for cookie := range flow.SubFlows {
1262 cookie := strconv.FormatUint(cookie, 10)
1263 fe := &FlowEvent{
1264 eType: EventTypeServiceFlowAdded,
1265 device: device.Name,
1266 cookie: cookie,
1267 eventData: vs,
1268 }
1269 device.RegisterFlowAddEvent(cookie, fe)
1270 vs.PendingFlows[cookie] = true
1271 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301272 return cntlr.GetController().AddFlows(cntx, vs.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301273}
1274
vinokuma926cb3e2023-03-29 11:41:06 +05301275// FlowInstallSuccess - Called when corresponding service flow installation is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301276// If no more pending flows, HSIA indication wil be triggered
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301277func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301278 logger.Debugw(ctx, "Flow Add Success Notification", log.Fields{"Cookie": cookie, "bwAvailInfo": bwAvailInfo, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301279 if vs.DeleteInProgress {
1280 logger.Warnw(ctx, "Skipping Flow Add Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1281 return
1282 }
1283 vs.ServiceLock.Lock()
1284
1285 if _, ok := vs.PendingFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301286 logger.Warnw(ctx, "Flow Add Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301287 vs.ServiceLock.Unlock()
1288 return
1289 }
1290
1291 delete(vs.PendingFlows, cookie)
1292 vs.AssociatedFlows[cookie] = true
1293 vs.ServiceLock.Unlock()
1294 var prevBwAvail, presentBwAvail string
1295 if bwAvailInfo.PrevBw != "" && bwAvailInfo.PresentBw != "" {
1296 prevBwAvail = bwAvailInfo.PrevBw
1297 presentBwAvail = bwAvailInfo.PresentBw
1298 vs.BwAvailInfo = prevBwAvail + "," + presentBwAvail
Tinoj Joseph1d108322022-07-13 10:07:39 +05301299 logger.Debugw(ctx, "Bandwidth-value-formed", log.Fields{"BwAvailInfo": vs.BwAvailInfo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301300 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301301 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301302
1303 if len(vs.PendingFlows) == 0 && vs.DsHSIAFlowsApplied {
Naveen Sampath04696f72022-06-13 15:19:14 +05301304 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1305 if err != nil {
1306 logger.Errorw(ctx, "Error Getting Device. Dropping HSIA Success indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1307 return
1308 } else if device.State != controller.DeviceStateUP {
1309 logger.Warnw(ctx, "Device state Down. Dropping HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1310 return
1311 }
1312
1313 if vs.Trigger == ServiceVlanUpdate {
1314 vs.Trigger = NBActivate
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301315 defer vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301316 }
1317 logger.Infow(ctx, "All Flows installed for Service", log.Fields{"Service": vs.Name})
1318 return
1319 }
1320 logger.Infow(ctx, "Processed Service Flow Add Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1321}
1322
vinokuma926cb3e2023-03-29 11:41:06 +05301323// FlowInstallFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301324// Trigger service failure indication to NB
1325func (vs *VoltService) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
1326 vs.ServiceLock.RLock()
1327
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301328 logger.Debugw(ctx, "Service flow installation failure", log.Fields{"Service": vs.Name, "Cookie": cookie, "errorCode": errorCode, "errReason": errReason})
Naveen Sampath04696f72022-06-13 15:19:14 +05301329 if _, ok := vs.PendingFlows[cookie]; !ok {
1330 logger.Errorw(ctx, "Flow Add Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1331 vs.ServiceLock.RUnlock()
1332 return
1333 }
1334 vs.ServiceLock.RUnlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301335 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 +05301336 vs.triggerServiceFailureInd(errorCode, errReason)
1337}
1338
vinokuma926cb3e2023-03-29 11:41:06 +05301339// DelFlows - Deletes the flow from the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301340// Triggers flow deletion after registering for flow indication event
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301341func (vs *VoltService) DelFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow, delFlowsInDevice bool) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301342 logger.Debugw(ctx, "Delete the flow from the service", log.Fields{"Port": vs.Port, "Device": device.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301343 if !vs.ForceDelete {
1344 // Using locks instead of concurrent map for AssociatedFlows to avoid
1345 // race condition during flow response indication processing
1346 vs.ServiceLock.Lock()
1347 defer vs.ServiceLock.Unlock()
1348
1349 for cookie := range flow.SubFlows {
1350 cookie := strconv.FormatUint(cookie, 10)
1351 fe := &FlowEvent{
1352 eType: EventTypeServiceFlowRemoved,
1353 cookie: cookie,
1354 eventData: vs,
1355 }
1356 device.RegisterFlowDelEvent(cookie, fe)
1357 }
1358 }
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301359 return cntlr.GetController().DelFlows(cntx, vs.Port, device.Name, flow, delFlowsInDevice)
Naveen Sampath04696f72022-06-13 15:19:14 +05301360}
1361
vinokuma926cb3e2023-03-29 11:41:06 +05301362// CheckAndDeleteService - remove service from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301363func (vs *VoltService) CheckAndDeleteService(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301364 logger.Debugw(ctx, "Delete service from DB/Cache", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301365 if vs.DeleteInProgress && len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301366 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301367 GetApplication().ServiceByName.Delete(vs.Name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301368 logger.Debugw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301369 }
1370}
1371
vinokuma926cb3e2023-03-29 11:41:06 +05301372// FlowRemoveSuccess - Called when corresponding service flow removal is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301373// If no more associated flows, DelHSIA indication wil be triggered
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301374func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301375 // if vs.DeleteInProgress {
1376 // logger.Warnw(ctx, "Skipping Flow Remove Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1377 // return
1378 // }
1379 vs.ServiceLock.Lock()
1380 logger.Infow(ctx, "Processing Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1381
1382 if _, ok := vs.AssociatedFlows[cookie]; ok {
1383 delete(vs.AssociatedFlows, cookie)
1384 } else if _, ok := vs.PendingFlows[cookie]; ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301385 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 +05301386 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301387 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 +05301388 }
1389
1390 vs.ServiceLock.Unlock()
1391
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301392 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301393
1394 if len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Naveen Sampath04696f72022-06-13 15:19:14 +05301395 device := GetApplication().GetDevice(vs.Device)
1396 if device == nil {
1397 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1398 return
1399 } else if device.State != controller.DeviceStateUP {
1400 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1401 return
1402 }
1403
1404 if vs.UpdateInProgress {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301405 vs.updateVnetProfile(cntx, vs.Device)
vinokuma926cb3e2023-03-29 11:41:06 +05301406 // Not sending DEL_HSIA Indication since it wil be generated internally by SubMgr
Naveen Sampath04696f72022-06-13 15:19:14 +05301407 return
1408 }
1409 logger.Infow(ctx, "All Flows removed for Service. Triggering Service De-activation Success indication to NB", log.Fields{"Service": vs.Name, "DeleteFlag": vs.DeleteInProgress})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301410 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301411
1412 return
1413 }
1414 logger.Infow(ctx, "Processed Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1415}
1416
vinokuma926cb3e2023-03-29 11:41:06 +05301417// FlowRemoveFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301418// Trigger service failure indication to NB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301419func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301420 vs.ServiceLock.RLock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301421 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 +05301422
1423 if _, ok := vs.AssociatedFlows[cookie]; !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301424 logger.Warnw(ctx, "Flow Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
Naveen Sampath04696f72022-06-13 15:19:14 +05301425 vs.ServiceLock.RUnlock()
1426 return
1427 }
1428 if vs.DeleteInProgress {
1429 delete(vs.AssociatedFlows, cookie)
1430 }
1431 vs.ServiceLock.RUnlock()
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301432 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 +05301433
1434 vs.triggerServiceFailureInd(errorCode, errReason)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301435 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301436}
1437
1438func (vs *VoltService) triggerServiceFailureInd(errorCode uint32, errReason string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301439 logger.Debugw(ctx, "Trigger Service Failure Ind", log.Fields{"Service": vs.Name, "Port": vs.Port})
Naveen Sampath04696f72022-06-13 15:19:14 +05301440 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1441 if err != nil {
1442 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1443 return
1444 } else if device.State != controller.DeviceStateUP {
1445 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1446 return
1447 }
1448}
1449
1450// RestoreSvcsFromDb read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301451func (va *VoltApplication) RestoreSvcsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301452 // VNETS must be learnt first
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301453 logger.Debug(ctx, "Restore Svcs From Db")
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301454 vss, _ := db.GetServices(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301455 for _, vs := range vss {
1456 b, ok := vs.Value.([]byte)
1457 if !ok {
1458 logger.Warn(ctx, "The value type is not []byte")
1459 continue
1460 }
1461 var vvs VoltService
1462 err := json.Unmarshal(b, &vvs)
1463 if err != nil {
1464 logger.Warn(ctx, "Unmarshal of VNET failed")
1465 continue
1466 }
1467 logger.Debugw(ctx, "Retrieved Service", log.Fields{"Service": vvs.VoltServiceCfg})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301468 if err := va.AddService(cntx, vvs.VoltServiceCfg, &vvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301469 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": vvs.Name, "Error": err})
1470 }
1471
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301472 if vvs.VoltServiceOper.DeactivateInProgress {
1473 va.ServicesToDeactivate[vvs.VoltServiceCfg.Name] = true
1474 logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
1475 }
1476
Naveen Sampath04696f72022-06-13 15:19:14 +05301477 if vvs.VoltServiceOper.DeleteInProgress {
1478 va.ServicesToDelete[vvs.VoltServiceCfg.Name] = true
1479 logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
1480 }
1481 }
1482}
1483
1484// GetService to get service
1485func (va *VoltApplication) GetService(name string) *VoltService {
1486 if vs, ok := va.ServiceByName.Load(name); ok {
1487 return vs.(*VoltService)
1488 }
1489 return nil
1490}
1491
1492// GetCircuitID to get circuit id
1493func (vs *VoltService) GetCircuitID() []byte {
1494 return []byte(vs.CircuitID)
1495}
1496
1497// GetRemoteID to get remote id
1498func (vs *VoltService) GetRemoteID() []byte {
1499 return []byte(vs.RemoteID)
1500}
1501
1502// IPAssigned to check if ip is assigned
1503func (vs *VoltService) IPAssigned() bool {
1504 if vs.Ipv4Addr != nil && !vs.Ipv4Addr.Equal(net.ParseIP("0.0.0.0")) {
1505 return true
1506 } else if vs.Ipv6Addr != nil && !vs.Ipv6Addr.Equal(net.ParseIP("0:0:0:0:0:0:0:0")) {
1507 return true
1508 }
1509 return false
1510}
1511
1512// GetServiceNameFromCookie to get service name from cookie
1513func (va *VoltApplication) GetServiceNameFromCookie(cookie uint64, portName string, pbit uint8, device string, tableMetadata uint64) *VoltService {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301514 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 +05301515 var vlan uint64
1516 vlanControl := (tableMetadata >> 32) & 0xF
1517
1518 if vlanControl == uint64(OLTCVlanOLTSVlan) {
1519 // Fetching UniVlan for vlanControl OLTCVLANOLTSVLAN
1520 vlan = (tableMetadata >> 16) & 0xFFFF
1521 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301522 // Fetching CVlan for other vlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301523 vlan = cookie >> 52
1524 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301525 logger.Debugw(ctx, "Configured Params", log.Fields{"VlanControl": vlanControl, "vlan": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301526 var vlans []of.VlanType
1527 vlans = append(vlans, of.VlanType(vlan))
1528 service := GetApplication().GetServiceFromCvlan(device, portName, vlans, uint8(pbit))
1529 if nil != service {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301530 logger.Infow(ctx, "Service Found for", log.Fields{"serviceName": service.Name, "portName": portName, "ctag": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301531 } else {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301532 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 +05301533 }
1534 return service
1535}
1536
vinokuma926cb3e2023-03-29 11:41:06 +05301537// MigrateServicesReqStatus - update vnet request status
Naveen Sampath04696f72022-06-13 15:19:14 +05301538type MigrateServicesReqStatus string
1539
1540const (
vinokuma926cb3e2023-03-29 11:41:06 +05301541 // MigrateSrvsReqInit constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301542 MigrateSrvsReqInit MigrateServicesReqStatus = "Init"
vinokuma926cb3e2023-03-29 11:41:06 +05301543 // MigrateSrvsReqDeactTriggered constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301544 MigrateSrvsReqDeactTriggered MigrateServicesReqStatus = "Profiles Deactivated"
vinokuma926cb3e2023-03-29 11:41:06 +05301545 // MigrateSrvsReqCompleted constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301546 MigrateSrvsReqCompleted MigrateServicesReqStatus = "Update Complete"
1547)
1548
vinokuma926cb3e2023-03-29 11:41:06 +05301549// MigrateServicesRequest - update vnet request params
Naveen Sampath04696f72022-06-13 15:19:14 +05301550type MigrateServicesRequest struct {
1551 ID string
1552 OldVnetID string
1553 NewVnetID string
1554 ServicesList map[string]bool
1555 DeviceID string
1556 Status MigrateServicesReqStatus
1557 MigrateServicesLock sync.RWMutex
1558}
1559
1560func newMigrateServicesRequest(id string, oldVnetID string, newVnetID string, serviceMap map[string]bool, deviceID string) *MigrateServicesRequest {
Naveen Sampath04696f72022-06-13 15:19:14 +05301561 var msr MigrateServicesRequest
1562 msr.OldVnetID = oldVnetID
1563 msr.NewVnetID = newVnetID
1564 msr.ID = id
1565 msr.ServicesList = serviceMap
1566 msr.DeviceID = deviceID
1567 msr.Status = MigrateSrvsReqInit
1568 return &msr
1569}
1570
vinokuma926cb3e2023-03-29 11:41:06 +05301571// GetMsrKey - generates migrate service request key
Naveen Sampath04696f72022-06-13 15:19:14 +05301572func (msr *MigrateServicesRequest) GetMsrKey() string {
1573 return msr.OldVnetID + "-" + msr.ID
1574}
1575
1576// //isRequestComplete - return if all request has been processed and completed
1577// // RequestProcessed indicates that all the profile de-activation has been triggered
1578// // And the associated profiles indicates the profiles awaiting results
1579// func (msr *MigrateServicesRequest) isRequestComplete() bool {
1580// //return edr.RequestProcessed && (len(edr.AssociatedProfiles) == 0)
1581// return (len(edr.AssociatedProfiles) == 0)
1582// }
1583
vinokuma926cb3e2023-03-29 11:41:06 +05301584// WriteToDB - writes the udpate vnet request details ot DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301585func (msr *MigrateServicesRequest) WriteToDB(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301586 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)})
1587 if b, err := json.Marshal(msr); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301588 if err = db.PutMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey(), string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301589 logger.Warnw(ctx, "PutMigrateServicesReq Failed", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID,
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05301590 "Device": msr.DeviceID, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301591 }
1592 }
1593}
1594
vinokuma926cb3e2023-03-29 11:41:06 +05301595// MigrateServices - updated vnet profile for services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301596func (va *VoltApplication) MigrateServices(cntx context.Context, serialNum string, reqID string, oldVnetID, newVnetID string, serviceList []string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301597 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 +05301598 if _, ok := va.VnetsByName.Load(oldVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301599 return errors.New("old vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301600 }
1601 if _, ok := va.VnetsByName.Load(newVnetID); !ok {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301602 return errors.New("new vnet id not found")
Naveen Sampath04696f72022-06-13 15:19:14 +05301603 }
1604
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301605 d, _ := va.GetDeviceBySerialNo(serialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301606 if d == nil {
1607 logger.Errorw(ctx, "Error Getting Device", log.Fields{"SerialNum": serialNum})
1608 return errorCodes.ErrDeviceNotFound
1609 }
1610
1611 serviceMap := make(map[string]bool)
1612
1613 for _, service := range serviceList {
1614 serviceMap[service] = false
1615 }
1616 msr := newMigrateServicesRequest(reqID, oldVnetID, newVnetID, serviceMap, d.Name)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301617 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301618
1619 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301620 go msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301621 return nil
1622}
1623
vinokuma926cb3e2023-03-29 11:41:06 +05301624// ProcessMigrateServicesProfRequest - collects all associated profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301625func (msr *MigrateServicesRequest) ProcessMigrateServicesProfRequest(cntx context.Context) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301626 logger.Debug(ctx, "Process Migrate Services Prof Request")
Naveen Sampath04696f72022-06-13 15:19:14 +05301627 va := GetApplication()
1628 for srv, processed := range msr.ServicesList {
vinokuma926cb3e2023-03-29 11:41:06 +05301629 // Indicates new service is already created and only deletion of old one is pending
Naveen Sampath04696f72022-06-13 15:19:14 +05301630 if processed {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301631 va.DelService(cntx, srv, true, nil, true)
1632 msr.serviceMigrated(cntx, srv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301633 continue
1634 }
1635
1636 logger.Infow(ctx, "Migrate Service Triggering", log.Fields{"Service": srv})
1637 if vsIntf, ok := va.ServiceByName.Load(srv); ok {
1638 vs := vsIntf.(*VoltService)
1639 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1640 if vpv == nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301641 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 +05301642 continue
1643 }
1644 logger.Infow(ctx, "Migrating Service", log.Fields{"Service": vs.Name, "UsFlowApplied": vs.UsHSIAFlowsApplied})
1645 vpv.Blocked = true
1646
1647 // setDeactTrigger := func(key, value interface{}) bool {
1648 // vs := value.(*VoltService)
1649 vs.ServiceLock.Lock()
1650 vs.UpdateInProgress = true
1651 metadata := &MigrateServiceMetadata{
1652 NewVnetID: msr.NewVnetID,
1653 RequestID: msr.ID,
1654 }
1655 vs.Metadata = metadata
1656 vs.ServiceLock.Unlock()
1657
vinokuma926cb3e2023-03-29 11:41:06 +05301658 // vpv flows will be removed when last service is removed from it and
Naveen Sampath04696f72022-06-13 15:19:14 +05301659 // new vpv flows will be installed when new service is added
1660 if vs.UsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301661 vpv.DelTrapFlows(cntx)
1662 vs.DelHsiaFlows(cntx)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301663 logger.Infow(ctx, "Remove Service Flows Triggered", log.Fields{"Service": srv, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301664 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301665 vs.updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301666 }
1667 } else {
1668 logger.Warnw(ctx, "Migrate Service Failed: Service Not Found", log.Fields{"Service": srv, "Vnet": msr.OldVnetID})
1669 }
1670 }
1671}
1672
vinokuma926cb3e2023-03-29 11:41:06 +05301673// AddMigratingServices - store msr info to device obj
Naveen Sampath04696f72022-06-13 15:19:14 +05301674func (d *VoltDevice) AddMigratingServices(msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301675 logger.Infow(ctx, "Add Migrating Services", log.Fields{"Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301676 var msrMap *util.ConcurrentMap
1677 if msrMapIntf, ok := d.MigratingServices.Get(msr.OldVnetID); !ok {
1678 msrMap = util.NewConcurrentMap()
1679 } else {
1680 msrMap = msrMapIntf.(*util.ConcurrentMap)
1681 }
1682
1683 msrMap.Set(msr.ID, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301684 logger.Debugw(ctx, "1: MsrListLen", log.Fields{"Len": msrMap.Length(), "Vnet": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301685
1686 d.MigratingServices.Set(msr.OldVnetID, msrMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301687 logger.Debugw(ctx, "1: DeviceMsr", log.Fields{"Device": d.Name, "Vnet": msr.OldVnetID, "Len": d.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301688}
1689
vinokuma926cb3e2023-03-29 11:41:06 +05301690// getMigrateServicesRequest - fetches msr info from device
Naveen Sampath04696f72022-06-13 15:19:14 +05301691func (va *VoltApplication) getMigrateServicesRequest(deviceID string, oldVnetID string, requestID string) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301692 logger.Debugw(ctx, "Get Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301693 if vd := va.GetDevice(deviceID); vd != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301694 logger.Debugw(ctx, "2: DeviceMsr", log.Fields{"Device": deviceID, "Vnet": oldVnetID, "Len": vd.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301695 if msrListIntf, ok := vd.MigratingServices.Get(oldVnetID); ok {
1696 msrList := msrListIntf.(*util.ConcurrentMap)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301697 logger.Debugw(ctx, "2: MsrListLen", log.Fields{"Len": msrList.Length(), "Vnet": oldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301698 if msrObj, ok := msrList.Get(requestID); ok {
1699 return msrObj.(*MigrateServicesRequest)
1700 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301701 }
1702 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301703 logger.Warnw(ctx, "Device Not Found", log.Fields{"DeviceID": deviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301704 return nil
1705}
1706
vinokuma926cb3e2023-03-29 11:41:06 +05301707// updateMigrateServicesRequest - Updates the device with updated msr
Naveen Sampath04696f72022-06-13 15:19:14 +05301708func (va *VoltApplication) updateMigrateServicesRequest(deviceID string, oldVnetID string, requestID string, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301709 logger.Debugw(ctx, "Update Migrate Services Request", log.Fields{"DeviceID": deviceID, "OldVnetID": oldVnetID, "RequestID": requestID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301710 if vd := va.GetDevice(deviceID); vd != nil {
1711 if msrList, ok := vd.MigratingServices.Get(oldVnetID); ok {
1712 if _, ok := msrList.(*util.ConcurrentMap).Get(requestID); ok {
1713 msrList.(*util.ConcurrentMap).Set(requestID, msr)
1714 }
1715 }
1716 }
1717}
1718
vinokuma926cb3e2023-03-29 11:41:06 +05301719// updateVnetProfile - Called on flow process completion
1720// Removes old service and creates new VPV & service with updated vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301721func (vs *VoltService) updateVnetProfile(cntx context.Context, deviceID string) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301722 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 +05301723
1724 nvs := VoltService{}
1725 nvs.VoltServiceCfg = vs.VoltServiceCfg
1726 nvs.Device = vs.Device
1727 nvs.Ipv4Addr = vs.Ipv4Addr
1728 nvs.Ipv6Addr = vs.Ipv6Addr
1729 nvs.UsMeterID = vs.UsMeterID
1730 nvs.DsMeterID = vs.DsMeterID
1731 nvs.AggDsMeterID = vs.AggDsMeterID
1732 nvs.UsHSIAFlowsApplied = vs.UsHSIAFlowsApplied
1733 nvs.DsHSIAFlowsApplied = vs.DsHSIAFlowsApplied
1734 nvs.UsDhcpFlowsApplied = vs.UsDhcpFlowsApplied
1735 nvs.DsDhcpFlowsApplied = vs.DsDhcpFlowsApplied
1736 nvs.IgmpFlowsApplied = vs.IgmpFlowsApplied
1737 nvs.Icmpv6FlowsApplied = vs.Icmpv6FlowsApplied
1738 nvs.PendingFlows = vs.PendingFlows
1739 nvs.AssociatedFlows = vs.AssociatedFlows
1740 nvs.DeleteInProgress = vs.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301741 nvs.DeactivateInProgress = vs.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301742 nvs.ForceDelete = vs.ForceDelete
1743 nvs.BwAvailInfo = vs.BwAvailInfo
1744 nvs.UpdateInProgress = vs.UpdateInProgress
1745
1746 if nvs.DeleteInProgress {
1747 logger.Warnw(ctx, "Skipping Service Migration. Service Delete in Progress", log.Fields{"Device": deviceID, "Service": vs.Name, "Vnet": vs.VnetID})
1748 return
1749 }
1750
1751 metadata := vs.Metadata.(*MigrateServiceMetadata)
1752 oldVnetID := vs.VnetID
Naveen Sampath04696f72022-06-13 15:19:14 +05301753 oldSrvName := vs.Name
1754
1755 if metadata == nil || metadata.NewVnetID == "" {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301756 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 +05301757 return
1758 }
1759
vinokuma926cb3e2023-03-29 11:41:06 +05301760 nvs.VnetID = metadata.NewVnetID
1761 id := metadata.RequestID
1762
1763 // First add the new service and then only delete the old service
Naveen Sampath04696f72022-06-13 15:19:14 +05301764 // Since if post del service in case of pod crash or reboot, the service data will be lost
1765 va := GetApplication()
1766 msr := va.getMigrateServicesRequest(deviceID, oldVnetID, id)
1767 vnets := strings.Split(metadata.NewVnetID, "-")
1768 svlan, _ := strconv.Atoi(vnets[0])
1769 nvs.SVlan = of.VlanType(svlan)
1770 nvs.UpdateInProgress = false
1771 nvs.Metadata = nil
1772 nvs.Trigger = ServiceVlanUpdate
1773
1774 svcName := vs.Port + "-" + strconv.FormatUint(uint64(nvs.SVlan), 10) + "-"
1775 svcName = svcName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1776 nvs.Name = svcName + strconv.FormatUint(uint64(vs.TechProfileID), 10)
1777
vinokuma926cb3e2023-03-29 11:41:06 +05301778 // TODO:Nav Pass a copy, not the pointer
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301779 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 +05301780 if err := va.AddService(cntx, nvs.VoltServiceCfg, &nvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301781 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": nvs.Name, "Error": err})
1782 }
1783 logger.Infow(ctx, "Add New Service Triggered", log.Fields{"Service": nvs.Name, "US": nvs.UsHSIAFlowsApplied, "DS": nvs.DsHSIAFlowsApplied, "DelFlag": nvs.DeleteInProgress})
1784
1785 msr.ServicesList[oldSrvName] = true
1786 va.updateMigrateServicesRequest(deviceID, oldVnetID, id, msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301787 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301788
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301789 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 +05301790 va.DelService(cntx, oldSrvName, true, nil, true)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301791 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 +05301792 msr.serviceMigrated(cntx, oldSrvName)
Naveen Sampath04696f72022-06-13 15:19:14 +05301793}
1794
vinokuma926cb3e2023-03-29 11:41:06 +05301795// serviceMigrated - called on successful service updation
Naveen Sampath04696f72022-06-13 15:19:14 +05301796// Removes the service entry from servicelist and deletes the request on process completion
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301797func (msr *MigrateServicesRequest) serviceMigrated(cntx context.Context, serviceName string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301798 logger.Infow(ctx, "Service Migrated", log.Fields{"ServiceName": serviceName})
Naveen Sampath04696f72022-06-13 15:19:14 +05301799 msr.MigrateServicesLock.Lock()
1800 defer msr.MigrateServicesLock.Unlock()
1801
1802 delete(msr.ServicesList, serviceName)
1803
1804 if len(msr.ServicesList) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301805 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301806 return
1807 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301808 msr.WriteToDB(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +05301809 // TODO:Nav - Need for any Response to SubMgr?
Naveen Sampath04696f72022-06-13 15:19:14 +05301810}
1811
vinokuma926cb3e2023-03-29 11:41:06 +05301812// TriggerPendingMigrateServicesReq - trigger pending service request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301813func (va *VoltApplication) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
1814 va.FetchAndProcessAllMigrateServicesReq(cntx, device, storeAndProcessMigrateSrvRequest)
Naveen Sampath04696f72022-06-13 15:19:14 +05301815}
1816
vinokuma926cb3e2023-03-29 11:41:06 +05301817// FetchAndProcessAllMigrateServicesReq - fetch all pending migrate services req from DB and process based on provided func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301818func (va *VoltApplication) FetchAndProcessAllMigrateServicesReq(cntx context.Context, device string, msrAction func(context.Context, *MigrateServicesRequest)) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301819 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 +05301820 msrList, _ := db.GetAllMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301821 for _, msr := range msrList {
1822 b, ok := msr.Value.([]byte)
1823 if !ok {
1824 logger.Warn(ctx, "The value type is not []byte")
1825 continue
1826 }
1827 msr := va.createMigrateServicesFromString(b)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301828 msrAction(cntx, msr)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301829 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 +05301830 }
1831}
1832
1833// createMigrateServicesFromString to create Service from string
1834func (va *VoltApplication) createMigrateServicesFromString(b []byte) *MigrateServicesRequest {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301835 logger.Info(ctx, "Create Migrate Services From String")
Naveen Sampath04696f72022-06-13 15:19:14 +05301836 var msr MigrateServicesRequest
1837 if err := json.Unmarshal(b, &msr); err == nil {
1838 logger.Debugw(ctx, "Adding Migrate Services Request From Db", log.Fields{"Vlan": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301839 } else {
1840 logger.Warn(ctx, "Unmarshal failed")
1841 }
1842 return &msr
1843}
1844
vinokuma926cb3e2023-03-29 11:41:06 +05301845// storeAndProcessMigrateSrvRequest - stores the msr info in device obj and triggers req
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301846func storeAndProcessMigrateSrvRequest(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301847 logger.Infow(ctx, "Store And Process Migrate Srv Request", log.Fields{"MsrID": msr.DeviceID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301848 d := GetApplication().GetDevice(msr.DeviceID)
1849 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301850 msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301851}
1852
vinokuma926cb3e2023-03-29 11:41:06 +05301853// forceUpdateAllServices - force udpate services with new vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301854func forceUpdateAllServices(cntx context.Context, msr *MigrateServicesRequest) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301855 logger.Infow(ctx, "Force udpate services with new vnet profile", log.Fields{"MsrID": msr.NewVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301856 for srv := range msr.ServicesList {
1857 if vsIntf, ok := GetApplication().ServiceByName.Load(srv); ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301858 vsIntf.(*VoltService).updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301859 }
1860 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301861 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301862}
1863
vinokuma926cb3e2023-03-29 11:41:06 +05301864// nolint: gocyclo
1865// DeepEqualServicecfg - checks if the given service cfgs are same
Naveen Sampath04696f72022-06-13 15:19:14 +05301866func (va *VoltApplication) DeepEqualServicecfg(evs *VoltServiceCfg, nvs *VoltServiceCfg) bool {
1867 if nvs.Name != evs.Name {
1868 return false
1869 }
1870 if nvs.UniVlan != evs.UniVlan {
1871 return false
1872 }
1873 if nvs.CVlan != evs.CVlan {
1874 return false
1875 }
1876 if nvs.SVlan != evs.SVlan {
1877 return false
1878 }
1879 if nvs.SVlanTpid != 0 && nvs.SVlanTpid != evs.SVlanTpid {
1880 return false
1881 }
1882 if !util.IsPbitSliceSame(nvs.Pbits, evs.Pbits) {
1883 return false
1884 }
1885 if !reflect.DeepEqual(nvs.DsRemarkPbitsMap, evs.DsRemarkPbitsMap) {
1886 return false
1887 }
1888 if nvs.TechProfileID != evs.TechProfileID {
1889 return false
1890 }
1891 if nvs.CircuitID != evs.CircuitID {
1892 return false
1893 }
1894 if !bytes.Equal(nvs.RemoteID, evs.RemoteID) {
1895 return false
1896 }
1897 if nvs.Port != evs.Port {
1898 return false
1899 }
1900 if nvs.PonPort != evs.PonPort {
1901 return false
1902 }
1903 if evs.MacLearning == MacLearningNone && !util.MacAddrsMatch(nvs.MacAddr, evs.MacAddr) {
1904 return false
1905 }
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05301906 if nvs.IsOption82Enabled != evs.IsOption82Enabled {
Naveen Sampath04696f72022-06-13 15:19:14 +05301907 return false
1908 }
1909 if nvs.IgmpEnabled != evs.IgmpEnabled {
1910 return false
1911 }
1912 if nvs.McastService != evs.McastService {
1913 return false
1914 }
1915 if nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification {
1916 return false
1917 }
1918 if nvs.UsMeterProfile != evs.UsMeterProfile {
1919 return false
1920 }
1921 if nvs.DsMeterProfile != evs.DsMeterProfile {
1922 return false
1923 }
1924 if nvs.AggDsMeterProfile != evs.AggDsMeterProfile {
1925 return false
1926 }
1927 if nvs.VnetID != evs.VnetID {
1928 return false
1929 }
1930 if nvs.MvlanProfileName != evs.MvlanProfileName {
1931 return false
1932 }
1933 if nvs.RemoteIDType != evs.RemoteIDType {
1934 return false
1935 }
1936 if nvs.SchedID != evs.SchedID {
1937 return false
1938 }
1939 if nvs.AllowTransparent != evs.AllowTransparent {
1940 return false
1941 }
1942 if nvs.EnableMulticastKPI != evs.EnableMulticastKPI {
1943 return false
1944 }
1945 if nvs.DataRateAttr != evs.DataRateAttr {
1946 return false
1947 }
1948 if nvs.MinDataRateUs != evs.MinDataRateUs {
1949 return false
1950 }
1951 if nvs.MinDataRateDs != evs.MinDataRateDs {
1952 return false
1953 }
1954 if nvs.MaxDataRateUs != evs.MaxDataRateUs {
1955 return false
1956 }
1957 if nvs.MaxDataRateDs != evs.MaxDataRateDs {
1958 return false
1959 }
1960
1961 return true
1962}
1963
vinokuma926cb3e2023-03-29 11:41:06 +05301964// TriggerAssociatedFlowDelete - re-trigger service flow delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301965func (vs *VoltService) TriggerAssociatedFlowDelete(cntx context.Context) bool {
vinokuma926cb3e2023-03-29 11:41:06 +05301966 // Clear the Flows flag if already set
1967 // This case happens only in case of some race condition
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301968 logger.Infow(ctx, "Trigger Associated Flow Delete", log.Fields{"Device": vs.Device, "Service": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301969 if vs.UsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301970 if err := vs.DelUsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301971 logger.Warnw(ctx, "DelUsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301972 }
1973 }
1974
1975 if vs.DsHSIAFlowsApplied {
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05301976 if err := vs.DelDsHsiaFlows(cntx, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05301977 logger.Warnw(ctx, "DelDsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301978 }
1979 }
1980
1981 vs.ServiceLock.Lock()
1982 cookieList := []uint64{}
1983 for cookie := range vs.AssociatedFlows {
1984 cookieList = append(cookieList, convertToUInt64(cookie))
1985 }
1986 vs.ServiceLock.Unlock()
1987
1988 if len(cookieList) == 0 {
1989 return false
1990 }
1991
vinokuma926cb3e2023-03-29 11:41:06 +05301992 // Trigger Flow Delete
Naveen Sampath04696f72022-06-13 15:19:14 +05301993 for _, cookie := range cookieList {
1994 if vd := GetApplication().GetDevice(vs.Device); vd != nil {
1995 flow := &of.VoltFlow{}
1996 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1997 subFlow := of.NewVoltSubFlow()
1998 subFlow.Cookie = cookie
1999 flow.SubFlows[cookie] = subFlow
2000 logger.Infow(ctx, "Retriggering Service Delete Flow", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie})
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302001 if err := vs.DelFlows(cntx, vd, flow, false); err != nil {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302002 logger.Warnw(ctx, "DelFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05302003 }
2004 }
2005 }
2006 return true
2007}
2008
vinokuma926cb3e2023-03-29 11:41:06 +05302009// triggerServiceInProgressInd - Indication is generated when Service is not provisioned after add serviec req from NB
Naveen Sampath04696f72022-06-13 15:19:14 +05302010func (vs *VoltService) triggerServiceInProgressInd() {
2011}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302012
vinokuma926cb3e2023-03-29 11:41:06 +05302013// JSONMarshal wrapper function for json Marshal VoltService
2014func (vs *VoltService) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302015 return json.Marshal(VoltService{
2016 VoltServiceCfg: vs.VoltServiceCfg,
2017 VoltServiceOper: VoltServiceOper{
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302018 Device: vs.VoltServiceOper.Device,
2019 Ipv4Addr: vs.VoltServiceOper.Ipv4Addr,
2020 Ipv6Addr: vs.VoltServiceOper.Ipv6Addr,
2021 UsMeterID: vs.VoltServiceOper.UsMeterID,
2022 DsMeterID: vs.VoltServiceOper.DsMeterID,
2023 AggDsMeterID: vs.VoltServiceOper.AggDsMeterID,
2024 UsHSIAFlowsApplied: vs.VoltServiceOper.UsHSIAFlowsApplied,
2025 DsHSIAFlowsApplied: vs.VoltServiceOper.DsHSIAFlowsApplied,
2026 UsDhcpFlowsApplied: vs.VoltServiceOper.UsDhcpFlowsApplied,
2027 DsDhcpFlowsApplied: vs.VoltServiceOper.DsDhcpFlowsApplied,
2028 IgmpFlowsApplied: vs.VoltServiceOper.IgmpFlowsApplied,
2029 Icmpv6FlowsApplied: vs.VoltServiceOper.Icmpv6FlowsApplied,
2030 PendingFlows: vs.VoltServiceOper.PendingFlows,
2031 AssociatedFlows: vs.VoltServiceOper.AssociatedFlows,
2032 DeleteInProgress: vs.VoltServiceOper.DeleteInProgress,
2033 DeactivateInProgress: vs.VoltServiceOper.DeactivateInProgress,
2034 ForceDelete: vs.VoltServiceOper.ForceDelete,
2035 BwAvailInfo: vs.VoltServiceOper.BwAvailInfo,
2036 UpdateInProgress: vs.VoltServiceOper.UpdateInProgress,
2037 Metadata: vs.VoltServiceOper.Metadata,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302038 },
2039 })
2040}
Tinoj Josephec742f62022-09-29 19:11:10 +05302041
2042// GetProgrammedSubscribers to get list of programmed subscribers
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302043func (va *VoltApplication) GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302044 var svcList []*VoltService
2045 logger.Infow(ctx, "GetProgrammedSubscribers Request ", log.Fields{"Device": deviceID, "Port": portNo})
2046 va.ServiceByName.Range(func(key, value interface{}) bool {
2047 vs := value.(*VoltService)
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302048 if len(deviceID) > 0 {
2049 if len(portNo) > 0 {
Tinoj Josephec742f62022-09-29 19:11:10 +05302050 if deviceID == vs.Device && portNo == vs.Port {
2051 svcList = append(svcList, vs)
2052 }
2053 } else {
2054 if deviceID == vs.Device {
2055 svcList = append(svcList, vs)
2056 }
2057 }
2058 } else {
2059 svcList = append(svcList, vs)
2060 }
2061 return true
2062 })
2063 return svcList, nil
2064}
2065
Akash Soni634d9bf2023-07-10 12:11:10 +05302066type FlowProvisionStatus struct {
2067 FlowProvisionStatus string
2068}
2069
2070// GetFlowProvisionStatus to get status of the subscriber and flow provisioned in controller
Akash Soni3c391e72023-08-16 12:21:33 +05302071func (va *VoltApplication) GetFlowProvisionStatus(portNo string) FlowProvisionStatus {
Akash Soni634d9bf2023-07-10 12:11:10 +05302072 logger.Infow(ctx, "GetFlowProvisionStatus Request ", log.Fields{"Port": portNo})
2073 flowProvisionStatus := FlowProvisionStatus{}
Akash Soni3c391e72023-08-16 12:21:33 +05302074 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
Akash Soni634d9bf2023-07-10 12:11:10 +05302075 va.ServiceByName.Range(func(key, value interface{}) bool {
2076 vs := value.(*VoltService)
2077 logger.Debugw(ctx, "Volt Service ", log.Fields{"VS": vs})
Akash Soni3c391e72023-08-16 12:21:33 +05302078 if portNo == vs.Port {
2079 if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() == 0 {
2080 flowProvisionStatus.FlowProvisionStatus = ALL_FLOWS_PROVISIONED
2081 return false
2082 } else if !vs.IsActivated {
2083 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_DISABLED_IN_CONTROLLER
2084 return false
2085 } else if !vs.DsHSIAFlowsApplied && !vs.UsHSIAFlowsApplied {
2086 flowProvisionStatus.FlowProvisionStatus = NO_FLOWS_PROVISIONED
2087 return false
2088 } else if vs.LenOfPendingFlows() > 0 {
2089 flowProvisionStatus.FlowProvisionStatus = FLOWS_PROVISIONED_PARTIALLY
2090 return false
Akash Soni634d9bf2023-07-10 12:11:10 +05302091 }
2092 }
2093 return true
2094 })
Akash Soni634d9bf2023-07-10 12:11:10 +05302095 return flowProvisionStatus
2096}
2097
2098func (vs *VoltService) LenOfPendingFlows() int {
2099 vs.ServiceLock.RLock()
2100 lth := len(vs.PendingFlows)
2101 vs.ServiceLock.RUnlock()
2102 return lth
2103}
2104
Tinoj Josephec742f62022-09-29 19:11:10 +05302105// ActivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302106func (va *VoltApplication) ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302107 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 +05302108 device, err := va.GetDeviceFromPort(portNo)
2109 if err != nil {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302110 // Lets activate the service even though port was not found. We will push the flows once the port is added by voltha
2111 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 +05302112 }
2113 // If device id is not provided check only port number
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302114 if device != nil {
2115 if deviceID == DeviceAny {
2116 deviceID = device.Name
2117 } else if deviceID != device.Name {
2118 logger.Errorw(ctx, "Wrong Device ID", log.Fields{"Device": deviceID, "Port": portNo})
2119 return errorCodes.ErrDeviceNotFound
2120 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302121 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302122 va.ServiceByName.Range(func(key, value interface{}) bool {
2123 vs := value.(*VoltService)
Tinoj Josephec742f62022-09-29 19:11:10 +05302124 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302125 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302126 logger.Infow(ctx, "Service Activate Request Does not match", log.Fields{"Device": deviceID, "voltService": vs})
Tinoj Josephec742f62022-09-29 19:11:10 +05302127 return true
2128 }
2129 if portNo == vs.Port && !vs.IsActivated {
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302130 // Mark the service as activated, so that we can push the flows later when the port is added by voltha
2131 logger.Infow(ctx, "Service Activate", log.Fields{"Name": vs.Name})
Tinoj Josephec742f62022-09-29 19:11:10 +05302132 vs.IsActivated = true
2133 va.ServiceByName.Store(vs.Name, vs)
2134 vs.WriteToDb(cntx)
Sridhar Ravindraf8251e72023-09-06 17:09:30 +05302135
2136 // Push the flows only if the port is already added and we have a valid device
2137 if device != nil {
2138 p := device.GetPort(vs.Port)
2139 if p == nil {
2140 logger.Warnw(ctx, "Wrong device or port", log.Fields{"Device": deviceID, "Port": portNo})
2141 return true
2142 }
2143 // If port is already up send indication to vpv
2144 if p.State == PortStateUp {
2145 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2146 // PortUp call initiates flow addition
2147 vpv.PortUpInd(cntx, device, portNo)
2148 } else {
2149 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2150 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302151 }
2152 }
2153 }
2154 return true
2155 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302156 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302157}
2158
2159// DeactivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302160func (va *VoltApplication) DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302161 logger.Infow(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo, "Svaln": sVlan, "Cvlan": cVlan, "TpID": tpID})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302162
Tinoj Josephec742f62022-09-29 19:11:10 +05302163 va.ServiceByName.Range(func(key, value interface{}) bool {
2164 vs := value.(*VoltService)
2165 // If svlan if provided, then the tags and tpID of service has to be matching
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302166 logger.Debugw(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo})
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302167 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302168 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 +05302169 return true
2170 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302171 if portNo == vs.Port && vs.IsActivated {
Tinoj Josephec742f62022-09-29 19:11:10 +05302172 vs.IsActivated = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302173 vs.DeactivateInProgress = true
Tinoj Josephec742f62022-09-29 19:11:10 +05302174 va.ServiceByName.Store(vs.Name, vs)
2175 vs.WriteToDb(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302176 device, err := va.GetDeviceFromPort(portNo)
2177 if err != nil {
2178 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
2179 // So no error is returned
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +05302180 logger.Warnw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portNo})
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302181 return true
2182 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302183 p := device.GetPort(vs.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05302184 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302185 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2186 // Port down call internally deletes all the flows
Sridhar Ravindra03aa0bf2023-09-12 17:46:40 +05302187 vpv.PortDownInd(cntx, deviceID, portNo, true, false)
Tinoj Josephec742f62022-09-29 19:11:10 +05302188 if vpv.IgmpEnabled {
2189 va.ReceiverDownInd(cntx, deviceID, portNo)
2190 }
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302191 vs.DeactivateInProgress = false
Tinoj Josephec742f62022-09-29 19:11:10 +05302192 } else {
2193 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2194 }
2195 }
2196 }
2197 return true
2198 })
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302199 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302200}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302201
vinokuma926cb3e2023-03-29 11:41:06 +05302202// GetServicePbit to get first set bit in the pbit map
2203// returns -1 : If configured to match on all pbits
2204// returns 8 : If no pbits are configured
2205// returns first pbit if specific pbit is configured
Tinoj Josephec742f62022-09-29 19:11:10 +05302206func (vs *VoltService) GetServicePbit() int {
2207 if vs.IsPbitExist(of.PbitMatchAll) {
2208 return -1
2209 }
vinokuma926cb3e2023-03-29 11:41:06 +05302210 for pbit := 0; pbit < int(of.PbitMatchNone); pbit++ {
Tinoj Josephec742f62022-09-29 19:11:10 +05302211 if vs.IsPbitExist(of.PbitType(pbit)) {
2212 return pbit
2213 }
2214 }
2215 return int(of.PbitMatchNone)
2216}