blob: 2592be5ecbe89a1d260c3d1123dec2daebfdd7b2 [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)
111 logger.Infow(ctx, "Meter Obtained Name", log.Fields{"Meter": meter})
112 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)
121 logger.Infow(ctx, "Meter Obtained ID", log.Fields{"Meter": meter})
122 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) {
144 logger.Debugw(ctx, "Adding Meter To Device", log.Fields{"Id": vm.ID, "Device": device, "Port": port})
145 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) {
204 var aggVM *VoltMeter
205 vm, err := m.GetMeterByProfID(meterID)
206 if err == nil {
207 if 0 != aggMeterID { //Assuming valid meter id will never be 0
208 if aggVM, err = m.GetMeterByProfID(aggMeterID); err != nil {
209 logger.Warnw(ctx, "Aggregated Meter not found", log.Fields{"Id": aggMeterID})
210 }
211 }
212 vm.AddToDevice(port, device, aggVM)
213 } else {
214 logger.Warnw(ctx, "Meter not found", log.Fields{"Id": meterID})
215 }
216}
217
218// RestoreMetersFromDb to read from the DB and restore all the services
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530219func (m *MeterMgr) RestoreMetersFromDb(cntx context.Context) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530220 // VNETS must be learnt first
221 logger.Infow(ctx, "LastMeterID on restart", log.Fields{"LastMeterID": m.LastMeterID})
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530222 ms, _ := db.GetMeters(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530223 for _, mt := range ms {
224 b, ok := mt.Value.([]byte)
225 if !ok {
226 logger.Warn(ctx, "The value type is not []byte")
227 continue
228 }
229 var meter VoltMeter
230 err := json.Unmarshal(b, &meter)
231 if err != nil {
232 logger.Warn(ctx, "Unmarshal of meter profile failed")
233 continue
234 }
235 logger.Infow(ctx, "Retrieved Meter", log.Fields{"Meter": meter.Name})
236 m.AddMeter(&meter)
237 if meter.ID > m.LastMeterID {
238 m.LastMeterID = meter.ID
239 }
240 }
241 logger.Infow(ctx, "LastMeterID on reading DB", log.Fields{"LastMeterID": m.LastMeterID})
242}
243
244// AddMeterProf to add the meter profile name as key
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530245func (va *VoltApplication) AddMeterProf(cntx context.Context, cfg VoltMeter) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530246 mm := &va.MeterMgr
247 if _, ok := mm.GetMeterByName(cfg.Name); ok {
248 logger.Warnw(ctx, "Meter profile exists", log.Fields{"Name": cfg.Name})
249 return
250 }
251
252 mm.LastMeterID++
vinokuma926cb3e2023-03-29 11:41:06 +0530253 // FIX-ME: Hardcoded the meter-id temp till meter delete is introduced
254 // Restriction: Only one meter profile should be used across all services
Naveen Sampath04696f72022-06-13 15:19:14 +0530255 // id := uint32(1) //mm.LastMeterId
256 id := mm.LastMeterID
257 cfg.ID = id
258 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530259 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530260 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
261 }
262}
263
264// UpdateMeterProf to update the meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530265func (va *VoltApplication) UpdateMeterProf(cntx context.Context, cfg VoltMeter) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530266 mm := &va.MeterMgr
267 if _, ok := mm.GetMeterByName(cfg.Name); !ok {
268 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": cfg.Name})
269 return
270 }
271 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530272 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530273 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
274 }
275}
276
277// GetMeterByProfID to get a meter based on the identities of bandwidth profile and shaper
278// profile names.
279func (m *MeterMgr) GetMeterByProfID(id uint32) (*VoltMeter, error) {
280 if mtr, ok := m.GetMeterByID(id); ok {
281 return mtr, nil
282 }
283 return nil, errors.New("Meter Missing")
284}
285
286// GetMeter to get a meter based on the identities of bandwidth profile and shaper
287// profile names.
288func (m *MeterMgr) GetMeter(meterID string) (*VoltMeter, error) {
289 if mt, ok := m.GetMeterByName(meterID); ok {
290 return mt, nil
291 }
292 return nil, errors.New("Meter Missing")
293}
294
295// DeleteFromDevice to delete meter from the device
296func (vm *VoltMeter) DeleteFromDevice(port string, device string) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530297 meter := of.NewMeter(vm.ID)
298
299 logger.Debugw(ctx, "Delete meter from device", log.Fields{"Id": vm.ID, "meter": *meter})
300 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandDel, meter); err != nil {
301 logger.Warnw(ctx, "Delete meter from device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
302 }
303}
304
305// DelMeterProf to delete meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530306func (va *VoltApplication) DelMeterProf(cntx context.Context, name string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530307 mm := &va.MeterMgr
308 if _, ok := mm.GetMeterByName(name); !ok {
309 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": name})
310 return errors.New("Meter profile doesn't exist")
311 }
312 cfg, _ := mm.GetMeterByName(name)
313 if cfg.AssociatedServices != 0 {
314 logger.Warnw(ctx, "Mismatch in submgr and vgc oeter profile service reference",
315 log.Fields{"MeterProfile": name, "serviceCount": cfg.AssociatedServices})
316 return errors.New("Service reference is not 0")
317 }
vinokuma926cb3e2023-03-29 11:41:06 +0530318 // TODO : delete from all devices
Naveen Sampath04696f72022-06-13 15:19:14 +0530319 delmeterFromDevice := func(key interface{}, value interface{}) bool {
320 device := key.(string)
321 port, _ := GetApplication().GetNniPort(device)
322 cfg.DeleteFromDevice(port, device)
323 return true
324 }
325 va.DevicesDisc.Range(delmeterFromDevice)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530326 cfg.DelFromDb(cntx)
vinokuma926cb3e2023-03-29 11:41:06 +0530327 // Delete meter from device will be invoked by caller separately
Naveen Sampath04696f72022-06-13 15:19:14 +0530328 mm.DelMeter(cfg)
329 return nil
330}