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