blob: d6e949acef1b38b90b1c81e35236dfb1ecba4004 [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
khenaidood948f772021-08-11 17:49:24 -040023 fu "github.com/opencord/voltha-lib-go/v7/pkg/flows"
24 "github.com/opencord/voltha-lib-go/v7/pkg/log"
25 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
Kent Hagerman3136fbd2020-05-14 10:30:45 -040026 "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
khenaidoo1a0d6222021-06-30 16:48:44 -040031func (agent *LogicalAgent) listLogicalDeviceMeters(ctx context.Context) map[uint32]*ofp.OfpMeterEntry {
32 meterIDs := agent.meterLoader.ListIDs()
Kent Hagerman433a31a2020-05-20 19:04:48 -040033 meters := make(map[uint32]*ofp.OfpMeterEntry, len(meterIDs))
34 for meterID := range meterIDs {
khenaidoo1a0d6222021-06-30 16:48:44 -040035 if meterHandle, have := agent.meterLoader.Lock(meterID); have {
Kent Hagerman433a31a2020-05-20 19:04:48 -040036 meters[meterID] = meterHandle.GetReadOnly()
37 meterHandle.Unlock()
38 }
39 }
khenaidoo1a0d6222021-06-30 16:48:44 -040040 logger.Debugw(ctx, "list-logical-device-meters", log.Fields{"logical-device-id": agent.logicalDeviceID, "num-meters": len(meters)})
Kent Hagerman433a31a2020-05-20 19:04:48 -040041 return meters
42}
43
Kent Hagerman3136fbd2020-05-14 10:30:45 -040044// updateMeterTable updates the meter table of that logical device
45func (agent *LogicalAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +000046 logger.Debug(ctx, "updateMeterTable")
Kent Hagerman3136fbd2020-05-14 10:30:45 -040047 if meterMod == nil {
48 return nil
49 }
Girish Gowdrad821e4d2021-12-08 15:23:52 +053050 // This lock is necessary to ensure that logical-device-delete and meter operations are synchronized.
51 // It was observed during tests that while meter cleanup was happening as part of logical-device delete,
52 // ONOS was re-adding meters which became stale entries on the KV store.
53 // It might look like a costly operation to lock the logical-device-agent for every meter operation,
54 // but in practicality we have only handful number of meter profiles for a given deployment so we do
55 // not expect too many meter operations.
56 // We do not need such mechanism for flows, since flows are not stored on the KV store (it is only cached).
57 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
58 return err
59 }
60 defer agent.requestQueue.RequestComplete()
61
Girish Gowdrad821e4d2021-12-08 15:23:52 +053062 if agent.stopped {
Girish Gowdra06a0ce22021-12-14 11:09:10 +053063 logger.Warnw(ctx, "logical-device-already-stopped-not-handling-meter", log.Fields{"logical-device-id": agent.logicalDeviceID})
64 return nil
65 } else if _, err := agent.ldeviceMgr.getLogicalDeviceFromModel(ctx, agent.logicalDeviceID); err != nil {
66 logger.Warnw(ctx, "logical-device-already-removed-not-handling-meter", log.Fields{"logical-device-id": agent.logicalDeviceID})
Girish Gowdrad821e4d2021-12-08 15:23:52 +053067 return nil
68 }
69
Kent Hagerman3136fbd2020-05-14 10:30:45 -040070 switch meterMod.GetCommand() {
71 case ofp.OfpMeterModCommand_OFPMC_ADD:
72 return agent.meterAdd(ctx, meterMod)
73 case ofp.OfpMeterModCommand_OFPMC_DELETE:
74 return agent.meterDelete(ctx, meterMod)
75 case ofp.OfpMeterModCommand_OFPMC_MODIFY:
76 return agent.meterModify(ctx, meterMod)
77 }
78 return status.Errorf(codes.Internal,
divyadesaicb8b59d2020-08-18 09:55:47 +000079 "unhandled-command: logical-device-id:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
Kent Hagerman3136fbd2020-05-14 10:30:45 -040080}
81
82func (agent *LogicalAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Kent Hagerman3136fbd2020-05-14 10:30:45 -040083 if meterMod == nil {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +030084 logger.Errorw(ctx, "failed-meterAdd-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -040085 return nil
86 }
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +030087 logger.Debugw(ctx, "meterAdd", log.Fields{"metermod": *meterMod, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -040088
Rohan Agrawal31f21802020-06-12 05:38:46 +000089 meterEntry := fu.MeterEntryFromMeterMod(ctx, meterMod)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040090
khenaidoo1a0d6222021-06-30 16:48:44 -040091 meterHandle, created, err := agent.meterLoader.LockOrCreate(ctx, meterEntry)
Kent Hagerman433a31a2020-05-20 19:04:48 -040092 if err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -040093 return err
94 }
Kent Hagerman433a31a2020-05-20 19:04:48 -040095 defer meterHandle.Unlock()
Kent Hagerman3136fbd2020-05-14 10:30:45 -040096
Kent Hagerman433a31a2020-05-20 19:04:48 -040097 if created {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +030098 logger.Debugw(ctx, "Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman433a31a2020-05-20 19:04:48 -040099 } else {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300100 logger.Infow(ctx, "Meter-already-exists", log.Fields{"meter": *meterMod, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400101 }
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400102 return nil
103}
104
105func (agent *LogicalAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400106 if meterMod == nil {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300107 logger.Errorw(ctx, "failed-meterDelete-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400108 return nil
109 }
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300110 logger.Debug(ctx, "meterDelete", log.Fields{"meterMod": *meterMod, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400111
khenaidoo1a0d6222021-06-30 16:48:44 -0400112 meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400113 if !have {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300114 logger.Warnw(ctx, "meter-not-found", log.Fields{"meterID": meterMod.MeterId, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman433a31a2020-05-20 19:04:48 -0400115 return nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400116 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400117 defer meterHandle.Unlock()
118
119 //TODO: A meter lock is held here while flow lock(s) are acquired, if this is done in opposite order anywhere
120 // there's potential for deadlock.
121 if err := agent.deleteFlowsHavingMeter(ctx, meterMod.MeterId); err != nil {
122 return err
123 }
124
125 if err := meterHandle.Delete(ctx); err != nil {
126 return err
127 }
128
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300129 logger.Debugw(ctx, "meterDelete-success", log.Fields{"meterID": meterMod.MeterId, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400130 return nil
131}
132
133func (agent *LogicalAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000134 logger.Debug(ctx, "meterModify")
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400135 if meterMod == nil {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300136 logger.Errorw(ctx, "failed-meterModify-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400137 return nil
138 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400139
khenaidoo1a0d6222021-06-30 16:48:44 -0400140 meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
Kent Hagerman433a31a2020-05-20 19:04:48 -0400141 if !have {
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300142 return fmt.Errorf("no-meter-to-modify: %d, logical-device-id: %s", meterMod.MeterId, agent.logicalDeviceID)
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400143 }
Kent Hagerman433a31a2020-05-20 19:04:48 -0400144 defer meterHandle.Unlock()
145
146 oldMeter := meterHandle.GetReadOnly()
Rohan Agrawal31f21802020-06-12 05:38:46 +0000147 newMeter := fu.MeterEntryFromMeterMod(ctx, meterMod)
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400148 newMeter.Stats.FlowCount = oldMeter.Stats.FlowCount
149
Kent Hagerman433a31a2020-05-20 19:04:48 -0400150 if err := meterHandle.Update(ctx, newMeter); err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400151 return err
152 }
Andrey Pozolotin34dd63f2021-05-31 21:26:40 +0300153 logger.Debugw(ctx, "replaced-with-new-meter", log.Fields{"oldMeter": oldMeter, "newMeter": newMeter, "logical-device-id": agent.logicalDeviceID})
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400154 return nil
155}