Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package device |
| 18 | |
| 19 | import ( |
| 20 | "context" |
| 21 | "fmt" |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 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 | "google.golang.org/grpc/codes" |
| 27 | "google.golang.org/grpc/status" |
| 28 | ) |
| 29 | |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 30 | // listLogicalDeviceMeters returns logical device meters |
| 31 | func (agent *LogicalAgent) listLogicalDeviceMeters() map[uint32]*ofp.OfpMeterEntry { |
Kent Hagerman | fa9d6d4 | 2020-05-25 11:49:40 -0400 | [diff] [blame] | 32 | meterIDs := agent.meterLoader.ListIDs() |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 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 Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 43 | // updateMeterTable updates the meter table of that logical device |
| 44 | func (agent *LogicalAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 45 | logger.Debug(ctx, "updateMeterTable") |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 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 | |
| 61 | func (agent *LogicalAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 62 | logger.Debugw(ctx, "meterAdd", log.Fields{"metermod": *meterMod}) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 63 | if meterMod == nil { |
| 64 | return nil |
| 65 | } |
| 66 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 67 | meterEntry := fu.MeterEntryFromMeterMod(ctx, meterMod) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 68 | |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 69 | meterHandle, created, err := agent.meterLoader.LockOrCreate(ctx, meterEntry) |
| 70 | if err != nil { |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 71 | return err |
| 72 | } |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 73 | defer meterHandle.Unlock() |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 74 | |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 75 | if created { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 76 | logger.Debugw(ctx, "Meter-added-successfully", log.Fields{"Added-meter": meterEntry}) |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 77 | } else { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 78 | logger.Infow(ctx, "Meter-already-exists", log.Fields{"meter": *meterMod}) |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 79 | } |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 80 | return nil |
| 81 | } |
| 82 | |
| 83 | func (agent *LogicalAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 84 | logger.Debug(ctx, "meterDelete", log.Fields{"meterMod": *meterMod}) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 85 | if meterMod == nil { |
| 86 | return nil |
| 87 | } |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 88 | |
| 89 | meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId) |
| 90 | if !have { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 91 | logger.Warnw(ctx, "meter-not-found", log.Fields{"meterID": meterMod.MeterId}) |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 92 | return nil |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 93 | } |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 94 | 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 | |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 106 | logger.Debugw(ctx, "meterDelete-success", log.Fields{"meterID": meterMod.MeterId}) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 107 | return nil |
| 108 | } |
| 109 | |
| 110 | func (agent *LogicalAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error { |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 111 | logger.Debug(ctx, "meterModify") |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 112 | if meterMod == nil { |
| 113 | return nil |
| 114 | } |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 115 | |
| 116 | meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId) |
| 117 | if !have { |
| 118 | return fmt.Errorf("no-meter-to-modify: %d", meterMod.MeterId) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 119 | } |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 120 | defer meterHandle.Unlock() |
| 121 | |
| 122 | oldMeter := meterHandle.GetReadOnly() |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 123 | newMeter := fu.MeterEntryFromMeterMod(ctx, meterMod) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 124 | newMeter.Stats.FlowCount = oldMeter.Stats.FlowCount |
| 125 | |
Kent Hagerman | 433a31a | 2020-05-20 19:04:48 -0400 | [diff] [blame] | 126 | if err := meterHandle.Update(ctx, newMeter); err != nil { |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 127 | return err |
| 128 | } |
Rohan Agrawal | 31f2180 | 2020-06-12 05:38:46 +0000 | [diff] [blame] | 129 | logger.Debugw(ctx, "replaced-with-new-meter", log.Fields{"oldMeter": oldMeter, "newMeter": newMeter}) |
Kent Hagerman | 3136fbd | 2020-05-14 10:30:45 -0400 | [diff] [blame] | 130 | return nil |
| 131 | } |