blob: dc44fda153584f51b8cfadee97f038d49b3ee26c [file] [log] [blame]
Kent Hagerman3136fbd2020-05-14 10:30:45 -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"
Kent Hagerman3136fbd2020-05-14 10:30:45 -040022
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 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
28)
29
Kent Hagerman433a31a2020-05-20 19:04:48 -040030// listLogicalDeviceMeters returns logical device meters
31func (agent *LogicalAgent) listLogicalDeviceMeters() map[uint32]*ofp.OfpMeterEntry {
32 meterIDs := agent.meterLoader.List()
33 meters := make(map[uint32]*ofp.OfpMeterEntry, len(meterIDs))
34 for meterID := range meterIDs {
35 if meterHandle, have := agent.meterLoader.Lock(meterID); have {
36 meters[meterID] = meterHandle.GetReadOnly()
37 meterHandle.Unlock()
38 }
39 }
40 return meters
41}
42
Kent Hagerman3136fbd2020-05-14 10:30:45 -040043// updateMeterTable updates the meter table of that logical device
44func (agent *LogicalAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
45 logger.Debug("updateMeterTable")
46 if meterMod == nil {
47 return nil
48 }
49 switch meterMod.GetCommand() {
50 case ofp.OfpMeterModCommand_OFPMC_ADD:
51 return agent.meterAdd(ctx, meterMod)
52 case ofp.OfpMeterModCommand_OFPMC_DELETE:
53 return agent.meterDelete(ctx, meterMod)
54 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
55 return agent.meterModify(ctx, meterMod)
56 }
57 return status.Errorf(codes.Internal,
58 "unhandled-command: lDeviceId:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
59}
60
61func (agent *LogicalAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
62 logger.Debugw("meterAdd", log.Fields{"metermod": *meterMod})
63 if meterMod == nil {
64 return nil
65 }
66
67 meterEntry := fu.MeterEntryFromMeterMod(meterMod)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040068
Kent Hagerman433a31a2020-05-20 19:04:48 -040069 meterHandle, created, err := agent.meterLoader.LockOrCreate(ctx, meterEntry)
70 if err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -040071 return err
72 }
Kent Hagerman433a31a2020-05-20 19:04:48 -040073 defer meterHandle.Unlock()
Kent Hagerman3136fbd2020-05-14 10:30:45 -040074
Kent Hagerman433a31a2020-05-20 19:04:48 -040075 if created {
76 logger.Debugw("Meter-added-successfully", log.Fields{"Added-meter": meterEntry})
77 } else {
78 logger.Infow("Meter-already-exists", log.Fields{"meter": *meterMod})
79 }
Kent Hagerman3136fbd2020-05-14 10:30:45 -040080 return nil
81}
82
83func (agent *LogicalAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
84 logger.Debug("meterDelete", log.Fields{"meterMod": *meterMod})
85 if meterMod == nil {
86 return nil
87 }
Kent Hagerman433a31a2020-05-20 19:04:48 -040088
89 meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
90 if !have {
Kent Hagerman3136fbd2020-05-14 10:30:45 -040091 logger.Warnw("meter-not-found", log.Fields{"meterID": meterMod.MeterId})
Kent Hagerman433a31a2020-05-20 19:04:48 -040092 return nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -040093 }
Kent Hagerman433a31a2020-05-20 19:04:48 -040094 defer meterHandle.Unlock()
95
96 //TODO: A meter lock is held here while flow lock(s) are acquired, if this is done in opposite order anywhere
97 // there's potential for deadlock.
98 if err := agent.deleteFlowsHavingMeter(ctx, meterMod.MeterId); err != nil {
99 return err
100 }
101
102 if err := meterHandle.Delete(ctx); err != nil {
103 return err
104 }
105
106 logger.Debugw("meterDelete-success", log.Fields{"meterID": meterMod.MeterId})
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400107 return nil
108}
109
110func (agent *LogicalAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
111 logger.Debug("meterModify")
112 if meterMod == nil {
113 return nil
114 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400115
116 meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
117 if !have {
118 return fmt.Errorf("no-meter-to-modify: %d", meterMod.MeterId)
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400119 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400120 defer meterHandle.Unlock()
121
122 oldMeter := meterHandle.GetReadOnly()
123 newMeter := fu.MeterEntryFromMeterMod(meterMod)
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400124 newMeter.Stats.FlowCount = oldMeter.Stats.FlowCount
125
Kent Hagerman433a31a2020-05-20 19:04:48 -0400126 if err := meterHandle.Update(ctx, newMeter); err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400127 return err
128 }
129 logger.Debugw("replaced-with-new-meter", log.Fields{"oldMeter": oldMeter, "newMeter": newMeter})
130 return nil
131}