blob: cc61a4ff5a0d31ea2cf2eb95c677c185fb86de17 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14 */
15
16package application
17
18import (
vinokuma926cb3e2023-03-29 11:41:06 +053019 "context"
Naveen Sampath04696f72022-06-13 15:19:14 +053020 "encoding/json"
21 "errors"
22 "sync"
23
Naveen Sampath04696f72022-06-13 15:19:14 +053024 "voltha-go-controller/database"
vinokuma926cb3e2023-03-29 11:41:06 +053025 cntlr "voltha-go-controller/internal/pkg/controller"
Naveen Sampath04696f72022-06-13 15:19:14 +053026 "voltha-go-controller/internal/pkg/of"
Tinoj Joseph1d108322022-07-13 10:07:39 +053027 "voltha-go-controller/log"
Naveen Sampath04696f72022-06-13 15:19:14 +053028)
29
30// VoltShaperConfig is shaper profile configuration structure
31type VoltShaperConfig struct {
32 Name string
33 BurstSize uint32
34}
35
36// VoltBwConfig is bandwidth profile configuration structure
37type VoltBwConfig struct {
38 Name string
39 Fir uint32
40 Air uint32
41 Eir uint32
42}
43
44// VoltBandwidthProf is bandwidth profile stored at VGC
45type VoltBandwidthProf struct {
46 VoltBwConfig
47}
48
49// VoltShaperProf is shaper profile stored at VGC
50type VoltShaperProf struct {
51 VoltShaperConfig
52}
53
54// VoltMeterProf is meter profile stored at VGC
55type VoltMeterProf struct {
56 VoltMeter
57}
58
59// MeterMgr structure
60type MeterMgr struct {
61 Meters sync.Map
62 MetersByID sync.Map
63 LastMeterID uint32
64}
65
66// Init to initialize MeterMgr
67func (m *MeterMgr) Init() {
68 m.LastMeterID = 0
69}
70
71// VoltMeter : A VOLT meter is a combination of BW and shaper profiles
72// The ID is generated by the VOLT application
73type VoltMeter struct {
74 Name string
vinokuma926cb3e2023-03-29 11:41:06 +053075 Version string
Naveen Sampath04696f72022-06-13 15:19:14 +053076 ID uint32
77 Fir uint32
78 Air uint32
79 Eir uint32
80 BurstSize uint32
81 AssociatedServices uint32
Naveen Sampath04696f72022-06-13 15:19:14 +053082 Cir uint32
83 Cbs uint32
84 Pir uint32
85 Pbs uint32
86 Gir uint32
87 Ebs uint32
88}
89
90// WriteToDb to write a meter profile to DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +053091func (vm *VoltMeter) WriteToDb(cntx context.Context) error {
Naveen Sampath04696f72022-06-13 15:19:14 +053092 vm.Version = database.PresentVersionMap[database.MeterPath]
93 b, err := json.Marshal(vm)
94 if err != nil {
95 return err
96 }
Tinoj Joseph07cc5372022-07-18 22:53:51 +053097 if err1 := db.PutMeter(cntx, vm.Name, string(b)); err1 != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +053098 return err1
99 }
100 return nil
101}
102
103// DelFromDb to delete a meter profile from DB
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530104func (vm *VoltMeter) DelFromDb(cntx context.Context) {
105 _ = db.DelMeter(cntx, vm.Name)
Naveen Sampath04696f72022-06-13 15:19:14 +0530106}
107
108// GetMeterByName to get meter by name
109func (m *MeterMgr) GetMeterByName(name string) (*VoltMeter, bool) {
110 meter, ok := m.Meters.Load(name)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530111 logger.Infow(ctx, "Meter Obtained Name", log.Fields{"Name": name, "Meter": meter})
Naveen Sampath04696f72022-06-13 15:19:14 +0530112 if ok {
113 return meter.(*VoltMeter), ok
114 }
115 return nil, ok
116}
117
118// GetMeterByID to get meter by ID
119func (m *MeterMgr) GetMeterByID(id uint32) (*VoltMeter, bool) {
120 meter, ok := m.MetersByID.Load(id)
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530121 logger.Infow(ctx, "GetMeter Obtained ID", log.Fields{"ID": id, "Meter": meter})
Naveen Sampath04696f72022-06-13 15:19:14 +0530122 if ok {
123 return meter.(*VoltMeter), ok
124 }
125 return nil, ok
126}
127
128// AddMeter to add meter
129func (m *MeterMgr) AddMeter(meter *VoltMeter) {
130 m.Meters.Store(meter.Name, meter)
131 m.MetersByID.Store(meter.ID, meter)
132 logger.Infow(ctx, "Meter Added/Updated", log.Fields{"Meter": meter, "Name": meter.Name, "Id": meter.ID})
133}
134
135// DelMeter to delete meter
136func (m *MeterMgr) DelMeter(meter *VoltMeter) {
137 m.Meters.Delete(meter.Name)
138 m.MetersByID.Delete(meter.ID)
139 logger.Infow(ctx, "Meter Deleted", log.Fields{"Meter": meter, "Name": meter.Name, "Id": meter.ID})
140}
141
142// AddToDevice to add meter to the device
143func (vm *VoltMeter) AddToDevice(port string, device string, aggVM *VoltMeter) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530144 logger.Debugw(ctx, "Add To Device", log.Fields{"Id": vm.ID, "Device": device, "Port": port})
Naveen Sampath04696f72022-06-13 15:19:14 +0530145 meter := of.NewMeter(vm.ID)
146 // meter.AddBand(vm.Air, vm.BurstSize)
147 // meter.AddBand(vm.Eir, vm.BurstSize)
148 // if aggVM != nil {
149 // meter.AddBand(aggVM.Air, aggVM.BurstSize)
150 // meter.AddBand(aggVM.Eir, aggVM.BurstSize)
151 // }
152
153 //Community VGC Impl
154
155 //Set Cir
156 if vm.Cir != 0 {
157 meter.AddBand(vm.Cir, vm.Cbs)
158 }
159
160 //Set Air to 0 if both air & gir are set
161 if vm.Air != 0 && vm.Gir != 0 {
162 vm.Air = 0
163 }
164
vinokuma926cb3e2023-03-29 11:41:06 +0530165 // Set Pir & Pbs
Naveen Sampath04696f72022-06-13 15:19:14 +0530166 var pir uint32
167 var pbs uint32
168 if vm.Pir != 0 {
169 pir = vm.Pir
170 } else {
171 pir = vm.Eir + vm.Cir + vm.Gir + vm.Air
172 }
173
174 if vm.Pbs != 0 {
175 pbs = vm.Pbs
176 } else {
177 pbs = vm.Ebs + vm.Cbs
178 }
179 meter.AddBand(pir, pbs)
180
181 //Set Gir
182 if vm.Gir != 0 {
183 meter.AddBand(vm.Gir, 0)
184 }
185
186 logger.Infow(ctx, "Meter Config", log.Fields{"Cir": vm.Cir, "Air": vm.Air, "Pir": vm.Pir, "Gir": vm.Gir, "Eir": vm.Eir})
187 logger.Infow(ctx, "Meter Burst Config", log.Fields{"Cbs": vm.Cbs, "Pbs": vm.Pbs})
188 logger.Infow(ctx, "Meter Burst Oper", log.Fields{"Pir": pir, "Pbs": pbs})
vinokuma926cb3e2023-03-29 11:41:06 +0530189 // Set Air
Naveen Sampath04696f72022-06-13 15:19:14 +0530190 // Air is used in place of Gir only if Gir is
191 // not present and Air is not 0
192 if vm.Air != 0 {
193 meter.AddBand(vm.Air, 0)
194 }
195
Tinoj Joseph1d108322022-07-13 10:07:39 +0530196 logger.Debugw(ctx, "Total Bands are", log.Fields{"meter": *meter})
Naveen Sampath04696f72022-06-13 15:19:14 +0530197 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandAdd, meter); err != nil {
198 logger.Warnw(ctx, "Add meter to device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
199 }
200}
201
202// AddMeterToDevice to add meter to the device
203func (m *MeterMgr) AddMeterToDevice(port string, device string, meterID uint32, aggMeterID uint32) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530204 logger.Debugw(ctx, "Adding Meter To Device", log.Fields{"Agg MeterID": aggMeterID, "Device": device, "Port": port, "MeterID": meterID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530205 var aggVM *VoltMeter
206 vm, err := m.GetMeterByProfID(meterID)
207 if err == nil {
208 if 0 != aggMeterID { //Assuming valid meter id will never be 0
209 if aggVM, err = m.GetMeterByProfID(aggMeterID); err != nil {
210 logger.Warnw(ctx, "Aggregated Meter not found", log.Fields{"Id": aggMeterID})
211 }
212 }
213 vm.AddToDevice(port, device, aggVM)
214 } else {
215 logger.Warnw(ctx, "Meter not found", log.Fields{"Id": meterID})
216 }
217}
218
219// RestoreMetersFromDb to read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530220func (m *MeterMgr) RestoreMetersFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530221 // VNETS must be learnt first
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530222 logger.Infow(ctx, "Received RestoreMetersFromDb and LastMeterID on restart", log.Fields{"LastMeterID": m.LastMeterID})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530223 ms, _ := db.GetMeters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530224 for _, mt := range ms {
225 b, ok := mt.Value.([]byte)
226 if !ok {
227 logger.Warn(ctx, "The value type is not []byte")
228 continue
229 }
230 var meter VoltMeter
231 err := json.Unmarshal(b, &meter)
232 if err != nil {
233 logger.Warn(ctx, "Unmarshal of meter profile failed")
234 continue
235 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530236 logger.Debugw(ctx, "Retrieved Meter", log.Fields{"Meter": meter.Name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530237 m.AddMeter(&meter)
238 if meter.ID > m.LastMeterID {
239 m.LastMeterID = meter.ID
240 }
241 }
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530242 logger.Debugw(ctx, "LastMeterID on reading DB", log.Fields{"LastMeterID": m.LastMeterID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530243}
244
245// AddMeterProf to add the meter profile name as key
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530246func (va *VoltApplication) AddMeterProf(cntx context.Context, cfg VoltMeter) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530247 logger.Infow(ctx, "Add the meter profile name as key", log.Fields{"MeterConfig": cfg})
Naveen Sampath04696f72022-06-13 15:19:14 +0530248 mm := &va.MeterMgr
249 if _, ok := mm.GetMeterByName(cfg.Name); ok {
250 logger.Warnw(ctx, "Meter profile exists", log.Fields{"Name": cfg.Name})
251 return
252 }
253
254 mm.LastMeterID++
vinokuma926cb3e2023-03-29 11:41:06 +0530255 // FIX-ME: Hardcoded the meter-id temp till meter delete is introduced
256 // Restriction: Only one meter profile should be used across all services
Naveen Sampath04696f72022-06-13 15:19:14 +0530257 // id := uint32(1) //mm.LastMeterId
258 id := mm.LastMeterID
259 cfg.ID = id
260 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530261 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530262 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
263 }
264}
265
266// UpdateMeterProf to update the meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530267func (va *VoltApplication) UpdateMeterProf(cntx context.Context, cfg VoltMeter) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530268 logger.Debugw(ctx, "Update the meter profile name as key", log.Fields{"MeterConfig": cfg})
Naveen Sampath04696f72022-06-13 15:19:14 +0530269 mm := &va.MeterMgr
270 if _, ok := mm.GetMeterByName(cfg.Name); !ok {
271 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": cfg.Name})
272 return
273 }
274 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530275 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530276 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
277 }
278}
279
280// GetMeterByProfID to get a meter based on the identities of bandwidth profile and shaper
281// profile names.
282func (m *MeterMgr) GetMeterByProfID(id uint32) (*VoltMeter, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530283 logger.Debugw(ctx, "Get Meter by Profile id", log.Fields{"ID": id})
Naveen Sampath04696f72022-06-13 15:19:14 +0530284 if mtr, ok := m.GetMeterByID(id); ok {
285 return mtr, nil
286 }
287 return nil, errors.New("Meter Missing")
288}
289
290// GetMeter to get a meter based on the identities of bandwidth profile and shaper
291// profile names.
292func (m *MeterMgr) GetMeter(meterID string) (*VoltMeter, error) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530293 logger.Debugw(ctx, "Get Meter by Meter id", log.Fields{"MeterID": meterID})
Naveen Sampath04696f72022-06-13 15:19:14 +0530294 if mt, ok := m.GetMeterByName(meterID); ok {
295 return mt, nil
296 }
297 return nil, errors.New("Meter Missing")
298}
299
300// DeleteFromDevice to delete meter from the device
301func (vm *VoltMeter) DeleteFromDevice(port string, device string) {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530302 logger.Debugw(ctx, "Delete meter from device", log.Fields{"Id": vm.ID, "Port": port, "Device": device})
Naveen Sampath04696f72022-06-13 15:19:14 +0530303 meter := of.NewMeter(vm.ID)
304
305 logger.Debugw(ctx, "Delete meter from device", log.Fields{"Id": vm.ID, "meter": *meter})
306 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandDel, meter); err != nil {
307 logger.Warnw(ctx, "Delete meter from device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
308 }
309}
310
311// DelMeterProf to delete meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530312func (va *VoltApplication) DelMeterProf(cntx context.Context, name string) error {
Hitesh Chhabra2b2347d2023-07-31 17:36:48 +0530313 logger.Debugw(ctx, "Delete meter profile", log.Fields{"Name": name})
Naveen Sampath04696f72022-06-13 15:19:14 +0530314 mm := &va.MeterMgr
315 if _, ok := mm.GetMeterByName(name); !ok {
316 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": name})
Akash Soni6f369452023-09-19 11:18:28 +0530317 return errors.New("meter profile doesn't exist")
Naveen Sampath04696f72022-06-13 15:19:14 +0530318 }
319 cfg, _ := mm.GetMeterByName(name)
320 if cfg.AssociatedServices != 0 {
321 logger.Warnw(ctx, "Mismatch in submgr and vgc oeter profile service reference",
322 log.Fields{"MeterProfile": name, "serviceCount": cfg.AssociatedServices})
Akash Soni6f369452023-09-19 11:18:28 +0530323 return errors.New("service reference is not 0")
Naveen Sampath04696f72022-06-13 15:19:14 +0530324 }
vinokuma926cb3e2023-03-29 11:41:06 +0530325 // TODO : delete from all devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530326 delmeterFromDevice := func(key interface{}, value interface{}) bool {
327 device := key.(string)
328 port, _ := GetApplication().GetNniPort(device)
329 cfg.DeleteFromDevice(port, device)
330 return true
331 }
332 va.DevicesDisc.Range(delmeterFromDevice)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530333 cfg.DelFromDb(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +0530334 // Delete meter from device will be invoked by caller separately
Naveen Sampath04696f72022-06-13 15:19:14 +0530335 mm.DelMeter(cfg)
336 return nil
337}