blob: 26462add11934425902063ede6f8768bf507b543 [file] [log] [blame]
yoonseond6ba9a62017-01-30 11:48:07 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
yoonseond6ba9a62017-01-30 11:48:07 -08003 *
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 org.onosproject.incubator.net.virtual.impl.provider;
18
19import com.google.common.cache.Cache;
20import com.google.common.cache.CacheBuilder;
21import com.google.common.cache.RemovalCause;
22import com.google.common.cache.RemovalNotification;
yoonseond6ba9a62017-01-30 11:48:07 -080023import org.onosproject.core.IdGenerator;
24import org.onosproject.incubator.net.virtual.NetworkId;
25import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
26import org.onosproject.incubator.net.virtual.provider.VirtualMeterProvider;
27import org.onosproject.incubator.net.virtual.provider.VirtualMeterProviderService;
28import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.meter.Meter;
31import org.onosproject.net.meter.MeterEvent;
32import org.onosproject.net.meter.MeterFailReason;
33import org.onosproject.net.meter.MeterListener;
34import org.onosproject.net.meter.MeterOperation;
35import org.onosproject.net.meter.MeterOperations;
36import org.onosproject.net.meter.MeterService;
37import org.onosproject.net.provider.ProviderId;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070038import org.osgi.service.component.annotations.Activate;
39import org.osgi.service.component.annotations.Component;
40import org.osgi.service.component.annotations.Deactivate;
41import org.osgi.service.component.annotations.Reference;
42import org.osgi.service.component.annotations.ReferenceCardinality;
yoonseond6ba9a62017-01-30 11:48:07 -080043import org.slf4j.Logger;
44
45import java.util.concurrent.TimeUnit;
46import java.util.concurrent.atomic.AtomicLong;
47
48import static org.slf4j.LoggerFactory.getLogger;
49
50/**
51 * Provider to handle meters for virtual networks.
52 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070053@Component(service = VirtualMeterProvider.class)
yoonseond6ba9a62017-01-30 11:48:07 -080054public class DefaultVirtualMeterProvider extends AbstractVirtualProvider
55 implements VirtualMeterProvider {
56
57 private final Logger log = getLogger(getClass());
58
59 static final long TIMEOUT = 30;
60
Ray Milkeyd84f89b2018-08-17 14:54:17 -070061 @Reference(cardinality = ReferenceCardinality.MANDATORY)
yoonseond6ba9a62017-01-30 11:48:07 -080062 protected VirtualProviderRegistryService providerRegistryService;
63
Ray Milkeyd84f89b2018-08-17 14:54:17 -070064 @Reference(cardinality = ReferenceCardinality.MANDATORY)
yoonseond6ba9a62017-01-30 11:48:07 -080065 protected MeterService meterService;
66
67 private MeterListener internalMeterListener;
68 private Cache<Long, VirtualMeterOperation> pendingOperations;
69 private IdGenerator idGenerator;
70
71 @Activate
72 public void activate() {
73 providerRegistryService.registerProvider(this);
74 internalMeterListener = new InternalMeterListener();
75
76 idGenerator = getIdGenerator();
77
78 pendingOperations = CacheBuilder.newBuilder()
79 .expireAfterWrite(TIMEOUT, TimeUnit.SECONDS)
80 .removalListener(
81 (RemovalNotification<Long, VirtualMeterOperation>
82 notification) -> {
83 if (notification.getCause() == RemovalCause.EXPIRED) {
84 NetworkId networkId = notification.getValue().networkId();
85 MeterOperation op = notification.getValue().operation();
86
87 VirtualMeterProviderService providerService =
88 (VirtualMeterProviderService) providerRegistryService
89 .getProviderService(networkId,
90 VirtualMeterProvider.class);
91
92 providerService.meterOperationFailed(op,
93 MeterFailReason.TIMEOUT);
94 }
95 }).build();
96
97 meterService.addListener(internalMeterListener);
98
99 log.info("Started");
100 }
101
102 @Deactivate
103 public void deactivate() {
104 meterService.removeListener(internalMeterListener);
105 providerRegistryService.unregisterProvider(this);
106 }
107
108 /**
109 * Creates a provider with the identifier.
110 */
111 public DefaultVirtualMeterProvider() {
112 super(new ProviderId("vnet-meter",
113 "org.onosproject.virtual.vnet-meter"));
114 }
115
116 @Override
117 public void performMeterOperation(NetworkId networkId, DeviceId deviceId,
118 MeterOperations meterOps) {
119 meterOps.operations().forEach(op -> performOperation(networkId, deviceId, op));
120 }
121
122 @Override
123 public void performMeterOperation(NetworkId networkId, DeviceId deviceId,
124 MeterOperation meterOp) {
125 performOperation(networkId, deviceId, meterOp);
126 }
127
128 private void performOperation(NetworkId networkId, DeviceId deviceId,
129 MeterOperation op) {
130
131 VirtualMeterOperation vOp = new VirtualMeterOperation(networkId, op);
132 pendingOperations.put(idGenerator.getNewId(), vOp);
133
134 switch (op.type()) {
135 case ADD:
136 //TODO: devirtualize + submit
137 break;
138 case REMOVE:
139 //TODO: devirtualize + withdraw
140 break;
141 case MODIFY:
142 //TODO: devitualize + withdraw and submit
143 break;
144 default:
145 log.warn("Unknown Meter command {}; not sending anything",
146 op.type());
147 VirtualMeterProviderService providerService =
148 (VirtualMeterProviderService) providerRegistryService
149 .getProviderService(networkId,
150 VirtualMeterProvider.class);
151 providerService.meterOperationFailed(op,
152 MeterFailReason.UNKNOWN_COMMAND);
153 }
154
155 }
156
157 /**
158 * De-virtualizes a meter operation.
159 * It takes a virtual meter operation, and translate it to a physical meter operation.
160 *
161 * @param networkId a virtual network identifier
162 * @param deviceId a virtual network device identifier
163 * @param meterOps a meter operation to be de-virtualized
164 * @return de-virtualized meter operation
165 */
166 private VirtualMeterOperation devirtualize(NetworkId networkId,
167 DeviceId deviceId,
168 MeterOperation meterOps) {
169 return null;
170 }
171
172 /**
173 * Virtualizes meter.
174 * This translates meter events for virtual networks before delivering them.
175 *
176 * @param meter
177 * @return
178 */
179 private Meter virtualize(Meter meter) {
180 return null;
181 }
182
183
184 private class InternalMeterListener implements MeterListener {
185 @Override
186 public void event(MeterEvent event) {
187 //TODO: virtualize + notify event to meter provider service
188 //Is it enough to enable virtual network provider?
189 switch (event.type()) {
190 case METER_ADD_REQ:
191 break;
192 case METER_REM_REQ:
193 break;
Jordi Ortize0d42ac2017-07-14 14:46:07 +0200194 case METER_ADDED:
195 break;
196 case METER_REMOVED:
197 break;
yoonseond6ba9a62017-01-30 11:48:07 -0800198 default:
199 log.warn("Unknown meter event {}", event.type());
200 }
201 }
202 }
203
204 /**
205 * A class to hold a network identifier and a meter operation.
206 * This class is designed to be used only in virtual network meter provider.
207 */
208 private final class VirtualMeterOperation {
209 private NetworkId networkId;
210 private MeterOperation op;
211
212 private VirtualMeterOperation(NetworkId networkId, MeterOperation op) {
213 this.networkId = networkId;
214 this.op = op;
215 }
216
217 private NetworkId networkId() {
218 return networkId;
219 }
220
221 private MeterOperation operation() {
222 return this.op;
223 }
224 }
225
226 /**
227 * A class to hold a network identifier and a meter.
228 * This class is designed to be used in only virtual network meter provider.
229 */
230 private final class VirtualMeter {
231 private NetworkId networkId;
232 private Meter meter;
233
234 private VirtualMeter(NetworkId networkId, Meter meter) {
235 this.networkId = networkId;
236 this.meter = meter;
237 }
238
239 private NetworkId networkId() {
240 return this.networkId;
241 }
242
243 private Meter meter() {
244 return this.meter;
245 }
246 }
247
248 /**
249 * Id generator for virtual meters to guarantee the uniqueness of its identifier
250 * among multiple virtual network meters.
251 *
252 * @return an ID generator
253 */
254 private IdGenerator getIdGenerator() {
255 return new IdGenerator() {
256 private AtomicLong counter = new AtomicLong(0);
257
258 @Override
259 public long getNewId() {
260 return counter.getAndIncrement();
261 }
262 };
263 }
264}