blob: 19f7aad84c9aed78f738cc8364414ab052c3424e [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
yasin sapli5458a1c2021-06-14 22:24:38 +000023 fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
24 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Maninderdfadc982020-10-28 14:04:33 +053025 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
Kent Hagerman433a31a2020-05-20 19:04:48 -040026)
27
28// GetMeterConfig returns meters which which are used by the given flows
Gamze Abakafac8c192021-06-28 12:04:32 +000029func (agent *LogicalAgent) GetMeterConfig(ctx context.Context, flows []*ofp.OfpFlowStats) (map[uint32]*ofp.OfpMeterConfig, error) {
Kent Hagerman433a31a2020-05-20 19:04:48 -040030 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
khenaidoo1a0d6222021-06-30 16:48:44 -040035 meterHandle, have := agent.meterLoader.Lock(flowMeterID)
Kent Hagerman433a31a2020-05-20 19:04:48 -040036 if !have {
Rohan Agrawal31f21802020-06-12 05:38:46 +000037 logger.Errorw(ctx, "Meter-referred-by-flow-is-not-found-in-logicaldevice",
Kent Hagerman433a31a2020-05-20 19:04:48 -040038 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
Rohan Agrawal31f21802020-06-12 05:38:46 +000044 logger.Debugw(ctx, "Found meter in logical device", log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})
Kent Hagerman433a31a2020-05-20 19:04:48 -040045
46 meterHandle.Unlock()
47 }
48 }
49 }
Rohan Agrawal31f21802020-06-12 05:38:46 +000050 logger.Debugw(ctx, "meter-bands-for-flows", log.Fields{"flows": len(flows), "meters": metersConfig})
Kent Hagerman433a31a2020-05-20 19:04:48 -040051 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)
Rohan Agrawal31f21802020-06-12 05:38:46 +000058 logger.Debugw(ctx, "Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
Kent Hagerman433a31a2020-05-20 19:04:48 -040059 if meterID == 0 {
Rohan Agrawal31f21802020-06-12 05:38:46 +000060 logger.Debugw(ctx, "No-meter-present-in-the-flow", log.Fields{"flow": *flow})
Kent Hagerman433a31a2020-05-20 19:04:48 -040061 return true
62 }
63
64 if flowCommand != ofp.OfpFlowModCommand_OFPFC_ADD && flowCommand != ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
65 return true
66 }
67
khenaidoo1a0d6222021-06-30 16:48:44 -040068 meterHandle, have := agent.meterLoader.Lock(meterID)
Kent Hagerman433a31a2020-05-20 19:04:48 -040069 if !have {
Rohan Agrawal31f21802020-06-12 05:38:46 +000070 logger.Debugw(ctx, "Meter-is-not-present-in-logical-device", log.Fields{"meterID": meterID})
Kent Hagerman433a31a2020-05-20 19:04:48 -040071 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 {
divyadesaicb8b59d2020-08-18 09:55:47 +000097 logger.Debugw(ctx, "unable-to-update-meter-in-db", log.Fields{"logical-device-id": agent.logicalDeviceID, "meterID": meterID})
Kent Hagerman433a31a2020-05-20 19:04:48 -040098 return false
99 }
100
Rohan Agrawal31f21802020-06-12 05:38:46 +0000101 logger.Debugw(ctx, "updated-meter-flow-stats", log.Fields{"meterId": meterID})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400102 return true
103}