blob: fc0956838e11c479ee4a8b5e671a87a48997a4dd [file] [log] [blame]
Kent Hagerman433a31a2020-05-20 19:04:48 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package device
18
19import (
20 "context"
21 "fmt"
22
23 fu "github.com/opencord/voltha-lib-go/v3/pkg/flows"
24 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
26)
27
28// GetMeterConfig returns meters which which are used by the given flows
29func (agent *LogicalAgent) GetMeterConfig(flows map[uint64]*ofp.OfpFlowStats) (map[uint32]*ofp.OfpMeterConfig, error) {
30 metersConfig := make(map[uint32]*ofp.OfpMeterConfig)
31 for _, flow := range flows {
32 if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 {
33 if _, have := metersConfig[flowMeterID]; !have {
34 // Meter is present in the flow, Get from logical device
35 meterHandle, have := agent.meterLoader.Lock(flowMeterID)
36 if !have {
37 logger.Errorw("Meter-referred-by-flow-is-not-found-in-logicaldevice",
38 log.Fields{"meterID": flowMeterID, "Available-meters": metersConfig, "flow": *flow})
39 return nil, fmt.Errorf("Meter-referred-by-flow-is-not-found-in-logicaldevice.MeterId-%d", flowMeterID)
40 }
41
42 meter := meterHandle.GetReadOnly()
43 metersConfig[flowMeterID] = meter.Config
44 logger.Debugw("Found meter in logical device", log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
45
46 meterHandle.Unlock()
47 }
48 }
49 }
50 logger.Debugw("meter-bands-for-flows", log.Fields{"flows": len(flows), "meters": metersConfig})
51 return metersConfig, nil
52}
53
54// updateFlowCountOfMeterStats updates the number of flows associated with this meter
55func (agent *LogicalAgent) updateFlowCountOfMeterStats(ctx context.Context, modCommand *ofp.OfpFlowMod, flow *ofp.OfpFlowStats, revertUpdate bool) bool {
56 flowCommand := modCommand.GetCommand()
57 meterID := fu.GetMeterIdFromFlow(flow)
58 logger.Debugw("Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
59 if meterID == 0 {
60 logger.Debugw("No-meter-present-in-the-flow", log.Fields{"flow": *flow})
61 return true
62 }
63
64 if flowCommand != ofp.OfpFlowModCommand_OFPFC_ADD && flowCommand != ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
65 return true
66 }
67
68 meterHandle, have := agent.meterLoader.Lock(meterID)
69 if !have {
70 logger.Debugw("Meter-is-not-present-in-logical-device", log.Fields{"meterID": meterID})
71 return true
72 }
73 defer meterHandle.Unlock()
74
75 oldMeter := meterHandle.GetReadOnly()
76 // avoiding using proto.Clone by only copying what have changed (this assumes that the oldMeter will never be modified)
77 newStats := *oldMeter.Stats
78 if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
79 if revertUpdate {
80 newStats.FlowCount--
81 } else {
82 newStats.FlowCount++
83 }
84 } else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
85 if revertUpdate {
86 newStats.FlowCount++
87 } else {
88 newStats.FlowCount--
89 }
90 }
91
92 newMeter := &ofp.OfpMeterEntry{
93 Config: oldMeter.Config,
94 Stats: &newStats,
95 }
96 if err := meterHandle.Update(ctx, newMeter); err != nil {
97 logger.Debugw("unable-to-update-meter-in-db", log.Fields{"logicalDevice": agent.logicalDeviceID, "meterID": meterID})
98 return false
99 }
100
101 logger.Debugw("updated-meter-flow-stats", log.Fields{"meterId": meterID})
102 return true
103}