blob: 4b5fd71e2f3e88fef33a20f0535519cb73df2571 [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"
21 "sync"
22
23 cntlr "voltha-go-controller/internal/pkg/controller"
24 "voltha-go-controller/database"
25 "voltha-go-controller/internal/pkg/of"
26 "github.com/opencord/voltha-lib-go/v7/pkg/log"
27)
28
29// VoltShaperConfig is shaper profile configuration structure
30type VoltShaperConfig struct {
31 Name string
32 BurstSize uint32
33}
34
35// VoltBwConfig is bandwidth profile configuration structure
36type VoltBwConfig struct {
37 Name string
38 Fir uint32
39 Air uint32
40 Eir uint32
41}
42
43// VoltBandwidthProf is bandwidth profile stored at VGC
44type VoltBandwidthProf struct {
45 VoltBwConfig
46}
47
48// VoltShaperProf is shaper profile stored at VGC
49type VoltShaperProf struct {
50 VoltShaperConfig
51}
52
53// VoltMeterProf is meter profile stored at VGC
54type VoltMeterProf struct {
55 VoltMeter
56}
57
58// MeterMgr structure
59type MeterMgr struct {
60 Meters sync.Map
61 MetersByID sync.Map
62 LastMeterID uint32
63}
64
65// Init to initialize MeterMgr
66func (m *MeterMgr) Init() {
67 m.LastMeterID = 0
68}
69
70// VoltMeter : A VOLT meter is a combination of BW and shaper profiles
71// The ID is generated by the VOLT application
72type VoltMeter struct {
73 Name string
74 ID uint32
75 Fir uint32
76 Air uint32
77 Eir uint32
78 BurstSize uint32
79 AssociatedServices uint32
80 Version string
81 Cir uint32
82 Cbs uint32
83 Pir uint32
84 Pbs uint32
85 Gir uint32
86 Ebs uint32
87}
88
89// WriteToDb to write a meter profile to DB
90func (vm *VoltMeter) WriteToDb() error {
91 vm.Version = database.PresentVersionMap[database.MeterPath]
92 b, err := json.Marshal(vm)
93 if err != nil {
94 return err
95 }
96 if err1 := db.PutMeter(vm.Name, string(b)); err1 != nil {
97 return err1
98 }
99 return nil
100}
101
102// DelFromDb to delete a meter profile from DB
103func (vm *VoltMeter) DelFromDb() {
104 _ = db.DelMeter(vm.Name)
105}
106
107// GetMeterByName to get meter by name
108func (m *MeterMgr) GetMeterByName(name string) (*VoltMeter, bool) {
109 meter, ok := m.Meters.Load(name)
110 logger.Infow(ctx, "Meter Obtained Name", log.Fields{"Meter": meter})
111 if ok {
112 return meter.(*VoltMeter), ok
113 }
114 return nil, ok
115}
116
117// GetMeterByID to get meter by ID
118func (m *MeterMgr) GetMeterByID(id uint32) (*VoltMeter, bool) {
119 meter, ok := m.MetersByID.Load(id)
120 logger.Infow(ctx, "Meter Obtained ID", log.Fields{"Meter": meter})
121 if ok {
122 return meter.(*VoltMeter), ok
123 }
124 return nil, ok
125}
126
127// AddMeter to add meter
128func (m *MeterMgr) AddMeter(meter *VoltMeter) {
129 m.Meters.Store(meter.Name, meter)
130 m.MetersByID.Store(meter.ID, meter)
131 logger.Infow(ctx, "Meter Added/Updated", log.Fields{"Meter": meter, "Name": meter.Name, "Id": meter.ID})
132}
133
134// DelMeter to delete meter
135func (m *MeterMgr) DelMeter(meter *VoltMeter) {
136 m.Meters.Delete(meter.Name)
137 m.MetersByID.Delete(meter.ID)
138 logger.Infow(ctx, "Meter Deleted", log.Fields{"Meter": meter, "Name": meter.Name, "Id": meter.ID})
139}
140
141// AddToDevice to add meter to the device
142func (vm *VoltMeter) AddToDevice(port string, device string, aggVM *VoltMeter) {
143 logger.Debugw(ctx, "Adding Meter To Device", log.Fields{"Id": vm.ID, "Device": device, "Port": port})
144 meter := of.NewMeter(vm.ID)
145 // meter.AddBand(vm.Air, vm.BurstSize)
146 // meter.AddBand(vm.Eir, vm.BurstSize)
147 // if aggVM != nil {
148 // meter.AddBand(aggVM.Air, aggVM.BurstSize)
149 // meter.AddBand(aggVM.Eir, aggVM.BurstSize)
150 // }
151
152 //Community VGC Impl
153
154 //Set Cir
155 if vm.Cir != 0 {
156 meter.AddBand(vm.Cir, vm.Cbs)
157 }
158
159 //Set Air to 0 if both air & gir are set
160 if vm.Air != 0 && vm.Gir != 0 {
161 vm.Air = 0
162 }
163
164 //Set Pir & Pbs
165 var pir uint32
166 var pbs uint32
167 if vm.Pir != 0 {
168 pir = vm.Pir
169 } else {
170 pir = vm.Eir + vm.Cir + vm.Gir + vm.Air
171 }
172
173 if vm.Pbs != 0 {
174 pbs = vm.Pbs
175 } else {
176 pbs = vm.Ebs + vm.Cbs
177 }
178 meter.AddBand(pir, pbs)
179
180 //Set Gir
181 if vm.Gir != 0 {
182 meter.AddBand(vm.Gir, 0)
183 }
184
185 logger.Infow(ctx, "Meter Config", log.Fields{"Cir": vm.Cir, "Air": vm.Air, "Pir": vm.Pir, "Gir": vm.Gir, "Eir": vm.Eir})
186 logger.Infow(ctx, "Meter Burst Config", log.Fields{"Cbs": vm.Cbs, "Pbs": vm.Pbs})
187 logger.Infow(ctx, "Meter Burst Oper", log.Fields{"Pir": pir, "Pbs": pbs})
188 //Set Air
189 // Air is used in place of Gir only if Gir is
190 // not present and Air is not 0
191 if vm.Air != 0 {
192 meter.AddBand(vm.Air, 0)
193 }
194
195 logger.Debug(ctx, "Total Bands are", log.Fields{"meter": *meter})
196 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandAdd, meter); err != nil {
197 logger.Warnw(ctx, "Add meter to device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
198 }
199}
200
201// AddMeterToDevice to add meter to the device
202func (m *MeterMgr) AddMeterToDevice(port string, device string, meterID uint32, aggMeterID uint32) {
203 var aggVM *VoltMeter
204 vm, err := m.GetMeterByProfID(meterID)
205 if err == nil {
206 if 0 != aggMeterID { //Assuming valid meter id will never be 0
207 if aggVM, err = m.GetMeterByProfID(aggMeterID); err != nil {
208 logger.Warnw(ctx, "Aggregated Meter not found", log.Fields{"Id": aggMeterID})
209 }
210 }
211 vm.AddToDevice(port, device, aggVM)
212 } else {
213 logger.Warnw(ctx, "Meter not found", log.Fields{"Id": meterID})
214 }
215}
216
217// RestoreMetersFromDb to read from the DB and restore all the services
218func (m *MeterMgr) RestoreMetersFromDb() {
219 // VNETS must be learnt first
220 logger.Infow(ctx, "LastMeterID on restart", log.Fields{"LastMeterID": m.LastMeterID})
221 ms, _ := db.GetMeters()
222 for _, mt := range ms {
223 b, ok := mt.Value.([]byte)
224 if !ok {
225 logger.Warn(ctx, "The value type is not []byte")
226 continue
227 }
228 var meter VoltMeter
229 err := json.Unmarshal(b, &meter)
230 if err != nil {
231 logger.Warn(ctx, "Unmarshal of meter profile failed")
232 continue
233 }
234 logger.Infow(ctx, "Retrieved Meter", log.Fields{"Meter": meter.Name})
235 m.AddMeter(&meter)
236 if meter.ID > m.LastMeterID {
237 m.LastMeterID = meter.ID
238 }
239 }
240 logger.Infow(ctx, "LastMeterID on reading DB", log.Fields{"LastMeterID": m.LastMeterID})
241}
242
243// AddMeterProf to add the meter profile name as key
244func (va *VoltApplication) AddMeterProf(cfg VoltMeter) {
245
246 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++
253 //FIX-ME: Hardcoded the meter-id temp till meter delete is introduced
254 //Restriction: Only one meter profile should be used across all services
255 // id := uint32(1) //mm.LastMeterId
256 id := mm.LastMeterID
257 cfg.ID = id
258 mm.AddMeter(&cfg)
259 if err := cfg.WriteToDb(); err != nil {
260 logger.Warnw(ctx, "MeterProf Write to DB Failed", log.Fields{"MeterConfig": cfg, "Error": err})
261 }
262}
263
264// UpdateMeterProf to update the meter profile
265func (va *VoltApplication) UpdateMeterProf(cfg VoltMeter) {
266 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)
272 if err := cfg.WriteToDb(); err != nil {
273 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) {
297
298 meter := of.NewMeter(vm.ID)
299
300 logger.Debugw(ctx, "Delete meter from device", log.Fields{"Id": vm.ID, "meter": *meter})
301 if err := cntlr.GetController().ModMeter(port, device, of.MeterCommandDel, meter); err != nil {
302 logger.Warnw(ctx, "Delete meter from device Failed", log.Fields{"Id": vm.ID, "meter": *meter, "Error": err})
303 }
304}
305
306// DelMeterProf to delete meter profile
307func (va *VoltApplication) DelMeterProf(name string) error {
308 mm := &va.MeterMgr
309 if _, ok := mm.GetMeterByName(name); !ok {
310 logger.Warnw(ctx, "Meter profile does not exist", log.Fields{"Name": name})
311 return errors.New("Meter profile doesn't exist")
312 }
313 cfg, _ := mm.GetMeterByName(name)
314 if cfg.AssociatedServices != 0 {
315 logger.Warnw(ctx, "Mismatch in submgr and vgc oeter profile service reference",
316 log.Fields{"MeterProfile": name, "serviceCount": cfg.AssociatedServices})
317 return errors.New("Service reference is not 0")
318 }
319 //TODO : delete from all devices
320 delmeterFromDevice := func(key interface{}, value interface{}) bool {
321 device := key.(string)
322 port, _ := GetApplication().GetNniPort(device)
323 cfg.DeleteFromDevice(port, device)
324 return true
325 }
326 va.DevicesDisc.Range(delmeterFromDevice)
327 cfg.DelFromDb()
328 //Delete meter from device will be invoked by caller separately
329 mm.DelMeter(cfg)
330 return nil
331}