blob: 532ff62093121beb324ffe9bfee24a29c0aba648 [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"
23 "net"
24 "reflect"
Naveen Sampath04696f72022-06-13 15:19:14 +053025 "sort"
26 "strconv"
27 "strings"
28 "sync"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053029 infraerrorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053030
31 "github.com/google/gopacket/layers"
32
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053033 "voltha-go-controller/database"
Naveen Sampath04696f72022-06-13 15:19:14 +053034 "voltha-go-controller/internal/pkg/controller"
35 cntlr "voltha-go-controller/internal/pkg/controller"
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +053036 errorCodes "voltha-go-controller/internal/pkg/errorcodes"
Naveen Sampath04696f72022-06-13 15:19:14 +053037 "voltha-go-controller/internal/pkg/of"
38 "voltha-go-controller/internal/pkg/util"
Tinoj Joseph1d108322022-07-13 10:07:39 +053039 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053040)
41
42const (
43 // DSLAttrEnabled constant
44 DSLAttrEnabled string = "ENABLED"
Tinoj Josephec742f62022-09-29 19:11:10 +053045 // DeviceAny constant
46 DeviceAny string = "DEVICE-ANY"
Akash Soni634d9bf2023-07-10 12:11:10 +053047
48 ALL_FLOWS_PROVISIONED string = "ALL_FLOWS_PROVISIONED"
49
50 NO_FLOWS_PROVISIONED string = "NO_FLOWS_PROVISIONED"
51
52 FLOWS_PROVISIONED_PARTIALLY string = "FLOWS_PROVISIONED_PARTIALLY"
53
54 SUBSCRIBER_DISABLED_IN_CONTROLLER string = "DISABLED_IN_CONTROLLER"
55
56 SUBSCRIBER_NOT_IN_CONTROLLER string = "NOT_IN_CONTROLLER"
57
58 ONT_FLOWS_PROVISION_STATE_UNUSED string = "ONT_FLOWS_PROVISION_STATE_UNUSED"
Naveen Sampath04696f72022-06-13 15:19:14 +053059)
60
61// VoltServiceCfg structure
62// Name - Uniquely identifies a service across the entire application
63// UniVlan - The VLAN of the packets entering the UNI of ONU
64// CVlan - The VLAN to transalate to/from on the PON link
65// SVlan - The outer VLAN to be used on the NNI of OLT.
vinokuma926cb3e2023-03-29 11:41:06 +053066// - In general, 4096 is used as NO VLAN for all the above
67// SVlanTpid - SVlan Tag Protocol Identifier
Naveen Sampath04696f72022-06-13 15:19:14 +053068// Pbits - Each bit of uint8 represents one p-bit. MSB is pbit 7
69// DhcpRelay - Whether it is turned on/off
70// CircuitId - The circuit id to be used with DHCP relay. Unused otherwise
71// RemoveId - Same as above
72// Port - The access port for the service. Each service has a single access
vinokuma926cb3e2023-03-29 11:41:06 +053073// port. The converse is not always true
Naveen Sampath04696f72022-06-13 15:19:14 +053074// MacLearning - If MAC learning is turned on, the MAC address learned from the
vinokuma926cb3e2023-03-29 11:41:06 +053075// the service activation is used in programming flows
Naveen Sampath04696f72022-06-13 15:19:14 +053076// MacAddress - The MAC hardware address learnt on the UNI interface
77// MacAddresses - Not yet implemented. To be used to learn more MAC addresses
78type VoltServiceCfg struct {
Naveen Sampath04696f72022-06-13 15:19:14 +053079 Pbits []of.PbitType
vinokuma926cb3e2023-03-29 11:41:06 +053080 Name string
Naveen Sampath04696f72022-06-13 15:19:14 +053081 CircuitID string
Naveen Sampath04696f72022-06-13 15:19:14 +053082 Port string
Naveen Sampath04696f72022-06-13 15:19:14 +053083 UsMeterProfile string
84 DsMeterProfile string
85 AggDsMeterProfile string
86 VnetID string
87 MvlanProfileName string
88 RemoteIDType string
Naveen Sampath04696f72022-06-13 15:19:14 +053089 DataRateAttr string
vinokuma926cb3e2023-03-29 11:41:06 +053090 ServiceType string
91 DsRemarkPbitsMap map[int]int // Ex: Remark case {0:0,1:0} and No-remark case {1:1}
92 RemoteID []byte
93 MacAddr net.HardwareAddr
94 ONTEtherTypeClassification int
95 SchedID int
96 Trigger ServiceTrigger
97 MacLearning MacLearningType
98 PonPort uint32
Naveen Sampath04696f72022-06-13 15:19:14 +053099 MinDataRateUs uint32
100 MinDataRateDs uint32
101 MaxDataRateUs uint32
102 MaxDataRateDs uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530103 TechProfileID uint16
104 SVlanTpid layers.EthernetType
105 UniVlan of.VlanType
106 CVlan of.VlanType
107 SVlan of.VlanType
108 UsPonCTagPriority of.PbitType
109 UsPonSTagPriority of.PbitType
110 DsPonSTagPriority of.PbitType
111 DsPonCTagPriority of.PbitType
112 VlanControl VlanControl
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530113 IsOption82Enabled bool
vinokuma926cb3e2023-03-29 11:41:06 +0530114 IgmpEnabled bool
115 McastService bool
116 AllowTransparent bool
117 EnableMulticastKPI bool
Tinoj Josephec742f62022-09-29 19:11:10 +0530118 IsActivated bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530119}
120
121// VoltServiceOper structure
122type VoltServiceOper struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530123 Metadata interface{}
124 PendingFlows map[string]bool
125 AssociatedFlows map[string]bool
126 BwAvailInfo string
Naveen Sampath04696f72022-06-13 15:19:14 +0530127 //MacLearning bool
128 //MacAddr net.HardwareAddr
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530129 Device string
130 Ipv4Addr net.IP
131 Ipv6Addr net.IP
132 ServiceLock sync.RWMutex `json:"-"`
133 UsMeterID uint32
134 DsMeterID uint32
135 AggDsMeterID uint32
136 UpdateInProgress bool
137 DeleteInProgress bool
138 DeactivateInProgress bool
139 ForceDelete bool
vinokuma926cb3e2023-03-29 11:41:06 +0530140 // Multiservice-Fix
Naveen Sampath04696f72022-06-13 15:19:14 +0530141 UsHSIAFlowsApplied bool
142 DsHSIAFlowsApplied bool
143 UsDhcpFlowsApplied bool
144 DsDhcpFlowsApplied bool
145 IgmpFlowsApplied bool
146 Icmpv6FlowsApplied bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530147}
148
149// VoltService structure
150type VoltService struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530151 VoltServiceOper
152 Version string
vinokuma926cb3e2023-03-29 11:41:06 +0530153 VoltServiceCfg
Naveen Sampath04696f72022-06-13 15:19:14 +0530154}
155
vinokuma926cb3e2023-03-29 11:41:06 +0530156// ServiceTrigger - Service activation trigger
Naveen Sampath04696f72022-06-13 15:19:14 +0530157type ServiceTrigger int
158
159const (
vinokuma926cb3e2023-03-29 11:41:06 +0530160 // NBActivate - Service added due to NB Action
Naveen Sampath04696f72022-06-13 15:19:14 +0530161 NBActivate ServiceTrigger = 0
vinokuma926cb3e2023-03-29 11:41:06 +0530162 // ServiceVlanUpdate - Service added due to Svlan Update
Naveen Sampath04696f72022-06-13 15:19:14 +0530163 ServiceVlanUpdate ServiceTrigger = 1
164)
165
166// AppMutexes structure
167type AppMutexes struct {
168 ServiceDataMutex sync.Mutex `json:"-"`
169 VnetMutex sync.Mutex `json:"-"`
170}
171
vinokuma926cb3e2023-03-29 11:41:06 +0530172// MigrateServiceMetadata - migrate services request metadata
Naveen Sampath04696f72022-06-13 15:19:14 +0530173type MigrateServiceMetadata struct {
174 NewVnetID string
175 RequestID string
176}
177
178// AppMutex variable
179var AppMutex AppMutexes
180
181// NewVoltService for constructor for volt service
182func NewVoltService(cfg *VoltServiceCfg) *VoltService {
183 var vs VoltService
184 vs.VoltServiceCfg = *cfg
185 vs.UsHSIAFlowsApplied = false
186 vs.DsHSIAFlowsApplied = false
187 vs.DeleteInProgress = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +0530188 vs.DeactivateInProgress = false
Naveen Sampath04696f72022-06-13 15:19:14 +0530189 //vs.MacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +0530190 vs.IsOption82Enabled = cfg.IsOption82Enabled
Naveen Sampath04696f72022-06-13 15:19:14 +0530191 vs.MacAddr = cfg.MacAddr
192 vs.Ipv4Addr = net.ParseIP("0.0.0.0")
193 vs.Ipv6Addr = net.ParseIP("::")
194 vs.PendingFlows = make(map[string]bool)
195 vs.AssociatedFlows = make(map[string]bool)
196 return &vs
197}
198
199// WriteToDb commit a service to the DB if service delete is not in-progress
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530200func (vs *VoltService) WriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530201 vs.ServiceLock.RLock()
202 defer vs.ServiceLock.RUnlock()
203
204 if vs.DeleteInProgress {
205 logger.Warnw(ctx, "Skipping Redis Update for Service, Service delete in progress", log.Fields{"Service": vs.Name})
206 return
207 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530208 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530209}
210
vinokuma926cb3e2023-03-29 11:41:06 +0530211// ForceWriteToDb force commit a service to the DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530212func (vs *VoltService) ForceWriteToDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530213 b, err := json.Marshal(vs)
214
215 if err != nil {
216 logger.Errorw(ctx, "Json Marshal Failed for Service", log.Fields{"Service": vs.Name})
217 return
218 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530219 if err1 := db.PutService(cntx, vs.Name, string(b)); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530220 logger.Errorw(ctx, "DB write oper failed for Service", log.Fields{"Service": vs.Name})
221 }
222}
223
224// isDataRateAttrPresent to check if data attribute is present
225func (vs *VoltService) isDataRateAttrPresent() bool {
226 return vs.DataRateAttr == DSLAttrEnabled
227}
228
229// DelFromDb delete a service from DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530230func (vs *VoltService) DelFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530231 logger.Debugw(ctx, "Deleting Service from DB", log.Fields{"Name": vs.Name})
vinokuma926cb3e2023-03-29 11:41:06 +0530232 // TODO - Need to understand and delete the second call
233 // Calling twice has worked though don't know why
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530234 _ = db.DelService(cntx, vs.Name)
235 _ = db.DelService(cntx, vs.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530236}
237
238// MatchesVlans find the service that matches the VLANs. In this case it is
239// purely based on CVLAN. The CVLAN can sufficiently be used to
240// match a service
241func (vs *VoltService) MatchesVlans(vlans []of.VlanType) bool {
242 if len(vlans) != 1 {
243 return false
244 }
245
246 if vlans[0] == vs.CVlan {
247 return true
248 }
249 return false
250}
251
252// MatchesPbits allows matching a service to a pbit. This is used
253// to search for a service matching the pbits, typically to identify
254// attributes for other flows such as DHCP, IGMP, etc.
255func (vs *VoltService) MatchesPbits(pbits []of.PbitType) bool {
256 for _, pbit := range pbits {
257 for _, pb := range vs.Pbits {
258 if pb == pbit {
259 return true
260 }
261 }
262 }
263 return false
264}
265
266// IsPbitExist allows matching a service to a pbit. This is used
267// to search for a service matching the pbit
268func (vs *VoltService) IsPbitExist(pbit of.PbitType) bool {
269 for _, pb := range vs.Pbits {
270 if pb == pbit {
271 return true
272 }
273 }
274 return false
275}
276
277// AddHsiaFlows - Adds US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530278func (vs *VoltService) AddHsiaFlows(cntx context.Context) {
279 if err := vs.AddUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530280 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
281 vs.triggerServiceFailureInd(statusCode, statusMessage)
282 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530283 if err := vs.AddDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530284 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
285 vs.triggerServiceFailureInd(statusCode, statusMessage)
286 }
287}
288
vinokuma926cb3e2023-03-29 11:41:06 +0530289// DelHsiaFlows - Deletes US & DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530290func (vs *VoltService) DelHsiaFlows(cntx context.Context) {
291 if err := vs.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530292 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
293 vs.triggerServiceFailureInd(statusCode, statusMessage)
294 }
295
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530296 if err := vs.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530297 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
298 vs.triggerServiceFailureInd(statusCode, statusMessage)
299 }
300}
301
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530302func (vs *VoltService) AddMeterToDevice(cntx context.Context) error {
303 if vs.DeleteInProgress || vs.UpdateInProgress {
304 logger.Errorw(ctx, "Ignoring Meter Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
305 }
306 va := GetApplication()
307 logger.Infow(ctx, "Configuring Meters for FTTB", log.Fields{"ServiceName": vs.Name})
308 device, err := va.GetDeviceFromPort(vs.Port)
309 if err != nil {
310 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error()})
311 return errorCodes.ErrDeviceNotFound
312 } else if device.State != controller.DeviceStateUP {
313 logger.Warnw(ctx, "Device state Down. Ignoring Meter Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
314 return nil
315 }
316 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
317 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
318 return nil
319}
320
Naveen Sampath04696f72022-06-13 15:19:14 +0530321// AddUsHsiaFlows - Add US HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530322func (vs *VoltService) AddUsHsiaFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530323 if vs.DeleteInProgress || vs.UpdateInProgress {
324 logger.Errorw(ctx, "Ignoring US HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
325 return nil
326 }
327
328 va := GetApplication()
329 logger.Infow(ctx, "Configuring US HSIA Service Flows", log.Fields{"ServiceName": vs.Name})
330 if !vs.UsHSIAFlowsApplied || vgcRebooted {
331 device, err := va.GetDeviceFromPort(vs.Port)
332 if err != nil {
333 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error()})
334 return errorCodes.ErrDeviceNotFound
335 } else if device.State != controller.DeviceStateUP {
336 logger.Warnw(ctx, "Device state Down. Ignoring US HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
337 return nil
338 }
339
340 vs.Device = device.Name
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530341 /* In case of DPU_MGMT_TRAFFIC the meters will be configured before US flow creation*/
vinokuma926cb3e2023-03-29 11:41:06 +0530342 if vs.ServiceType != DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530343 va.AddMeterToDevice(vs.Port, device.Name, vs.UsMeterID, 0)
344 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
345 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530346 logger.Infow(ctx, "Adding HSIA flows", log.Fields{"Name": vs.Name})
347 pBits := vs.Pbits
348
vinokuma926cb3e2023-03-29 11:41:06 +0530349 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530350 if len(vs.Pbits) == 0 {
351 pBits = append(pBits, PbitMatchNone)
352 }
353 for _, pbits := range pBits {
354 usflows, err := vs.BuildUsHsiaFlows(pbits)
355 if err != nil {
356 logger.Errorw(ctx, "Error Building HSIA US flows", log.Fields{"Reason": err.Error()})
357 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
358 vs.triggerServiceFailureInd(statusCode, statusMessage)
359 continue
360 }
361 usflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530362 if err := vs.AddFlows(cntx, device, usflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530363 logger.Errorw(ctx, "Error adding HSIA US flows", log.Fields{"Reason": err.Error()})
364 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
365 vs.triggerServiceFailureInd(statusCode, statusMessage)
366 }
367 }
368 vs.UsHSIAFlowsApplied = true
369 logger.Infow(ctx, "Pushed US HSIA Service Flows", log.Fields{"ServiceName": vs.Name})
370 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530371 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530372 return nil
373}
374
375// AddDsHsiaFlows - Add DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530376func (vs *VoltService) AddDsHsiaFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530377 if vs.DeleteInProgress {
378 logger.Errorw(ctx, "Ignoring DS HSIA Flow Push, Service deleteion In-Progress", log.Fields{"Device": vs.Device, "Service": vs.Name})
379 return nil
380 }
381
382 va := GetApplication()
383 logger.Infow(ctx, "Configuring DS HSIA Service Flows", log.Fields{"ServiceName": vs.Name})
384 if !vs.DsHSIAFlowsApplied || vgcRebooted {
385 device, err := va.GetDeviceFromPort(vs.Port)
386 if err != nil {
387 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error()})
388 return errorCodes.ErrDeviceNotFound
389 } else if device.State != controller.DeviceStateUP {
390 logger.Warnw(ctx, "Device state Down. Ignoring DS HSIA Flow Push", log.Fields{"Service": vs.Name, "Port": vs.Port})
391 return nil
392 }
393
394 va.AddMeterToDevice(vs.Port, device.Name, vs.DsMeterID, vs.AggDsMeterID)
395 logger.Infow(ctx, "Adding HSIA flows", log.Fields{"Name": vs.Name})
396
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 {
401 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
402 return err
403 }
404 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530405 if err = vs.AddFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530406 logger.Errorw(ctx, "Failed to add HSIA DS flows", log.Fields{"Reason": err})
407 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
408 vs.triggerServiceFailureInd(statusCode, statusMessage)
409 }
410 } else {
411 // if all 8 p-bits are to be remarked to one-pbit, configure all-to-one remarking flow
412 if _, ok := vs.DsRemarkPbitsMap[int(of.PbitMatchAll)]; ok {
413 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(of.PbitMatchAll))
414 if err != nil {
415 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
416 return err
417 }
418 logger.Debug(ctx, "Add-one-match-all-pbit-flow")
419 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530420 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530421 logger.Errorw(ctx, "Failed to add HSIA DS flows", log.Fields{"Reason": err})
422 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
423 vs.triggerServiceFailureInd(statusCode, statusMessage)
424 }
425 } else {
426 for matchPbit := range vs.DsRemarkPbitsMap {
427 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
428 if err != nil {
429 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
430 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
431 vs.triggerServiceFailureInd(statusCode, statusMessage)
432 continue
433 }
434 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530435 if err := vs.AddFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530436 logger.Errorw(ctx, "Failed to Add HSIA DS flows", log.Fields{"Reason": err})
437 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
438 vs.triggerServiceFailureInd(statusCode, statusMessage)
439 }
440 }
441 }
442 }
443 vs.DsHSIAFlowsApplied = true
444 logger.Infow(ctx, "Pushed DS HSIA Service Flows", log.Fields{"ServiceName": vs.Name})
445 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530446 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530447 return nil
448}
449
450// DelUsHsiaFlows - Deletes US HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530451func (vs *VoltService) DelUsHsiaFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530452 logger.Infow(ctx, "Removing US HSIA Services", log.Fields{"Services": vs.Name})
453 if vs.UsHSIAFlowsApplied || vgcRebooted {
454 device, err := GetApplication().GetDeviceFromPort(vs.Port)
455 if err != nil {
456 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error()})
457 return errorCodes.ErrDeviceNotFound
458 }
459
460 logger.Infow(ctx, "Removing HSIA flows", log.Fields{"Name": vs.Name})
461 pBits := vs.Pbits
462
vinokuma926cb3e2023-03-29 11:41:06 +0530463 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530464 if len(vs.Pbits) == 0 {
465 pBits = append(pBits, PbitMatchNone)
466 }
467 for _, pbits := range pBits {
468 usflows, err := vs.BuildUsHsiaFlows(pbits)
469 if err != nil {
470 logger.Errorw(ctx, "Error Building HSIA US flows", log.Fields{"Reason": err.Error()})
471 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
472 vs.triggerServiceFailureInd(statusCode, statusMessage)
473 continue
474 }
475 usflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530476 if err = vs.DelFlows(cntx, device, usflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530477 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
478 vs.triggerServiceFailureInd(statusCode, statusMessage)
479 }
480 }
481 vs.UsHSIAFlowsApplied = false
482 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530483 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530484 return nil
485}
486
487// DelDsHsiaFlows - Deletes DS HSIA Flows for the service
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530488func (vs *VoltService) DelDsHsiaFlows(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530489 logger.Infow(ctx, "Removing DS HSIA Services", log.Fields{"Services": vs.Name})
490 if vs.DsHSIAFlowsApplied || vgcRebooted {
491 device, err := GetApplication().GetDeviceFromPort(vs.Port)
492 if err != nil {
493 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error()})
494 return errorCodes.ErrDeviceNotFound
495 }
496
497 logger.Infow(ctx, "Removing HSIA flows", log.Fields{"Name": vs.Name})
498 var matchPbit int
vinokuma926cb3e2023-03-29 11:41:06 +0530499 // If no pbits configured for service, hence add PbitNone for flows
Naveen Sampath04696f72022-06-13 15:19:14 +0530500 if len(vs.DsRemarkPbitsMap) == 0 {
501 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(PbitMatchNone))
502 if err != nil {
503 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
504 return err
505 }
506 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530507 if err = vs.DelFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530508 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
509 vs.triggerServiceFailureInd(statusCode, statusMessage)
510 }
511 } else if _, ok := vs.DsRemarkPbitsMap[int(PbitMatchAll)]; ok {
512 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(int(PbitMatchAll)))
513 if err != nil {
514 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
515 return err
516 }
517 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530518 if err = vs.DelFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530519 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
520 vs.triggerServiceFailureInd(statusCode, statusMessage)
521 }
522 } else {
523 for matchPbit = range vs.DsRemarkPbitsMap {
524 dsflows, err := vs.BuildDsHsiaFlows(of.PbitType(matchPbit))
525 if err != nil {
526 logger.Errorw(ctx, "Error Building HSIA DS flows", log.Fields{"Reason": err.Error()})
527 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
528 vs.triggerServiceFailureInd(statusCode, statusMessage)
529 continue
530 }
531 dsflows.MigrateCookie = vgcRebooted
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530532 if err = vs.DelFlows(cntx, device, dsflows); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530533 statusCode, statusMessage := infraerrorCodes.GetErrorInfo(err)
534 vs.triggerServiceFailureInd(statusCode, statusMessage)
535 }
536 }
537 }
538 vs.DsHSIAFlowsApplied = false
539 }
vinokuma926cb3e2023-03-29 11:41:06 +0530540 logger.Infow(ctx, "Deleted HSIA DS flows from DB successfully", log.Fields{"ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530541 // Post HSIA configuration success indication on message bus
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530542 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530543 return nil
544}
545
546// BuildDsHsiaFlows build the DS HSIA flows
547// Called for add/delete HSIA flows
548func (vs *VoltService) BuildDsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
549 flow := &of.VoltFlow{}
550 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
551
552 // Get the out and in ports for the flows
553 device, err := GetApplication().GetDeviceFromPort(vs.Port)
554 if err != nil {
555 return nil, errorCodes.ErrDeviceNotFound
556 }
557 inport, _ := GetApplication().GetPortID(device.NniPort)
558 outport, _ := GetApplication().GetPortID(vs.Port)
559 // PortName and PortID to be used for validation of port before flow pushing
560 flow.PortID = outport
561 flow.PortName = vs.Port
562 allowTransparent := 0
563 if vs.AllowTransparent {
564 allowTransparent = 1
565 }
566
567 // initialized actnPbit to 0 for cookie genration backward compatibility.
568 var actnPbit of.PbitType
569 remarkPbit, remarkExists := vs.DsRemarkPbitsMap[int(pbits)]
570
571 generateDSCookie := func(vlan of.VlanType, valToShift uint64) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530572 // | 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 +0530573 cookie := uint64(vlan)<<52 + uint64(actnPbit)<<48 + uint64(outport)<<16 | of.HsiaFlowMask
574 cookie = cookie | of.DsFlowMask
575 cookie = cookie + (valToShift << 4) + uint64(pbits)
576 return cookie
577 }
578
579 l2ProtoValue, err := GetMetadataForL2Protocol(vs.SVlanTpid)
580 if err != nil {
581 logger.Errorw(ctx, "DS HSIA flow push failed: Invalid SvlanTpid", log.Fields{"SvlanTpid": vs.SVlanTpid, "Service": vs.Name})
582 return nil, err
583 }
584
585 // Add Table-0 flow that deals with the outer VLAN in pOLT
586 {
587 subflow1 := of.NewVoltSubFlow()
588 subflow1.SetTableID(0)
589 subflow1.SetGoToTable(1)
590 subflow1.SetInPort(inport)
591
592 if pbits != PbitMatchNone {
593 subflow1.SetMatchPbit(pbits)
594 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530595 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
596 subflow1.SetPcp(of.PbitType(remarkPbit))
597 // match & action pbits are different, set remark-pbit action
598 actnPbit = of.PbitType(remarkPbit)
599 // mask remark p-bit to 4bits
600 actnPbit = actnPbit & 0x0F
601 }
602
603 if err := vs.setDSMatchActionVlanT0(subflow1); err != nil {
604 return nil, err
605 }
Tinoj Joseph1d108322022-07-13 10:07:39 +0530606 logger.Infow(ctx, "HSIA DS flows MAC Learning & MAC", log.Fields{"ML": vs.MacLearning, "Mac": vs.MacAddr})
Naveen Sampath04696f72022-06-13 15:19:14 +0530607 if NonZeroMacAddress(vs.MacAddr) {
608 subflow1.SetMatchDstMac(vs.MacAddr)
609 }
610 subflow1.Priority = of.HsiaFlowPriority
611 subflow1.SetMeterID(vs.DsMeterID)
612
613 /* WriteMetaData 8 Byte(uint64) usage:
614 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
615 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
616 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530617 if vs.ServiceType == FttbSubscriberTraffic {
618 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
619 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530620 subflow1.SetWriteMetadata(metadata)
621
622 /* TableMetaData 8 Byte(uint64) Voltha usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
623 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
624 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
625 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | unitag | unitag | ctag | ctag | */
626
627 //TODO-COMM:
628 /* TableMetaData 8 Byte(uint64) Community usage: (Considering MSB bit as 63rd bit and LSB bit as 0th bit)
629 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
630 | 0000 | 00 | 0 | 0 | 00000000 | 00000000 | 0000 0000 | 00000000 | 00000000 | 00000000 | 00000000|
631 | reserved | svlanTpID | Buff us | AT | schedID | schedID | onteth vlanCtrl | ctag | ctag | ctag | ctag | */
632
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530633 if vs.ServiceType != FttbSubscriberTraffic {
634 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
635 subflow1.SetTableMetadata(metadata)
636 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530637 // TODO - We are using cookie as key and must come up with better cookie
638 // allocation algorithm
639 /**
640 * Cokies may clash when -
641 * on same uni-port we have two sub-service
642 * 1. U=10, C=100, S=310, p-bit=4 - VLAN_Control = OLT_CVLAN_OLT_SVLAN
643 * 2. U=10, C=10, S=320, p-bit=4 - VLAN_control = ONU_CVLAN_ONU_SVLAN
644 * However, this p-bit re-use will not be allowed by sub-mgr.
645 */
646 if vs.VlanControl == OLTCVlanOLTSVlan {
647 /**
648 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
649 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
650 * use old cookie.
651 */
652 subflow1.Cookie = generateDSCookie(vs.UniVlan, 0)
653 if vgcRebooted {
654 subflow1.OldCookie = generateDSCookie(vs.CVlan, 0)
655 }
656 } else {
657 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
658 subflow1.Cookie = generateDSCookie(vs.CVlan, 0)
659 }
660
661 flow.SubFlows[subflow1.Cookie] = subflow1
662 logger.Infow(ctx, "Building downstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie,
663 "subflow": subflow1})
664 }
665
vinokuma926cb3e2023-03-29 11:41:06 +0530666 // Add Table-1 flow that deals with inner VLAN at the ONU
Naveen Sampath04696f72022-06-13 15:19:14 +0530667 {
668 subflow2 := of.NewVoltSubFlow()
669 subflow2.SetTableID(1)
670 subflow2.SetInPort(inport)
671 if NonZeroMacAddress(vs.MacAddr) {
672 subflow2.SetMatchDstMac(vs.MacAddr)
673 }
674
675 if err := vs.setDSMatchActionVlanT1(subflow2); err != nil {
676 return nil, err
677 }
678 if pbits != PbitMatchNone {
679 subflow2.SetMatchPbit(pbits)
680 }
681
682 if remarkExists && (of.PbitType(remarkPbit) != pbits) {
683 subflow2.SetPcp(of.PbitType(remarkPbit))
684 }
685
686 subflow2.SetOutPort(outport)
687 subflow2.SetMeterID(vs.DsMeterID)
688
689 // refer Table-0 flow generation for byte information
690 metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530691 if vs.ServiceType == FttbSubscriberTraffic {
692 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
693 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530694 subflow2.SetWriteMetadata(metadata)
695
696 // Table-1 and inport is NNI: It is a DS flow for ONU, add uniport in metadata to make it unique
697 if util.IsNniPort(inport) {
698 metadata = uint64(outport)
699 } else {
700 // refer Table-0 flow generation for byte information
701 metadata = uint64(l2ProtoValue)<<58 | uint64(allowTransparent)<<56 | uint64(vs.SchedID)<<40 | uint64(vs.ONTEtherTypeClassification)<<36 | uint64(vs.VlanControl)<<32 | uint64(vs.CVlan)
702 }
703 subflow2.SetTableMetadata(metadata)
704 // Setting of Cookie - TODO - Improve the allocation algorithm
705 if vs.VlanControl == OLTCVlanOLTSVlan {
706 /**
707 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
708 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
709 * use old cookie.
710 */
711 subflow2.Cookie = generateDSCookie(vs.UniVlan, 1)
712 if vgcRebooted {
713 subflow2.OldCookie = generateDSCookie(vs.CVlan, 1)
714 }
715 } else {
716 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
717 subflow2.Cookie = generateDSCookie(vs.CVlan, 1)
718 }
719
720 subflow2.Priority = of.HsiaFlowPriority
721 flow.SubFlows[subflow2.Cookie] = subflow2
722 logger.Infow(ctx, "Building downstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie,
723 "subflow": subflow2})
724 }
725
726 return flow, nil
727}
728
729// BuildUsHsiaFlows build the US HSIA flows
730// Called for add/delete HSIA flows
731func (vs *VoltService) BuildUsHsiaFlows(pbits of.PbitType) (*of.VoltFlow, error) {
732 flow := &of.VoltFlow{}
733 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
734
735 // Get the out and in ports for the flows
736 device, err := GetApplication().GetDeviceFromPort(vs.Port)
737 if err != nil {
738 return nil, errorCodes.ErrDeviceNotFound
739 }
740 outport, _ := GetApplication().GetPortID(device.NniPort)
741 inport, _ := GetApplication().GetPortID(vs.Port)
742 // PortName and PortID to be used for validation of port before flow pushing
743 flow.PortID = inport
744 flow.PortName = vs.Port
Naveen Sampath04696f72022-06-13 15:19:14 +0530745
746 // Add Table-0 flow that deals with the inner VLAN in ONU
747 {
748 subflow1 := of.NewVoltSubFlow()
749 subflow1.SetTableID(0)
750 subflow1.SetGoToTable(1)
751 subflow1.SetInPort(inport)
752
vinokuma926cb3e2023-03-29 11:41:06 +0530753 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530754 subflow1.SetMatchPbit(vs.UsPonCTagPriority)
755 subflow1.SetPcp(vs.UsPonSTagPriority)
vinokuma926cb3e2023-03-29 11:41:06 +0530756 } else if vs.ServiceType == DpuAncpTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530757 subflow1.SetPcp(vs.UsPonSTagPriority)
758 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530759 if err := vs.setUSMatchActionVlanT0(subflow1); err != nil {
760 return nil, err
761 }
762 subflow1.SetMeterID(vs.UsMeterID)
763
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530764 /* WriteMetaData 8 Byte(uint64) usage:
765 | Byte8 | Byte7 | Byte6 | Byte5 | Byte4 | Byte3 | Byte2 | Byte1 |
766 | reserved | reserved | TpID | TpID | uinID | uniID | uniID | uniID | */
767 //metadata := uint64(vs.CVlan)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
768 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530769 if vs.ServiceType == FttbSubscriberTraffic {
770 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
771 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530772 subflow1.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530773
Naveen Sampath04696f72022-06-13 15:19:14 +0530774 if vs.VlanControl == OLTCVlanOLTSVlan {
775 /**
776 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
777 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
778 * use old cookie.
779 */
780 subflow1.Cookie = vs.generateUSCookie(vs.UniVlan, 0, inport, pbits)
781 if vgcRebooted {
782 subflow1.OldCookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
783 }
784 } else {
785 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
786 subflow1.Cookie = vs.generateUSCookie(vs.CVlan, 0, inport, pbits)
787 }
788 subflow1.Priority = of.HsiaFlowPriority
789 flow.SubFlows[subflow1.Cookie] = subflow1
790 logger.Infow(ctx, "Building upstream HSIA flow for T0", log.Fields{"cookie": subflow1.Cookie, "subflow": subflow1})
791 }
792
vinokuma926cb3e2023-03-29 11:41:06 +0530793 // Add Table-1 flow that deals with the outer vlan in pOLT
Naveen Sampath04696f72022-06-13 15:19:14 +0530794 {
795 subflow2 := of.NewVoltSubFlow()
796 subflow2.SetTableID(1)
797 subflow2.SetInPort(inport)
798
Naveen Sampath04696f72022-06-13 15:19:14 +0530799 if err := vs.setUSMatchActionVlanT1(subflow2); err != nil {
800 return nil, err
801 }
vinokuma926cb3e2023-03-29 11:41:06 +0530802 if vs.ServiceType == DpuMgmtTraffic {
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530803 subflow2.SetMatchSrcMac(vs.MacAddr)
804 }
Naveen Sampath04696f72022-06-13 15:19:14 +0530805 subflow2.SetInPort(inport)
806 subflow2.SetOutPort(outport)
807 subflow2.SetMeterID(vs.UsMeterID)
808
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530809 // refer Table-0 flow generation for byte information
810 metadata := uint64(vs.TechProfileID)<<32 + uint64(outport)
Sridhar Ravindrab8374ae2023-04-14 15:49:25 +0530811 if vs.ServiceType == FttbSubscriberTraffic {
812 metadata = uint64(of.VlanAny)<<48 + uint64(vs.TechProfileID)<<32 + uint64(outport)
813 }
Tinoj Joseph50d722c2022-12-06 22:53:22 +0530814 subflow2.SetWriteMetadata(metadata)
Naveen Sampath04696f72022-06-13 15:19:14 +0530815
Naveen Sampath04696f72022-06-13 15:19:14 +0530816 if vs.VlanControl == OLTCVlanOLTSVlan {
817 /**
818 * The new cookie generation is only for OLT_CVLAN_OLT_SVLAN case (TEF residential case) within a UNI.
819 * After vgc upgrade, if we have to deactivate an already existing TEF residential service, then we have to
820 * use old cookie.
821 */
822 subflow2.Cookie = vs.generateUSCookie(vs.UniVlan, 1, inport, pbits)
823 if vgcRebooted {
824 subflow2.OldCookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
825 }
826 } else {
827 // In case of Olt_Svlan , CVLAN=UNIVLAN so cookie can be constructed with CVLAN as well
828 subflow2.Cookie = vs.generateUSCookie(vs.CVlan, 1, inport, pbits)
829 }
830 subflow2.Priority = of.HsiaFlowPriority
831
832 flow.SubFlows[subflow2.Cookie] = subflow2
833 logger.Infow(ctx, "Building upstream HSIA flow for T1", log.Fields{"cookie": subflow2.Cookie, "subflow": subflow2})
834 }
835
836 return flow, nil
837}
838
839func (vs *VoltService) generateUSCookie(vlan of.VlanType, valToShift uint64, inport uint32, pbits of.PbitType) uint64 {
vinokuma926cb3e2023-03-29 11:41:06 +0530840 // | 12-bit cvlan/UniVlan | 4 bits empty | <32-bits uniport>| 16-bits HSIA mask OR flow mask OR pbit |
Naveen Sampath04696f72022-06-13 15:19:14 +0530841 cookie := uint64(vlan)<<52 + uint64(inport)<<16 | of.HsiaFlowMask
842 cookie = cookie | of.UsFlowMask
843 cookie = cookie + (valToShift << 4) + uint64(pbits)
844 return cookie
845}
846
847// setUSMatchActionVlanT1 - Sets the Match & Action w.r.t Vlans for US Table-1
848// based on different Vlan Controls
849func (vs *VoltService) setUSMatchActionVlanT1(flow *of.VoltSubFlow) error {
850 switch vs.VlanControl {
851 case None:
852 flow.SetMatchVlan(vs.SVlan)
853 case ONUCVlanOLTSVlan:
854 flow.SetMatchVlan(vs.CVlan)
855 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
856 case OLTCVlanOLTSVlan:
857 flow.SetMatchVlan(vs.UniVlan)
858 flow.SetSetVlan(vs.CVlan)
859 flow.SetPushVlan(vs.SVlan, vs.SVlanTpid)
860 case ONUCVlan:
861 flow.SetMatchVlan(vs.SVlan)
862 case OLTSVlan:
863 if vs.UniVlan != of.VlanAny && vs.UniVlan != of.VlanNone {
864 flow.SetMatchVlan(vs.UniVlan)
865 flow.SetSetVlan(vs.SVlan)
866 } else if vs.UniVlan != of.VlanNone {
867 flow.SetMatchVlan(vs.UniVlan)
868 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
869 } else {
870 flow.SetPushVlan(vs.SVlan, layers.EthernetTypeDot1Q)
871 }
872 default:
873 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vs.VlanControl})
874 return errorCodes.ErrInvalidParamInRequest
875 }
876 return nil
877}
878
879// setDSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for DS Table-0
880// based on different Vlan Controls
881func (vs *VoltService) setDSMatchActionVlanT0(flow *of.VoltSubFlow) error {
882 switch vs.VlanControl {
883 case None:
884 flow.SetMatchVlan(vs.SVlan)
885 case ONUCVlanOLTSVlan:
886 flow.SetMatchVlan(vs.SVlan)
887 flow.SetPopVlan()
888 case OLTCVlanOLTSVlan:
889 flow.SetMatchVlan(vs.SVlan)
890 flow.SetPopVlan()
891 flow.SetSetVlan(vs.UniVlan)
892 case ONUCVlan:
893 flow.SetMatchVlan(vs.SVlan)
894 case OLTSVlan:
895 flow.SetMatchVlan(vs.SVlan)
896 if vs.UniVlan != of.VlanNone && vs.UniVlan != of.VlanAny {
897 flow.SetSetVlan(vs.UniVlan)
898 } else {
899 flow.SetPopVlan()
900 }
901 default:
902 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vs.VlanControl})
903 return errorCodes.ErrInvalidParamInRequest
904 }
905 return nil
906}
907
908// setUSMatchActionVlanT0 - Sets the Match & Action w.r.t Vlans for US Table-0
909// based on different Vlan Controls
910func (vs *VoltService) setUSMatchActionVlanT0(flow *of.VoltSubFlow) error {
911 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:
933 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vs.VlanControl})
934 return errorCodes.ErrInvalidParamInRequest
935 }
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 {
942 switch vs.VlanControl {
943 case None:
944 flow.SetMatchVlan(vs.SVlan)
945 case ONUCVlanOLTSVlan:
946 flow.SetMatchVlan(vs.CVlan)
947 if vs.UniVlan != of.VlanNone {
948 flow.SetSetVlan(vs.UniVlan)
949 } else {
950 flow.SetPopVlan()
951 }
952 case OLTCVlanOLTSVlan:
953 flow.SetMatchVlan(vs.UniVlan)
954 case ONUCVlan:
955 flow.SetMatchVlan(vs.SVlan)
956 if vs.UniVlan != of.VlanNone {
957 flow.SetSetVlan(vs.UniVlan)
958 } else {
959 flow.SetPopVlan()
960 }
961 case OLTSVlan:
962 flow.SetMatchVlan(vs.UniVlan)
963 default:
964 logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vs.VlanControl})
965 return errorCodes.ErrInvalidParamInRequest
966 }
967 return nil
968}
969
970// SvcUpInd for service up indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530971func (vs *VoltService) SvcUpInd(cntx context.Context) {
972 vs.AddHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530973}
974
975// SvcDownInd for service down indication
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530976func (vs *VoltService) SvcDownInd(cntx context.Context) {
977 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530978}
979
980// SetIpv4Addr to set ipv4 address
981func (vs *VoltService) SetIpv4Addr(addr net.IP) {
982 vs.Ipv4Addr = addr
983}
984
985// SetIpv6Addr to set ipv6 address
986func (vs *VoltService) SetIpv6Addr(addr net.IP) {
987 vs.Ipv6Addr = addr
988}
989
990// SetMacAddr to set mac address
991func (vs *VoltService) SetMacAddr(addr net.HardwareAddr) {
992 vs.MacAddr = addr
993}
994
995// ----------------------------------------------
996// VOLT Application - Related to services
997// ---------------------------------------------
998// ---------------------------------------------------------------
999// Service CRUD functions. These are exposed to the overall binary
1000// to be invoked from the point where the CRUD operations are received
1001// from the external entities
1002
1003// AddService : A service in the context of VOLT is a subscriber or service of a
1004// subscriber which is uniquely identified by a combination of MAC
1005// address, VLAN tags, 802.1p bits. However, in the context of the
1006// current implementation, a service is an entity that is identified by a
1007// unique L2 (MAC address + VLANs) or unique L3 (VLANs + IP address)
1008// FUNC: Add Service
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301009func (va *VoltApplication) AddService(cntx context.Context, cfg VoltServiceCfg, oper *VoltServiceOper) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301010 var mmUs, mmDs *VoltMeter
1011 var err error
1012
vinokuma926cb3e2023-03-29 11:41:06 +05301013 // Take the Device lock only in case of NB add request.
Naveen Sampath04696f72022-06-13 15:19:14 +05301014 // Allow internal adds since internal add happen only under
1015 // 1. Restore Service from DB
1016 // 2. Service Migration
1017 if oper == nil {
1018 if svc := va.GetService(cfg.Name); svc != nil {
1019 logger.Warnw(ctx, "Service Already Exists. Ignoring Add Service Request", log.Fields{"Name": cfg.Name})
1020 return errors.New("Service Already Exists")
1021 }
1022 }
1023
1024 logger.Infow(ctx, "Service to be configured", log.Fields{"Cfg": cfg})
1025 // Service doesn't exist. So create it and add to the port
1026 vs := NewVoltService(&cfg)
1027 if oper != nil {
1028 vs.UsHSIAFlowsApplied = oper.UsHSIAFlowsApplied
1029 vs.DsHSIAFlowsApplied = oper.DsHSIAFlowsApplied
1030 vs.Ipv4Addr = oper.Ipv4Addr
1031 vs.Ipv6Addr = oper.Ipv6Addr
1032 vs.MacLearning = cfg.MacLearning
1033 vs.PendingFlows = oper.PendingFlows
1034 vs.AssociatedFlows = oper.AssociatedFlows
1035 vs.DeleteInProgress = oper.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301036 vs.DeactivateInProgress = oper.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301037 vs.BwAvailInfo = oper.BwAvailInfo
1038 vs.Device = oper.Device
1039 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301040 // Sorting Pbit from highest
Naveen Sampath04696f72022-06-13 15:19:14 +05301041 sort.Slice(vs.Pbits, func(i, j int) bool {
1042 return vs.Pbits[i] > vs.Pbits[j]
1043 })
1044 logger.Infow(ctx, "Sorted Pbits", log.Fields{"Pbits": vs.Pbits})
1045 }
1046 logger.Infow(ctx, "VolthService...", log.Fields{"vs": vs.Name})
1047
1048 // The bandwidth and shaper profile combined into meter
1049 if mmDs, err = va.GetMeter(cfg.DsMeterProfile); err == nil {
1050 vs.DsMeterID = mmDs.ID
1051 } else {
1052 return errors.New("DownStream meter profile not found")
1053 }
1054
1055 // The aggregated downstream meter profile
1056 // if mmAg, err = va.GetMeter(cfg.AggDsMeterProfile); err == nil {
1057 // vs.AggDsMeterID = mmAg.ID
1058 // } else {
1059 // return errors.New("Aggregated meter profile not found")
1060 // }
1061
1062 // if cfg.AggDsMeterProfile == cfg.UsMeterProfile {
1063 // vs.UsMeterID = mmAg.ID
1064 // } else {
1065 // The bandwidth and shaper profile combined into meter
1066 if mmUs, err = va.GetMeter(cfg.UsMeterProfile); err == nil {
1067 vs.UsMeterID = mmUs.ID
1068 } else {
1069 return errors.New("Upstream meter profile not found")
1070 }
1071 //}
1072
1073 AppMutex.ServiceDataMutex.Lock()
1074 defer AppMutex.ServiceDataMutex.Unlock()
1075
1076 // Add the service to the VNET
1077 vnet := va.GetVnet(cfg.SVlan, cfg.CVlan, cfg.UniVlan)
1078 if vnet != nil {
1079 if vpv := va.GetVnetByPort(vs.Port, cfg.SVlan, cfg.CVlan, cfg.UniVlan); vpv != nil {
1080 vpv.VpvLock.Lock()
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301081 vpv.AddSvc(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301082 vpv.VpvLock.Unlock()
1083 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301084 va.AddVnetToPort(cntx, vs.Port, vnet, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301085 }
1086 } else {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301087 logger.Errorw(ctx, "VNET-does-not-exist-for-service", log.Fields{"ServiceName": cfg.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301088 return errors.New("VNET doesn't exist")
1089 }
1090
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301091 // If the device is already discovered, update the device name in service
1092 d, err := va.GetDeviceFromPort(vs.Port)
1093 if err == nil {
1094 vs.Device = d.Name
1095 }
1096
Naveen Sampath04696f72022-06-13 15:19:14 +05301097 vs.Version = database.PresentVersionMap[database.ServicePath]
1098 // Add the service to the volt application
1099 va.ServiceByName.Store(vs.Name, vs)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301100 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301101
1102 if nil == oper {
Naveen Sampath04696f72022-06-13 15:19:14 +05301103 if !vs.UsHSIAFlowsApplied {
1104 vs.triggerServiceInProgressInd()
1105 }
1106
vinokuma926cb3e2023-03-29 11:41:06 +05301107 // Update meter profiles service count if service is being added from northbound
Naveen Sampath04696f72022-06-13 15:19:14 +05301108 mmDs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301109 va.UpdateMeterProf(cntx, *mmDs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301110 if mmUs != nil {
1111 mmUs.AssociatedServices++
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301112 va.UpdateMeterProf(cntx, *mmUs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301113 }
1114 //mmAg.AssociatedServices++
1115 //va.UpdateMeterProf(*mmAg)
vinokuma926cb3e2023-03-29 11:41:06 +05301116 logger.Debugw(ctx, "northbound-service-add-successful", log.Fields{"ServiceName": vs.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +05301117 }
1118
1119 logger.Warnw(ctx, "Added Service to DB", log.Fields{"Name": vs.Name, "Port": (vs.Port), "ML": vs.MacLearning})
1120 return nil
1121}
1122
vinokuma926cb3e2023-03-29 11:41:06 +05301123// DelServiceWithPrefix - Deletes service with the provided prefix.
Naveen Sampath04696f72022-06-13 15:19:14 +05301124// Added for DT/TT usecase with sadis replica interface
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301125func (va *VoltApplication) DelServiceWithPrefix(cntx context.Context, prefix string) error {
1126 var isServiceExist bool
Naveen Sampath04696f72022-06-13 15:19:14 +05301127 va.ServiceByName.Range(func(key, value interface{}) bool {
1128 srvName := key.(string)
1129 vs := value.(*VoltService)
1130 if strings.Contains(srvName, prefix) {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301131 isServiceExist = true
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301132 va.DelService(cntx, srvName, true, nil, false)
Naveen Sampath04696f72022-06-13 15:19:14 +05301133
1134 vnetName := strconv.FormatUint(uint64(vs.SVlan), 10) + "-"
1135 vnetName = vnetName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1136 vnetName = vnetName + strconv.FormatUint(uint64(vs.UniVlan), 10)
1137
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301138 if err := va.DelVnet(cntx, vnetName, ""); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301139 logger.Warnw(ctx, "Delete Vnet Failed", log.Fields{"Name": vnetName, "Error": err})
1140 }
1141 }
1142 return true
1143 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05301144
1145 if !isServiceExist {
1146 return errorCodes.ErrServiceNotFound
1147 }
1148 return nil
Naveen Sampath04696f72022-06-13 15:19:14 +05301149}
1150
1151// DelService delete a service form the application
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301152func (va *VoltApplication) DelService(cntx context.Context, name string, forceDelete bool, newSvc *VoltServiceCfg, serviceMigration bool) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301153 AppMutex.ServiceDataMutex.Lock()
1154 defer AppMutex.ServiceDataMutex.Unlock()
1155
1156 logger.Warnw(ctx, "Delete Service Request", log.Fields{"Service": name, "ForceDelete": forceDelete, "serviceMigration": serviceMigration})
1157 var noFlowsPresent bool
1158
1159 vsIntf, ok := va.ServiceByName.Load(name)
1160 if !ok {
1161 logger.Warnw(ctx, "Service doesn't exist", log.Fields{"ServiceName": name})
1162 return
1163 }
1164 vs := vsIntf.(*VoltService)
1165 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1166 if vpv == nil {
1167 logger.Errorw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name})
1168 return
1169 }
1170
vinokuma926cb3e2023-03-29 11:41:06 +05301171 // Set this to avoid race-condition during flow result processing
Naveen Sampath04696f72022-06-13 15:19:14 +05301172 vs.DeleteInProgress = true
1173 vs.ForceDelete = forceDelete
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301174 vs.ForceWriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301175
1176 if len(vs.AssociatedFlows) == 0 {
1177 noFlowsPresent = true
1178 }
1179 vpv.VpvLock.Lock()
1180 defer vpv.VpvLock.Unlock()
1181
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301182 vs.DelHsiaFlows(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301183
1184 if vpv.IgmpEnabled {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301185 va.ReceiverDownInd(cntx, vpv.Device, vpv.Port)
Naveen Sampath04696f72022-06-13 15:19:14 +05301186 }
1187 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 +05301188 vpv.DelService(cntx, vs)
Naveen Sampath04696f72022-06-13 15:19:14 +05301189 if vpv.servicesCount.Load() == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301190 va.DelVnetFromPort(cntx, vs.Port, vpv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301191 }
1192
1193 // Delete the service immediately in case of Force Delete
1194 // This will be enabled when profile reconciliation happens after restore
1195 // of backedup data
1196 if vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301197 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301198 GetApplication().ServiceByName.Delete(vs.Name)
1199 logger.Warnw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
1200 }
1201
Naveen Sampath04696f72022-06-13 15:19:14 +05301202 if nil != newSvc {
1203 logger.Infow(ctx, "Old Service meter profiles", log.Fields{"AGG": vs.AggDsMeterProfile, "DS": vs.DsMeterProfile, "US": vs.UsMeterProfile})
1204 logger.Infow(ctx, "New Service meter profiles", log.Fields{"AGG": newSvc.AggDsMeterProfile, "DS": newSvc.DsMeterProfile, "US": newSvc.UsMeterProfile})
1205 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301206
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301207 logger.Infow(ctx, "About to mark meter for deletion\n", log.Fields{"serviceName": vs.Name})
1208
1209 if aggMeter, ok := va.MeterMgr.GetMeterByID(vs.AggDsMeterID); ok {
1210 if nil == newSvc || (nil != newSvc && aggMeter.Name != newSvc.AggDsMeterProfile) {
vinokuma926cb3e2023-03-29 11:41:06 +05301211 if aggMeter.AssociatedServices > 0 {
1212 aggMeter.AssociatedServices--
1213 logger.Infow(ctx, "Agg Meter associated services updated\n", log.Fields{"MeterID": aggMeter})
1214 va.UpdateMeterProf(cntx, *aggMeter)
1215 }
Sridhar Ravindra2d2ef4e2023-02-08 16:43:38 +05301216 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301217 }
1218 if dsMeter, ok := va.MeterMgr.GetMeterByID(vs.DsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301219 if nil == newSvc || (nil != newSvc && dsMeter.Name != newSvc.DsMeterProfile) {
1220 if dsMeter.AssociatedServices > 0 {
1221 dsMeter.AssociatedServices--
1222 logger.Infow(ctx, "DS Meter associated services updated\n", log.Fields{"MeterID": dsMeter})
1223 va.UpdateMeterProf(cntx, *dsMeter)
1224 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301225 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301226 }
1227 if vs.AggDsMeterID != vs.UsMeterID {
1228 if usMeter, ok := va.MeterMgr.GetMeterByID(vs.UsMeterID); ok {
vinokuma926cb3e2023-03-29 11:41:06 +05301229 if nil == newSvc || (nil != newSvc && usMeter.Name != newSvc.UsMeterProfile) {
1230 if usMeter.AssociatedServices > 0 {
1231 usMeter.AssociatedServices--
1232 logger.Infow(ctx, "US Meter associated services updated\n", log.Fields{"MeterID": usMeter})
1233 va.UpdateMeterProf(cntx, *usMeter)
1234 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301235 }
1236 }
1237 }
1238
1239 if noFlowsPresent || vs.ForceDelete {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301240 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301241 }
1242
vinokuma926cb3e2023-03-29 11:41:06 +05301243 // Delete the per service counter too
Naveen Sampath04696f72022-06-13 15:19:14 +05301244 va.ServiceCounters.Delete(name)
1245 if vs.IgmpEnabled && vs.EnableMulticastKPI {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301246 _ = db.DelAllServiceChannelCounter(cntx, name)
Naveen Sampath04696f72022-06-13 15:19:14 +05301247 }
1248}
1249
vinokuma926cb3e2023-03-29 11:41:06 +05301250// AddFlows - Adds the flow to the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301251// Triggers flow addition after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301252func (vs *VoltService) AddFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301253 // Using locks instead of concurrent map for PendingFlows to avoid
1254 // race condition during flow response indication processing
1255 vs.ServiceLock.Lock()
1256 defer vs.ServiceLock.Unlock()
1257
1258 for cookie := range flow.SubFlows {
1259 cookie := strconv.FormatUint(cookie, 10)
1260 fe := &FlowEvent{
1261 eType: EventTypeServiceFlowAdded,
1262 device: device.Name,
1263 cookie: cookie,
1264 eventData: vs,
1265 }
1266 device.RegisterFlowAddEvent(cookie, fe)
1267 vs.PendingFlows[cookie] = true
1268 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301269 return cntlr.GetController().AddFlows(cntx, vs.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301270}
1271
vinokuma926cb3e2023-03-29 11:41:06 +05301272// FlowInstallSuccess - Called when corresponding service flow installation is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301273// If no more pending flows, HSIA indication wil be triggered
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301274func (vs *VoltService) FlowInstallSuccess(cntx context.Context, cookie string, bwAvailInfo of.BwAvailDetails) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301275 if vs.DeleteInProgress {
1276 logger.Warnw(ctx, "Skipping Flow Add Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1277 return
1278 }
1279 vs.ServiceLock.Lock()
1280
1281 if _, ok := vs.PendingFlows[cookie]; !ok {
1282 logger.Errorw(ctx, "Flow Add Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1283 vs.ServiceLock.Unlock()
1284 return
1285 }
1286
1287 delete(vs.PendingFlows, cookie)
1288 vs.AssociatedFlows[cookie] = true
1289 vs.ServiceLock.Unlock()
1290 var prevBwAvail, presentBwAvail string
1291 if bwAvailInfo.PrevBw != "" && bwAvailInfo.PresentBw != "" {
1292 prevBwAvail = bwAvailInfo.PrevBw
1293 presentBwAvail = bwAvailInfo.PresentBw
1294 vs.BwAvailInfo = prevBwAvail + "," + presentBwAvail
Tinoj Joseph1d108322022-07-13 10:07:39 +05301295 logger.Debugw(ctx, "Bandwidth-value-formed", log.Fields{"BwAvailInfo": vs.BwAvailInfo})
Naveen Sampath04696f72022-06-13 15:19:14 +05301296 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301297 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301298
1299 if len(vs.PendingFlows) == 0 && vs.DsHSIAFlowsApplied {
Naveen Sampath04696f72022-06-13 15:19:14 +05301300 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1301 if err != nil {
1302 logger.Errorw(ctx, "Error Getting Device. Dropping HSIA Success indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1303 return
1304 } else if device.State != controller.DeviceStateUP {
1305 logger.Warnw(ctx, "Device state Down. Dropping HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1306 return
1307 }
1308
1309 if vs.Trigger == ServiceVlanUpdate {
1310 vs.Trigger = NBActivate
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301311 defer vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301312 }
1313 logger.Infow(ctx, "All Flows installed for Service", log.Fields{"Service": vs.Name})
1314 return
1315 }
1316 logger.Infow(ctx, "Processed Service Flow Add Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1317}
1318
vinokuma926cb3e2023-03-29 11:41:06 +05301319// FlowInstallFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301320// Trigger service failure indication to NB
1321func (vs *VoltService) FlowInstallFailure(cookie string, errorCode uint32, errReason string) {
1322 vs.ServiceLock.RLock()
1323
1324 if _, ok := vs.PendingFlows[cookie]; !ok {
1325 logger.Errorw(ctx, "Flow Add Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1326 vs.ServiceLock.RUnlock()
1327 return
1328 }
1329 vs.ServiceLock.RUnlock()
1330 logger.Errorw(ctx, "HSIA Flow Add Failure Notification", log.Fields{"uniPort": vs.Port, "Cookie": cookie, "Service": vs.Name, "ErrorCode": errorCode, "ErrorReason": errReason})
1331 vs.triggerServiceFailureInd(errorCode, errReason)
1332}
1333
vinokuma926cb3e2023-03-29 11:41:06 +05301334// DelFlows - Deletes the flow from the service
Naveen Sampath04696f72022-06-13 15:19:14 +05301335// Triggers flow deletion after registering for flow indication event
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301336func (vs *VoltService) DelFlows(cntx context.Context, device *VoltDevice, flow *of.VoltFlow) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301337 if !vs.ForceDelete {
1338 // Using locks instead of concurrent map for AssociatedFlows to avoid
1339 // race condition during flow response indication processing
1340 vs.ServiceLock.Lock()
1341 defer vs.ServiceLock.Unlock()
1342
1343 for cookie := range flow.SubFlows {
1344 cookie := strconv.FormatUint(cookie, 10)
1345 fe := &FlowEvent{
1346 eType: EventTypeServiceFlowRemoved,
1347 cookie: cookie,
1348 eventData: vs,
1349 }
1350 device.RegisterFlowDelEvent(cookie, fe)
1351 }
1352 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301353 return cntlr.GetController().DelFlows(cntx, vs.Port, device.Name, flow)
Naveen Sampath04696f72022-06-13 15:19:14 +05301354}
1355
vinokuma926cb3e2023-03-29 11:41:06 +05301356// CheckAndDeleteService - remove service from DB is there are no pending flows to be removed
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301357func (vs *VoltService) CheckAndDeleteService(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301358 if vs.DeleteInProgress && len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301359 vs.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301360 GetApplication().ServiceByName.Delete(vs.Name)
1361 logger.Warnw(ctx, "Deleted service from DB/Cache successfully", log.Fields{"serviceName": vs.Name})
1362 }
1363}
1364
vinokuma926cb3e2023-03-29 11:41:06 +05301365// FlowRemoveSuccess - Called when corresponding service flow removal is success
Naveen Sampath04696f72022-06-13 15:19:14 +05301366// If no more associated flows, DelHSIA indication wil be triggered
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301367func (vs *VoltService) FlowRemoveSuccess(cntx context.Context, cookie string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301368 // if vs.DeleteInProgress {
1369 // logger.Warnw(ctx, "Skipping Flow Remove Success Notification. Service deletion in-progress", log.Fields{"Cookie": cookie, "Service": vs.Name})
1370 // return
1371 // }
1372 vs.ServiceLock.Lock()
1373 logger.Infow(ctx, "Processing Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1374
1375 if _, ok := vs.AssociatedFlows[cookie]; ok {
1376 delete(vs.AssociatedFlows, cookie)
1377 } else if _, ok := vs.PendingFlows[cookie]; ok {
1378 logger.Errorw(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})
1379 } else {
1380 logger.Errorw(ctx, "Service Flow Remove Success for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie, "AssociatedFlows": vs.AssociatedFlows, "PendingFlows": vs.PendingFlows})
1381 }
1382
1383 vs.ServiceLock.Unlock()
1384
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301385 vs.WriteToDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301386
1387 if len(vs.AssociatedFlows) == 0 && !vs.DsHSIAFlowsApplied {
Naveen Sampath04696f72022-06-13 15:19:14 +05301388 device := GetApplication().GetDevice(vs.Device)
1389 if device == nil {
1390 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1391 return
1392 } else if device.State != controller.DeviceStateUP {
1393 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Success indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1394 return
1395 }
1396
1397 if vs.UpdateInProgress {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301398 vs.updateVnetProfile(cntx, vs.Device)
vinokuma926cb3e2023-03-29 11:41:06 +05301399 // Not sending DEL_HSIA Indication since it wil be generated internally by SubMgr
Naveen Sampath04696f72022-06-13 15:19:14 +05301400 return
1401 }
1402 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 +05301403 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301404
1405 return
1406 }
1407 logger.Infow(ctx, "Processed Service Flow Remove Success Indication", log.Fields{"Cookie": cookie, "Service": vs.Name, "Associated Flows": vs.AssociatedFlows, "DsFlowsApplied": vs.DsHSIAFlowsApplied})
1408}
1409
vinokuma926cb3e2023-03-29 11:41:06 +05301410// FlowRemoveFailure - Called when corresponding service flow installation is failed
Naveen Sampath04696f72022-06-13 15:19:14 +05301411// Trigger service failure indication to NB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301412func (vs *VoltService) FlowRemoveFailure(cntx context.Context, cookie string, errorCode uint32, errReason string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301413 vs.ServiceLock.RLock()
1414
1415 if _, ok := vs.AssociatedFlows[cookie]; !ok {
1416 logger.Errorw(ctx, "Flow Failure for unknown Cookie", log.Fields{"Service": vs.Name, "Cookie": cookie})
1417 vs.ServiceLock.RUnlock()
1418 return
1419 }
1420 if vs.DeleteInProgress {
1421 delete(vs.AssociatedFlows, cookie)
1422 }
1423 vs.ServiceLock.RUnlock()
1424 logger.Errorw(ctx, "Service Flow Remove Failure Notification", log.Fields{"uniPort": vs.Port, "Cookie": cookie, "Service": vs.Name, "ErrorCode": errorCode, "ErrorReason": errReason})
1425
1426 vs.triggerServiceFailureInd(errorCode, errReason)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301427 vs.CheckAndDeleteService(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301428}
1429
1430func (vs *VoltService) triggerServiceFailureInd(errorCode uint32, errReason string) {
1431 device, err := GetApplication().GetDeviceFromPort(vs.Port)
1432 if err != nil {
1433 logger.Errorw(ctx, "Error Getting Device. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Reason": err.Error(), "Service": vs.Name, "Port": vs.Port})
1434 return
1435 } else if device.State != controller.DeviceStateUP {
1436 logger.Warnw(ctx, "Device state Down. Dropping DEL_HSIA Failure indication to NB", log.Fields{"Service": vs.Name, "Port": vs.Port})
1437 return
1438 }
1439}
1440
1441// RestoreSvcsFromDb read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301442func (va *VoltApplication) RestoreSvcsFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301443 // VNETS must be learnt first
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301444 vss, _ := db.GetServices(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301445 for _, vs := range vss {
1446 b, ok := vs.Value.([]byte)
1447 if !ok {
1448 logger.Warn(ctx, "The value type is not []byte")
1449 continue
1450 }
1451 var vvs VoltService
1452 err := json.Unmarshal(b, &vvs)
1453 if err != nil {
1454 logger.Warn(ctx, "Unmarshal of VNET failed")
1455 continue
1456 }
1457 logger.Debugw(ctx, "Retrieved Service", log.Fields{"Service": vvs.VoltServiceCfg})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301458 if err := va.AddService(cntx, vvs.VoltServiceCfg, &vvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301459 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": vvs.Name, "Error": err})
1460 }
1461
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301462 if vvs.VoltServiceOper.DeactivateInProgress {
1463 va.ServicesToDeactivate[vvs.VoltServiceCfg.Name] = true
1464 logger.Warnw(ctx, "Service (restored) to be deactivated", log.Fields{"Service": vvs.Name})
1465 }
1466
Naveen Sampath04696f72022-06-13 15:19:14 +05301467 if vvs.VoltServiceOper.DeleteInProgress {
1468 va.ServicesToDelete[vvs.VoltServiceCfg.Name] = true
1469 logger.Warnw(ctx, "Service (restored) to be deleted", log.Fields{"Service": vvs.Name})
1470 }
1471 }
1472}
1473
1474// GetService to get service
1475func (va *VoltApplication) GetService(name string) *VoltService {
1476 if vs, ok := va.ServiceByName.Load(name); ok {
1477 return vs.(*VoltService)
1478 }
1479 return nil
1480}
1481
1482// GetCircuitID to get circuit id
1483func (vs *VoltService) GetCircuitID() []byte {
1484 return []byte(vs.CircuitID)
1485}
1486
1487// GetRemoteID to get remote id
1488func (vs *VoltService) GetRemoteID() []byte {
1489 return []byte(vs.RemoteID)
1490}
1491
1492// IPAssigned to check if ip is assigned
1493func (vs *VoltService) IPAssigned() bool {
1494 if vs.Ipv4Addr != nil && !vs.Ipv4Addr.Equal(net.ParseIP("0.0.0.0")) {
1495 return true
1496 } else if vs.Ipv6Addr != nil && !vs.Ipv6Addr.Equal(net.ParseIP("0:0:0:0:0:0:0:0")) {
1497 return true
1498 }
1499 return false
1500}
1501
1502// GetServiceNameFromCookie to get service name from cookie
1503func (va *VoltApplication) GetServiceNameFromCookie(cookie uint64, portName string, pbit uint8, device string, tableMetadata uint64) *VoltService {
Naveen Sampath04696f72022-06-13 15:19:14 +05301504 var vlan uint64
1505 vlanControl := (tableMetadata >> 32) & 0xF
1506
1507 if vlanControl == uint64(OLTCVlanOLTSVlan) {
1508 // Fetching UniVlan for vlanControl OLTCVLANOLTSVLAN
1509 vlan = (tableMetadata >> 16) & 0xFFFF
1510 } else {
vinokuma926cb3e2023-03-29 11:41:06 +05301511 // Fetching CVlan for other vlanControl
Naveen Sampath04696f72022-06-13 15:19:14 +05301512 vlan = cookie >> 52
1513 }
1514 logger.Infow(ctx, "Configured Params", log.Fields{"VlanControl": vlanControl, "vlan": vlan})
1515 var vlans []of.VlanType
1516 vlans = append(vlans, of.VlanType(vlan))
1517 service := GetApplication().GetServiceFromCvlan(device, portName, vlans, uint8(pbit))
1518 if nil != service {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301519 logger.Infow(ctx, "Service Found for", log.Fields{"serviceName": service.Name, "portName": portName, "ctag": vlan})
Naveen Sampath04696f72022-06-13 15:19:14 +05301520 } else {
1521 logger.Errorw(ctx, "No Service for", log.Fields{"portName": portName, "ctag": vlan, "Pbit": pbit, "device": device, "VlanControl": vlanControl})
1522 }
1523 return service
1524}
1525
vinokuma926cb3e2023-03-29 11:41:06 +05301526// MigrateServicesReqStatus - update vnet request status
Naveen Sampath04696f72022-06-13 15:19:14 +05301527type MigrateServicesReqStatus string
1528
1529const (
vinokuma926cb3e2023-03-29 11:41:06 +05301530 // MigrateSrvsReqInit constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301531 MigrateSrvsReqInit MigrateServicesReqStatus = "Init"
vinokuma926cb3e2023-03-29 11:41:06 +05301532 // MigrateSrvsReqDeactTriggered constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301533 MigrateSrvsReqDeactTriggered MigrateServicesReqStatus = "Profiles Deactivated"
vinokuma926cb3e2023-03-29 11:41:06 +05301534 // MigrateSrvsReqCompleted constant
Naveen Sampath04696f72022-06-13 15:19:14 +05301535 MigrateSrvsReqCompleted MigrateServicesReqStatus = "Update Complete"
1536)
1537
vinokuma926cb3e2023-03-29 11:41:06 +05301538// MigrateServicesRequest - update vnet request params
Naveen Sampath04696f72022-06-13 15:19:14 +05301539type MigrateServicesRequest struct {
1540 ID string
1541 OldVnetID string
1542 NewVnetID string
1543 ServicesList map[string]bool
1544 DeviceID string
1545 Status MigrateServicesReqStatus
1546 MigrateServicesLock sync.RWMutex
1547}
1548
1549func newMigrateServicesRequest(id string, oldVnetID string, newVnetID string, serviceMap map[string]bool, deviceID string) *MigrateServicesRequest {
Naveen Sampath04696f72022-06-13 15:19:14 +05301550 var msr MigrateServicesRequest
1551 msr.OldVnetID = oldVnetID
1552 msr.NewVnetID = newVnetID
1553 msr.ID = id
1554 msr.ServicesList = serviceMap
1555 msr.DeviceID = deviceID
1556 msr.Status = MigrateSrvsReqInit
1557 return &msr
1558}
1559
vinokuma926cb3e2023-03-29 11:41:06 +05301560// GetMsrKey - generates migrate service request key
Naveen Sampath04696f72022-06-13 15:19:14 +05301561func (msr *MigrateServicesRequest) GetMsrKey() string {
1562 return msr.OldVnetID + "-" + msr.ID
1563}
1564
1565// //isRequestComplete - return if all request has been processed and completed
1566// // RequestProcessed indicates that all the profile de-activation has been triggered
1567// // And the associated profiles indicates the profiles awaiting results
1568// func (msr *MigrateServicesRequest) isRequestComplete() bool {
1569// //return edr.RequestProcessed && (len(edr.AssociatedProfiles) == 0)
1570// return (len(edr.AssociatedProfiles) == 0)
1571// }
1572
vinokuma926cb3e2023-03-29 11:41:06 +05301573// WriteToDB - writes the udpate vnet request details ot DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301574func (msr *MigrateServicesRequest) WriteToDB(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301575 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)})
1576 if b, err := json.Marshal(msr); err == nil {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301577 if err = db.PutMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey(), string(b)); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301578 logger.Warnw(ctx, "PutMigrateServicesReq Failed", log.Fields{"OldVnet": msr.OldVnetID, "NewVnet": msr.NewVnetID,
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05301579 "Device": msr.DeviceID, "Error": err})
Naveen Sampath04696f72022-06-13 15:19:14 +05301580 }
1581 }
1582}
1583
vinokuma926cb3e2023-03-29 11:41:06 +05301584// MigrateServices - updated vnet profile for services
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301585func (va *VoltApplication) MigrateServices(cntx context.Context, serialNum string, reqID string, oldVnetID, newVnetID string, serviceList []string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +05301586 logger.Warnw(ctx, "Migrate Serviec Request Received", log.Fields{"SerialNum": serialNum, "RequestID": reqID, "OldVnet": oldVnetID, "NewVnet": newVnetID, "ServiceList": serviceList})
1587 if _, ok := va.VnetsByName.Load(oldVnetID); !ok {
1588 return errors.New("Old Vnet Id not found")
1589 }
1590 if _, ok := va.VnetsByName.Load(newVnetID); !ok {
1591 return errors.New("New Vnet Id not found")
1592 }
1593
Tinoj Joseph50d722c2022-12-06 22:53:22 +05301594 d, _ := va.GetDeviceBySerialNo(serialNum)
Naveen Sampath04696f72022-06-13 15:19:14 +05301595 if d == nil {
1596 logger.Errorw(ctx, "Error Getting Device", log.Fields{"SerialNum": serialNum})
1597 return errorCodes.ErrDeviceNotFound
1598 }
1599
1600 serviceMap := make(map[string]bool)
1601
1602 for _, service := range serviceList {
1603 serviceMap[service] = false
1604 }
1605 msr := newMigrateServicesRequest(reqID, oldVnetID, newVnetID, serviceMap, d.Name)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301606 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301607
1608 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301609 go msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301610 return nil
1611}
1612
vinokuma926cb3e2023-03-29 11:41:06 +05301613// ProcessMigrateServicesProfRequest - collects all associated profiles
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301614func (msr *MigrateServicesRequest) ProcessMigrateServicesProfRequest(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301615 va := GetApplication()
1616 for srv, processed := range msr.ServicesList {
vinokuma926cb3e2023-03-29 11:41:06 +05301617 // Indicates new service is already created and only deletion of old one is pending
Naveen Sampath04696f72022-06-13 15:19:14 +05301618 if processed {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301619 va.DelService(cntx, srv, true, nil, true)
1620 msr.serviceMigrated(cntx, srv)
Naveen Sampath04696f72022-06-13 15:19:14 +05301621 continue
1622 }
1623
1624 logger.Infow(ctx, "Migrate Service Triggering", log.Fields{"Service": srv})
1625 if vsIntf, ok := va.ServiceByName.Load(srv); ok {
1626 vs := vsIntf.(*VoltService)
1627 vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan)
1628 if vpv == nil {
1629 logger.Errorw(ctx, "Vpv Not found for Service", log.Fields{"vs": vs.Name, "port": vs.Port, "Vnet": vs.VnetID})
1630 continue
1631 }
1632 logger.Infow(ctx, "Migrating Service", log.Fields{"Service": vs.Name, "UsFlowApplied": vs.UsHSIAFlowsApplied})
1633 vpv.Blocked = true
1634
1635 // setDeactTrigger := func(key, value interface{}) bool {
1636 // vs := value.(*VoltService)
1637 vs.ServiceLock.Lock()
1638 vs.UpdateInProgress = true
1639 metadata := &MigrateServiceMetadata{
1640 NewVnetID: msr.NewVnetID,
1641 RequestID: msr.ID,
1642 }
1643 vs.Metadata = metadata
1644 vs.ServiceLock.Unlock()
1645
vinokuma926cb3e2023-03-29 11:41:06 +05301646 // vpv flows will be removed when last service is removed from it and
Naveen Sampath04696f72022-06-13 15:19:14 +05301647 // new vpv flows will be installed when new service is added
1648 if vs.UsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301649 vpv.DelTrapFlows(cntx)
1650 vs.DelHsiaFlows(cntx)
Tinoj Joseph1d108322022-07-13 10:07:39 +05301651 logger.Infow(ctx, "Remove Service Flows Triggered", log.Fields{"Service": srv, "US": vs.UsHSIAFlowsApplied, "DS": vs.DsHSIAFlowsApplied})
Naveen Sampath04696f72022-06-13 15:19:14 +05301652 } else {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301653 vs.updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301654 }
1655 } else {
1656 logger.Warnw(ctx, "Migrate Service Failed: Service Not Found", log.Fields{"Service": srv, "Vnet": msr.OldVnetID})
1657 }
1658 }
1659}
1660
vinokuma926cb3e2023-03-29 11:41:06 +05301661// AddMigratingServices - store msr info to device obj
Naveen Sampath04696f72022-06-13 15:19:14 +05301662func (d *VoltDevice) AddMigratingServices(msr *MigrateServicesRequest) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301663 var msrMap *util.ConcurrentMap
1664 if msrMapIntf, ok := d.MigratingServices.Get(msr.OldVnetID); !ok {
1665 msrMap = util.NewConcurrentMap()
1666 } else {
1667 msrMap = msrMapIntf.(*util.ConcurrentMap)
1668 }
1669
1670 msrMap.Set(msr.ID, msr)
1671 logger.Infow(ctx, "1: MsrListLen", log.Fields{"Len": msrMap.Length(), "Vnet": msr.OldVnetID})
1672
1673 d.MigratingServices.Set(msr.OldVnetID, msrMap)
1674 logger.Infow(ctx, "1: DeviceMsr", log.Fields{"Device": d.Name, "Vnet": msr.OldVnetID, "Len": d.MigratingServices.Length()})
Naveen Sampath04696f72022-06-13 15:19:14 +05301675}
1676
vinokuma926cb3e2023-03-29 11:41:06 +05301677// getMigrateServicesRequest - fetches msr info from device
Naveen Sampath04696f72022-06-13 15:19:14 +05301678func (va *VoltApplication) getMigrateServicesRequest(deviceID string, oldVnetID string, requestID string) *MigrateServicesRequest {
1679 if vd := va.GetDevice(deviceID); vd != nil {
1680 logger.Infow(ctx, "2: DeviceMsr", log.Fields{"Device": deviceID, "Vnet": oldVnetID, "Len": vd.MigratingServices.Length()})
1681 if msrListIntf, ok := vd.MigratingServices.Get(oldVnetID); ok {
1682 msrList := msrListIntf.(*util.ConcurrentMap)
1683 logger.Infow(ctx, "2: MsrListLen", log.Fields{"Len": msrList.Length(), "Vnet": oldVnetID})
1684 if msrObj, ok := msrList.Get(requestID); ok {
1685 return msrObj.(*MigrateServicesRequest)
1686 }
Naveen Sampath04696f72022-06-13 15:19:14 +05301687 }
1688 }
1689 logger.Errorw(ctx, "Device Not Found", log.Fields{"Device": deviceID})
1690 return nil
1691}
1692
vinokuma926cb3e2023-03-29 11:41:06 +05301693// updateMigrateServicesRequest - Updates the device with updated msr
Naveen Sampath04696f72022-06-13 15:19:14 +05301694func (va *VoltApplication) updateMigrateServicesRequest(deviceID string, oldVnetID string, requestID string, msr *MigrateServicesRequest) {
1695 if vd := va.GetDevice(deviceID); vd != nil {
1696 if msrList, ok := vd.MigratingServices.Get(oldVnetID); ok {
1697 if _, ok := msrList.(*util.ConcurrentMap).Get(requestID); ok {
1698 msrList.(*util.ConcurrentMap).Set(requestID, msr)
1699 }
1700 }
1701 }
1702}
1703
vinokuma926cb3e2023-03-29 11:41:06 +05301704// updateVnetProfile - Called on flow process completion
1705// Removes old service and creates new VPV & service with updated vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301706func (vs *VoltService) updateVnetProfile(cntx context.Context, deviceID string) {
Tinoj Joseph1d108322022-07-13 10:07:39 +05301707 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 +05301708
1709 nvs := VoltService{}
1710 nvs.VoltServiceCfg = vs.VoltServiceCfg
1711 nvs.Device = vs.Device
1712 nvs.Ipv4Addr = vs.Ipv4Addr
1713 nvs.Ipv6Addr = vs.Ipv6Addr
1714 nvs.UsMeterID = vs.UsMeterID
1715 nvs.DsMeterID = vs.DsMeterID
1716 nvs.AggDsMeterID = vs.AggDsMeterID
1717 nvs.UsHSIAFlowsApplied = vs.UsHSIAFlowsApplied
1718 nvs.DsHSIAFlowsApplied = vs.DsHSIAFlowsApplied
1719 nvs.UsDhcpFlowsApplied = vs.UsDhcpFlowsApplied
1720 nvs.DsDhcpFlowsApplied = vs.DsDhcpFlowsApplied
1721 nvs.IgmpFlowsApplied = vs.IgmpFlowsApplied
1722 nvs.Icmpv6FlowsApplied = vs.Icmpv6FlowsApplied
1723 nvs.PendingFlows = vs.PendingFlows
1724 nvs.AssociatedFlows = vs.AssociatedFlows
1725 nvs.DeleteInProgress = vs.DeleteInProgress
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301726 nvs.DeactivateInProgress = vs.DeactivateInProgress
Naveen Sampath04696f72022-06-13 15:19:14 +05301727 nvs.ForceDelete = vs.ForceDelete
1728 nvs.BwAvailInfo = vs.BwAvailInfo
1729 nvs.UpdateInProgress = vs.UpdateInProgress
1730
1731 if nvs.DeleteInProgress {
1732 logger.Warnw(ctx, "Skipping Service Migration. Service Delete in Progress", log.Fields{"Device": deviceID, "Service": vs.Name, "Vnet": vs.VnetID})
1733 return
1734 }
1735
1736 metadata := vs.Metadata.(*MigrateServiceMetadata)
1737 oldVnetID := vs.VnetID
Naveen Sampath04696f72022-06-13 15:19:14 +05301738 oldSrvName := vs.Name
1739
1740 if metadata == nil || metadata.NewVnetID == "" {
1741 logger.Errorw(ctx, "Migrate Service Metadata not found. Dropping vnet profile update request", log.Fields{"Service": vs.Name, "Vnet": vs.VnetID})
1742 return
1743 }
1744
vinokuma926cb3e2023-03-29 11:41:06 +05301745 nvs.VnetID = metadata.NewVnetID
1746 id := metadata.RequestID
1747
1748 // First add the new service and then only delete the old service
Naveen Sampath04696f72022-06-13 15:19:14 +05301749 // Since if post del service in case of pod crash or reboot, the service data will be lost
1750 va := GetApplication()
1751 msr := va.getMigrateServicesRequest(deviceID, oldVnetID, id)
1752 vnets := strings.Split(metadata.NewVnetID, "-")
1753 svlan, _ := strconv.Atoi(vnets[0])
1754 nvs.SVlan = of.VlanType(svlan)
1755 nvs.UpdateInProgress = false
1756 nvs.Metadata = nil
1757 nvs.Trigger = ServiceVlanUpdate
1758
1759 svcName := vs.Port + "-" + strconv.FormatUint(uint64(nvs.SVlan), 10) + "-"
1760 svcName = svcName + strconv.FormatUint(uint64(vs.CVlan), 10) + "-"
1761 nvs.Name = svcName + strconv.FormatUint(uint64(vs.TechProfileID), 10)
1762
vinokuma926cb3e2023-03-29 11:41:06 +05301763 // TODO:Nav Pass a copy, not the pointer
Naveen Sampath04696f72022-06-13 15:19:14 +05301764 logger.Infow(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 +05301765 if err := va.AddService(cntx, nvs.VoltServiceCfg, &nvs.VoltServiceOper); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301766 logger.Warnw(ctx, "Add New Service Failed", log.Fields{"Service": nvs.Name, "Error": err})
1767 }
1768 logger.Infow(ctx, "Add New Service Triggered", log.Fields{"Service": nvs.Name, "US": nvs.UsHSIAFlowsApplied, "DS": nvs.DsHSIAFlowsApplied, "DelFlag": nvs.DeleteInProgress})
1769
1770 msr.ServicesList[oldSrvName] = true
1771 va.updateMigrateServicesRequest(deviceID, oldVnetID, id, msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301772 msr.WriteToDB(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301773
1774 logger.Infow(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 +05301775 va.DelService(cntx, oldSrvName, true, nil, true)
Naveen Sampath04696f72022-06-13 15:19:14 +05301776 logger.Infow(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 +05301777 msr.serviceMigrated(cntx, oldSrvName)
Naveen Sampath04696f72022-06-13 15:19:14 +05301778}
1779
vinokuma926cb3e2023-03-29 11:41:06 +05301780// serviceMigrated - called on successful service updation
Naveen Sampath04696f72022-06-13 15:19:14 +05301781// Removes the service entry from servicelist and deletes the request on process completion
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301782func (msr *MigrateServicesRequest) serviceMigrated(cntx context.Context, serviceName string) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301783 msr.MigrateServicesLock.Lock()
1784 defer msr.MigrateServicesLock.Unlock()
1785
1786 delete(msr.ServicesList, serviceName)
1787
1788 if len(msr.ServicesList) == 0 {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301789 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301790 return
1791 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301792 msr.WriteToDB(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +05301793 // TODO:Nav - Need for any Response to SubMgr?
Naveen Sampath04696f72022-06-13 15:19:14 +05301794}
1795
vinokuma926cb3e2023-03-29 11:41:06 +05301796// TriggerPendingMigrateServicesReq - trigger pending service request
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301797func (va *VoltApplication) TriggerPendingMigrateServicesReq(cntx context.Context, device string) {
1798 va.FetchAndProcessAllMigrateServicesReq(cntx, device, storeAndProcessMigrateSrvRequest)
Naveen Sampath04696f72022-06-13 15:19:14 +05301799}
1800
vinokuma926cb3e2023-03-29 11:41:06 +05301801// FetchAndProcessAllMigrateServicesReq - fetch all pending migrate services req from DB and process based on provided func
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301802func (va *VoltApplication) FetchAndProcessAllMigrateServicesReq(cntx context.Context, device string, msrAction func(context.Context, *MigrateServicesRequest)) {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301803 msrList, _ := db.GetAllMigrateServicesReq(cntx, device)
Naveen Sampath04696f72022-06-13 15:19:14 +05301804 for _, msr := range msrList {
1805 b, ok := msr.Value.([]byte)
1806 if !ok {
1807 logger.Warn(ctx, "The value type is not []byte")
1808 continue
1809 }
1810 msr := va.createMigrateServicesFromString(b)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301811 msrAction(cntx, msr)
Naveen Sampath04696f72022-06-13 15:19:14 +05301812 logger.Warnw(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 +05301813 }
1814}
1815
1816// createMigrateServicesFromString to create Service from string
1817func (va *VoltApplication) createMigrateServicesFromString(b []byte) *MigrateServicesRequest {
1818 var msr MigrateServicesRequest
1819 if err := json.Unmarshal(b, &msr); err == nil {
1820 logger.Debugw(ctx, "Adding Migrate Services Request From Db", log.Fields{"Vlan": msr.OldVnetID})
Naveen Sampath04696f72022-06-13 15:19:14 +05301821 } else {
1822 logger.Warn(ctx, "Unmarshal failed")
1823 }
1824 return &msr
1825}
1826
vinokuma926cb3e2023-03-29 11:41:06 +05301827// storeAndProcessMigrateSrvRequest - stores the msr info in device obj and triggers req
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301828func storeAndProcessMigrateSrvRequest(cntx context.Context, msr *MigrateServicesRequest) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301829 d := GetApplication().GetDevice(msr.DeviceID)
1830 d.AddMigratingServices(msr)
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301831 msr.ProcessMigrateServicesProfRequest(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +05301832}
1833
vinokuma926cb3e2023-03-29 11:41:06 +05301834// forceUpdateAllServices - force udpate services with new vnet profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301835func forceUpdateAllServices(cntx context.Context, msr *MigrateServicesRequest) {
Naveen Sampath04696f72022-06-13 15:19:14 +05301836 for srv := range msr.ServicesList {
1837 if vsIntf, ok := GetApplication().ServiceByName.Load(srv); ok {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301838 vsIntf.(*VoltService).updateVnetProfile(cntx, msr.DeviceID)
Naveen Sampath04696f72022-06-13 15:19:14 +05301839 }
1840 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301841 _ = db.DelMigrateServicesReq(cntx, msr.DeviceID, msr.GetMsrKey())
Naveen Sampath04696f72022-06-13 15:19:14 +05301842}
1843
vinokuma926cb3e2023-03-29 11:41:06 +05301844// nolint: gocyclo
1845// DeepEqualServicecfg - checks if the given service cfgs are same
Naveen Sampath04696f72022-06-13 15:19:14 +05301846func (va *VoltApplication) DeepEqualServicecfg(evs *VoltServiceCfg, nvs *VoltServiceCfg) bool {
1847 if nvs.Name != evs.Name {
1848 return false
1849 }
1850 if nvs.UniVlan != evs.UniVlan {
1851 return false
1852 }
1853 if nvs.CVlan != evs.CVlan {
1854 return false
1855 }
1856 if nvs.SVlan != evs.SVlan {
1857 return false
1858 }
1859 if nvs.SVlanTpid != 0 && nvs.SVlanTpid != evs.SVlanTpid {
1860 return false
1861 }
1862 if !util.IsPbitSliceSame(nvs.Pbits, evs.Pbits) {
1863 return false
1864 }
1865 if !reflect.DeepEqual(nvs.DsRemarkPbitsMap, evs.DsRemarkPbitsMap) {
1866 return false
1867 }
1868 if nvs.TechProfileID != evs.TechProfileID {
1869 return false
1870 }
1871 if nvs.CircuitID != evs.CircuitID {
1872 return false
1873 }
1874 if !bytes.Equal(nvs.RemoteID, evs.RemoteID) {
1875 return false
1876 }
1877 if nvs.Port != evs.Port {
1878 return false
1879 }
1880 if nvs.PonPort != evs.PonPort {
1881 return false
1882 }
1883 if evs.MacLearning == MacLearningNone && !util.MacAddrsMatch(nvs.MacAddr, evs.MacAddr) {
1884 return false
1885 }
Hitesh Chhabra9f9a9df2023-06-13 17:52:15 +05301886 if nvs.IsOption82Enabled != evs.IsOption82Enabled {
Naveen Sampath04696f72022-06-13 15:19:14 +05301887 return false
1888 }
1889 if nvs.IgmpEnabled != evs.IgmpEnabled {
1890 return false
1891 }
1892 if nvs.McastService != evs.McastService {
1893 return false
1894 }
1895 if nvs.ONTEtherTypeClassification != evs.ONTEtherTypeClassification {
1896 return false
1897 }
1898 if nvs.UsMeterProfile != evs.UsMeterProfile {
1899 return false
1900 }
1901 if nvs.DsMeterProfile != evs.DsMeterProfile {
1902 return false
1903 }
1904 if nvs.AggDsMeterProfile != evs.AggDsMeterProfile {
1905 return false
1906 }
1907 if nvs.VnetID != evs.VnetID {
1908 return false
1909 }
1910 if nvs.MvlanProfileName != evs.MvlanProfileName {
1911 return false
1912 }
1913 if nvs.RemoteIDType != evs.RemoteIDType {
1914 return false
1915 }
1916 if nvs.SchedID != evs.SchedID {
1917 return false
1918 }
1919 if nvs.AllowTransparent != evs.AllowTransparent {
1920 return false
1921 }
1922 if nvs.EnableMulticastKPI != evs.EnableMulticastKPI {
1923 return false
1924 }
1925 if nvs.DataRateAttr != evs.DataRateAttr {
1926 return false
1927 }
1928 if nvs.MinDataRateUs != evs.MinDataRateUs {
1929 return false
1930 }
1931 if nvs.MinDataRateDs != evs.MinDataRateDs {
1932 return false
1933 }
1934 if nvs.MaxDataRateUs != evs.MaxDataRateUs {
1935 return false
1936 }
1937 if nvs.MaxDataRateDs != evs.MaxDataRateDs {
1938 return false
1939 }
1940
1941 return true
1942}
1943
vinokuma926cb3e2023-03-29 11:41:06 +05301944// TriggerAssociatedFlowDelete - re-trigger service flow delete for pending delete flows
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301945func (vs *VoltService) TriggerAssociatedFlowDelete(cntx context.Context) bool {
vinokuma926cb3e2023-03-29 11:41:06 +05301946 // Clear the Flows flag if already set
1947 // This case happens only in case of some race condition
Naveen Sampath04696f72022-06-13 15:19:14 +05301948 if vs.UsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301949 if err := vs.DelUsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301950 logger.Errorw(ctx, "DelUsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
1951 }
1952 }
1953
1954 if vs.DsHSIAFlowsApplied {
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301955 if err := vs.DelDsHsiaFlows(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301956 logger.Errorw(ctx, "DelDsHsiaFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Error": err})
1957 }
1958 }
1959
1960 vs.ServiceLock.Lock()
1961 cookieList := []uint64{}
1962 for cookie := range vs.AssociatedFlows {
1963 cookieList = append(cookieList, convertToUInt64(cookie))
1964 }
1965 vs.ServiceLock.Unlock()
1966
1967 if len(cookieList) == 0 {
1968 return false
1969 }
1970
vinokuma926cb3e2023-03-29 11:41:06 +05301971 // Trigger Flow Delete
Naveen Sampath04696f72022-06-13 15:19:14 +05301972 for _, cookie := range cookieList {
1973 if vd := GetApplication().GetDevice(vs.Device); vd != nil {
1974 flow := &of.VoltFlow{}
1975 flow.SubFlows = make(map[uint64]*of.VoltSubFlow)
1976 subFlow := of.NewVoltSubFlow()
1977 subFlow.Cookie = cookie
1978 flow.SubFlows[cookie] = subFlow
1979 logger.Infow(ctx, "Retriggering Service Delete Flow", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie})
Tinoj Joseph07cc5372022-07-18 22:53:51 +05301980 if err := vs.DelFlows(cntx, vd, flow); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +05301981 logger.Errorw(ctx, "DelFlows Failed", log.Fields{"Device": vs.Device, "Service": vs.Name, "Cookie": cookie, "Error": err})
1982 }
1983 }
1984 }
1985 return true
1986}
1987
vinokuma926cb3e2023-03-29 11:41:06 +05301988// triggerServiceInProgressInd - Indication is generated when Service is not provisioned after add serviec req from NB
Naveen Sampath04696f72022-06-13 15:19:14 +05301989func (vs *VoltService) triggerServiceInProgressInd() {
1990}
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05301991
vinokuma926cb3e2023-03-29 11:41:06 +05301992// JSONMarshal wrapper function for json Marshal VoltService
1993func (vs *VoltService) JSONMarshal() ([]byte, error) {
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05301994 return json.Marshal(VoltService{
1995 VoltServiceCfg: vs.VoltServiceCfg,
1996 VoltServiceOper: VoltServiceOper{
Hitesh Chhabra64be2442023-06-21 17:06:34 +05301997 Device: vs.VoltServiceOper.Device,
1998 Ipv4Addr: vs.VoltServiceOper.Ipv4Addr,
1999 Ipv6Addr: vs.VoltServiceOper.Ipv6Addr,
2000 UsMeterID: vs.VoltServiceOper.UsMeterID,
2001 DsMeterID: vs.VoltServiceOper.DsMeterID,
2002 AggDsMeterID: vs.VoltServiceOper.AggDsMeterID,
2003 UsHSIAFlowsApplied: vs.VoltServiceOper.UsHSIAFlowsApplied,
2004 DsHSIAFlowsApplied: vs.VoltServiceOper.DsHSIAFlowsApplied,
2005 UsDhcpFlowsApplied: vs.VoltServiceOper.UsDhcpFlowsApplied,
2006 DsDhcpFlowsApplied: vs.VoltServiceOper.DsDhcpFlowsApplied,
2007 IgmpFlowsApplied: vs.VoltServiceOper.IgmpFlowsApplied,
2008 Icmpv6FlowsApplied: vs.VoltServiceOper.Icmpv6FlowsApplied,
2009 PendingFlows: vs.VoltServiceOper.PendingFlows,
2010 AssociatedFlows: vs.VoltServiceOper.AssociatedFlows,
2011 DeleteInProgress: vs.VoltServiceOper.DeleteInProgress,
2012 DeactivateInProgress: vs.VoltServiceOper.DeactivateInProgress,
2013 ForceDelete: vs.VoltServiceOper.ForceDelete,
2014 BwAvailInfo: vs.VoltServiceOper.BwAvailInfo,
2015 UpdateInProgress: vs.VoltServiceOper.UpdateInProgress,
2016 Metadata: vs.VoltServiceOper.Metadata,
Tinoj Josephc2ccd6b2022-07-19 04:32:15 +05302017 },
2018 })
2019}
Tinoj Josephec742f62022-09-29 19:11:10 +05302020
2021// GetProgrammedSubscribers to get list of programmed subscribers
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302022func (va *VoltApplication) GetProgrammedSubscribers(cntx context.Context, deviceID, portNo string) ([]*VoltService, error) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302023 var svcList []*VoltService
2024 logger.Infow(ctx, "GetProgrammedSubscribers Request ", log.Fields{"Device": deviceID, "Port": portNo})
2025 va.ServiceByName.Range(func(key, value interface{}) bool {
2026 vs := value.(*VoltService)
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302027 if len(deviceID) > 0 {
2028 if len(portNo) > 0 {
Tinoj Josephec742f62022-09-29 19:11:10 +05302029 if deviceID == vs.Device && portNo == vs.Port {
2030 svcList = append(svcList, vs)
2031 }
2032 } else {
2033 if deviceID == vs.Device {
2034 svcList = append(svcList, vs)
2035 }
2036 }
2037 } else {
2038 svcList = append(svcList, vs)
2039 }
2040 return true
2041 })
2042 return svcList, nil
2043}
2044
Akash Soni634d9bf2023-07-10 12:11:10 +05302045type FlowProvisionStatus struct {
2046 FlowProvisionStatus string
2047}
2048
2049// GetFlowProvisionStatus to get status of the subscriber and flow provisioned in controller
Akash Soni3c391e72023-08-16 12:21:33 +05302050func (va *VoltApplication) GetFlowProvisionStatus(portNo string) FlowProvisionStatus {
Akash Soni634d9bf2023-07-10 12:11:10 +05302051 logger.Infow(ctx, "GetFlowProvisionStatus Request ", log.Fields{"Port": portNo})
2052 flowProvisionStatus := FlowProvisionStatus{}
Akash Soni3c391e72023-08-16 12:21:33 +05302053 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_NOT_IN_CONTROLLER
Akash Soni634d9bf2023-07-10 12:11:10 +05302054 va.ServiceByName.Range(func(key, value interface{}) bool {
2055 vs := value.(*VoltService)
2056 logger.Debugw(ctx, "Volt Service ", log.Fields{"VS": vs})
Akash Soni3c391e72023-08-16 12:21:33 +05302057 if portNo == vs.Port {
2058 if vs.DsHSIAFlowsApplied && vs.UsHSIAFlowsApplied && vs.LenOfPendingFlows() == 0 {
2059 flowProvisionStatus.FlowProvisionStatus = ALL_FLOWS_PROVISIONED
2060 return false
2061 } else if !vs.IsActivated {
2062 flowProvisionStatus.FlowProvisionStatus = SUBSCRIBER_DISABLED_IN_CONTROLLER
2063 return false
2064 } else if !vs.DsHSIAFlowsApplied && !vs.UsHSIAFlowsApplied {
2065 flowProvisionStatus.FlowProvisionStatus = NO_FLOWS_PROVISIONED
2066 return false
2067 } else if vs.LenOfPendingFlows() > 0 {
2068 flowProvisionStatus.FlowProvisionStatus = FLOWS_PROVISIONED_PARTIALLY
2069 return false
Akash Soni634d9bf2023-07-10 12:11:10 +05302070 }
2071 }
2072 return true
2073 })
Akash Soni634d9bf2023-07-10 12:11:10 +05302074 return flowProvisionStatus
2075}
2076
2077func (vs *VoltService) LenOfPendingFlows() int {
2078 vs.ServiceLock.RLock()
2079 lth := len(vs.PendingFlows)
2080 vs.ServiceLock.RUnlock()
2081 return lth
2082}
2083
Tinoj Josephec742f62022-09-29 19:11:10 +05302084// ActivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302085func (va *VoltApplication) ActivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302086 var isParmsInvalid bool
Tinoj Josephec742f62022-09-29 19:11:10 +05302087 logger.Infow(ctx, "Service Activate Request ", log.Fields{"Device": deviceID, "Port": portNo})
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302088 device, err := va.GetDeviceFromPort(portNo)
2089 if err != nil {
2090 logger.Errorw(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portNo})
2091 return errorCodes.ErrPortNotFound
2092 }
2093 // If device id is not provided check only port number
2094 if deviceID == DeviceAny {
2095 deviceID = device.Name
2096 } else if deviceID != device.Name {
2097 logger.Errorw(ctx, "Wrong Device ID", log.Fields{"Device": deviceID, "Port": portNo})
2098 return errorCodes.ErrDeviceNotFound
2099 }
Tinoj Josephec742f62022-09-29 19:11:10 +05302100 va.ServiceByName.Range(func(key, value interface{}) bool {
2101 vs := value.(*VoltService)
Tinoj Josephec742f62022-09-29 19:11:10 +05302102 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302103 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
Tinoj Joseph50d722c2022-12-06 22:53:22 +05302104 logger.Infow(ctx, "Service Activate Request Does not match", log.Fields{"Device": deviceID, "voltService": vs})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302105 isParmsInvalid = true
Tinoj Josephec742f62022-09-29 19:11:10 +05302106 return true
2107 }
2108 if portNo == vs.Port && !vs.IsActivated {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302109 isParmsInvalid = false
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302110 p := device.GetPort(vs.Port)
Tinoj Josephec742f62022-09-29 19:11:10 +05302111 if p == nil {
2112 logger.Warnw(ctx, "Wrong device or port", log.Fields{"Device": deviceID, "Port": portNo})
2113 return true
2114 }
2115 logger.Infow(ctx, "Service Activate", log.Fields{"Name": vs.Name})
2116 vs.IsActivated = true
2117 va.ServiceByName.Store(vs.Name, vs)
2118 vs.WriteToDb(cntx)
2119 // If port is already up send indication to vpv
2120 if p.State == PortStateUp {
2121 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2122 // PortUp call initiates flow addition
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302123 vpv.PortUpInd(cntx, device, portNo)
Tinoj Josephec742f62022-09-29 19:11:10 +05302124 } else {
2125 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2126 }
2127 }
2128 }
2129 return true
2130 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302131
2132 if isParmsInvalid {
2133 return errorCodes.ErrInvalidParamInRequest
2134 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302135 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302136}
2137
2138// DeactivateService to activate pre-provisioned service
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302139func (va *VoltApplication) DeactivateService(cntx context.Context, deviceID, portNo string, sVlan, cVlan of.VlanType, tpID uint16) error {
Tinoj Josephec742f62022-09-29 19:11:10 +05302140 logger.Infow(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302141 var isServiceExist bool
2142 var isParmsInvalid bool
2143
Tinoj Josephec742f62022-09-29 19:11:10 +05302144 va.ServiceByName.Range(func(key, value interface{}) bool {
2145 vs := value.(*VoltService)
2146 // If svlan if provided, then the tags and tpID of service has to be matching
Tinoj Josephd5b4f2f2022-11-11 19:25:24 +05302147 logger.Infow(ctx, "Service Deactivate Request ", log.Fields{"Device": deviceID, "Port": portNo})
2148 if sVlan != of.VlanNone && (sVlan != vs.SVlan || cVlan != vs.CVlan || tpID != vs.TechProfileID) {
vinokuma926cb3e2023-03-29 11:41:06 +05302149 logger.Infow(ctx, "condition not matched", log.Fields{"Device": deviceID, "Port": portNo, "sVlan": sVlan, "cVlan": cVlan, "tpID": tpID})
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302150 isParmsInvalid = true
Tinoj Josephec742f62022-09-29 19:11:10 +05302151 return true
2152 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302153 if portNo == vs.Port && vs.IsActivated {
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302154 isServiceExist = true
2155 isParmsInvalid = false
Tinoj Josephec742f62022-09-29 19:11:10 +05302156 vs.IsActivated = false
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302157 vs.DeactivateInProgress = true
Tinoj Josephec742f62022-09-29 19:11:10 +05302158 va.ServiceByName.Store(vs.Name, vs)
2159 vs.WriteToDb(cntx)
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302160 device, err := va.GetDeviceFromPort(portNo)
2161 if err != nil {
2162 // Even if the port/device does not exists at this point in time, the deactivate request is succss.
2163 // So no error is returned
2164 logger.Infow(ctx, "Error Getting Device", log.Fields{"Reason": err.Error(), "Port": portNo})
2165 return true
2166 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302167 p := device.GetPort(vs.Port)
vinokuma926cb3e2023-03-29 11:41:06 +05302168 if p != nil && (p.State == PortStateUp || !va.OltFlowServiceConfig.RemoveFlowsOnDisable) {
Tinoj Josephec742f62022-09-29 19:11:10 +05302169 if vpv := va.GetVnetByPort(vs.Port, vs.SVlan, vs.CVlan, vs.UniVlan); vpv != nil {
2170 // Port down call internally deletes all the flows
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302171 vpv.PortDownInd(cntx, deviceID, portNo, true)
Tinoj Josephec742f62022-09-29 19:11:10 +05302172 if vpv.IgmpEnabled {
2173 va.ReceiverDownInd(cntx, deviceID, portNo)
2174 }
Hitesh Chhabra64be2442023-06-21 17:06:34 +05302175 vs.DeactivateInProgress = false
Tinoj Josephec742f62022-09-29 19:11:10 +05302176 } else {
2177 logger.Warnw(ctx, "VPV does not exists!!!", log.Fields{"Device": deviceID, "port": portNo, "SvcName": vs.Name})
2178 }
2179 }
2180 }
2181 return true
2182 })
Hitesh Chhabra7d249a02023-07-04 21:33:49 +05302183
2184 if isParmsInvalid {
2185 return errorCodes.ErrInvalidParamInRequest
2186 } else if !isServiceExist && !isParmsInvalid {
2187 return errorCodes.ErrPortNotFound
2188 }
Tinoj Josephaf37ce82022-12-28 11:59:43 +05302189 return nil
Tinoj Josephec742f62022-09-29 19:11:10 +05302190}
Tinoj Joseph4ead4e02023-01-30 03:12:44 +05302191
vinokuma926cb3e2023-03-29 11:41:06 +05302192// GetServicePbit to get first set bit in the pbit map
2193// returns -1 : If configured to match on all pbits
2194// returns 8 : If no pbits are configured
2195// returns first pbit if specific pbit is configured
Tinoj Josephec742f62022-09-29 19:11:10 +05302196func (vs *VoltService) GetServicePbit() int {
2197 if vs.IsPbitExist(of.PbitMatchAll) {
2198 return -1
2199 }
vinokuma926cb3e2023-03-29 11:41:06 +05302200 for pbit := 0; pbit < int(of.PbitMatchNone); pbit++ {
Tinoj Josephec742f62022-09-29 19:11:10 +05302201 if vs.IsPbitExist(of.PbitType(pbit)) {
2202 return pbit
2203 }
2204 }
2205 return int(of.PbitMatchNone)
2206}