blob: 276fe992a0f980b7e09e30ad96af157fae350b1e [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 (
19 "encoding/json"
20 "errors"
Tinoj Joseph07cc5372022-07-18 22:53:51 +053021 "context"
Naveen Sampath04696f72022-06-13 15:19:14 +053022 "sync"
23
24 cntlr "voltha-go-controller/internal/pkg/controller"
25 "voltha-go-controller/database"
26 "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
75 ID uint32
76 Fir uint32
77 Air uint32
78 Eir uint32
79 BurstSize uint32
80 AssociatedServices uint32
81 Version string
82 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
165 //Set Pir & Pbs
166 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})
189 //Set Air
190 // 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
247 mm := &va.MeterMgr
248 if _, ok := mm.GetMeterByName(cfg.Name); ok {
249 logger.Warnw(ctx, "Meter profile exists", log.Fields{"Name": cfg.Name})
250 return
251 }
252
253 mm.LastMeterID++
254 //FIX-ME: Hardcoded the meter-id temp till meter delete is introduced
255 //Restriction: Only one meter profile should be used across all services
256 // id := uint32(1) //mm.LastMeterId
257 id := mm.LastMeterID
258 cfg.ID = id
259 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530260 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530261 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
262 }
263}
264
265// UpdateMeterProf to update the meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530266func (va *VoltApplication) UpdateMeterProf(cntx context.Context, cfg VoltMeter) {
Naveen Sampath04696f72022-06-13 15:19:14 +0530267 mm := &va.MeterMgr
268 if _, ok := mm.GetMeterByName(cfg.Name); !ok {
269 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": cfg.Name})
270 return
271 }
272 mm.AddMeter(&cfg)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530273 if err := cfg.WriteToDb(cntx); err != nil {
Naveen Sampath04696f72022-06-13 15:19:14 +0530274 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
275 }
276}
277
278// GetMeterByProfID to get a meter based on the identities of bandwidth profile and shaper
279// profile names.
280func (m *MeterMgr) GetMeterByProfID(id uint32) (*VoltMeter, error) {
281 if mtr, ok := m.GetMeterByID(id); ok {
282 return mtr, nil
283 }
284 return nil, errors.New("Meter Missing")
285}
286
287// GetMeter to get a meter based on the identities of bandwidth profile and shaper
288// profile names.
289func (m *MeterMgr) GetMeter(meterID string) (*VoltMeter, error) {
290 if mt, ok := m.GetMeterByName(meterID); ok {
291 return mt, nil
292 }
293 return nil, errors.New("Meter Missing")
294}
295
296// DeleteFromDevice to delete meter from the device
297func (vm *VoltMeter) DeleteFromDevice(port string, device string) {
298
299 meter := of.NewMeter(vm.ID)
300
301 logger.Debugw(ctx, "Delete meter from device", log.Fields{"Id": vm.ID, "meter": *meter})
302 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandDel, meter); err != nil {
303 logger.Warnw(ctx, "Delete meter from device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
304 }
305}
306
307// DelMeterProf to delete meter profile
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530308func (va *VoltApplication) DelMeterProf(cntx context.Context, name string) error {
Naveen Sampath04696f72022-06-13 15:19:14 +0530309 mm := &va.MeterMgr
310 if _, ok := mm.GetMeterByName(name); !ok {
311 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": name})
312 return errors.New("Meter profile doesn't exist")
313 }
314 cfg, _ := mm.GetMeterByName(name)
315 if cfg.AssociatedServices != 0 {
316 logger.Warnw(ctx, "Mismatch in submgr and vgc oeter profile service reference",
317 log.Fields{"MeterProfile": name, "serviceCount": cfg.AssociatedServices})
318 return errors.New("Service reference is not 0")
319 }
320 //TODO : delete from all devices
321 delmeterFromDevice := func(key interface{}, value interface{}) bool {
322 device := key.(string)
323 port, _ := GetApplication().GetNniPort(device)
324 cfg.DeleteFromDevice(port, device)
325 return true
326 }
327 va.DevicesDisc.Range(delmeterFromDevice)
Tinoj Joseph07cc5372022-07-18 22:53:51 +0530328 cfg.DelFromDb(cntx)
Naveen Sampath04696f72022-06-13 15:19:14 +0530329 //Delete meter from device will be invoked by caller separately
330 mm.DelMeter(cfg)
331 return nil
332}