blob: f186ef6d405500b60b1319b17b9d7ceed3ed82db [file] [log] [blame]
alshabibe27055b2015-07-09 21:43:10 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
alshabibe27055b2015-07-09 21:43:10 -07003 *
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.provider.of.meter.impl;
18
alshabib1d2bc402015-07-31 17:04:11 -070019
alshabibc7911792015-07-30 17:55:30 -070020import com.google.common.cache.Cache;
21import com.google.common.cache.CacheBuilder;
22import com.google.common.cache.RemovalCause;
23import com.google.common.cache.RemovalNotification;
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -080024import com.google.common.collect.ImmutableSet;
alshabibc7911792015-07-30 17:55:30 -070025import com.google.common.collect.Maps;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070026import org.osgi.service.component.annotations.Activate;
27import org.osgi.service.component.annotations.Component;
28import org.osgi.service.component.annotations.Deactivate;
29import org.osgi.service.component.annotations.Reference;
30import org.osgi.service.component.annotations.ReferenceCardinality;
Charles Chanb9cfc3a2017-08-04 17:50:21 -070031import org.onlab.util.ItemNotFoundException;
alshabib7bb05012015-08-05 10:15:09 -070032import org.onosproject.core.CoreService;
Charles Chana59f9b762017-07-30 18:09:44 -070033import org.onosproject.net.driver.Driver;
34import org.onosproject.net.driver.DriverService;
alshabib10c810b2015-08-18 16:59:04 -070035import org.onosproject.net.meter.Band;
36import org.onosproject.net.meter.DefaultBand;
37import org.onosproject.net.meter.DefaultMeter;
38import org.onosproject.net.meter.Meter;
39import org.onosproject.net.meter.MeterFailReason;
Jordi Ortizaa8de492016-12-01 00:21:36 +010040import org.onosproject.net.meter.MeterFeatures;
alshabib58fe6dc2015-08-19 17:16:13 -070041import org.onosproject.net.meter.MeterId;
alshabib10c810b2015-08-18 16:59:04 -070042import org.onosproject.net.meter.MeterOperation;
43import org.onosproject.net.meter.MeterOperations;
44import org.onosproject.net.meter.MeterProvider;
45import org.onosproject.net.meter.MeterProviderRegistry;
46import org.onosproject.net.meter.MeterProviderService;
47import org.onosproject.net.meter.MeterState;
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -080048import org.onosproject.net.Device;
alshabib7bb05012015-08-05 10:15:09 -070049import org.onosproject.net.DeviceId;
alshabibe27055b2015-07-09 21:43:10 -070050import org.onosproject.net.provider.AbstractProvider;
51import org.onosproject.net.provider.ProviderId;
alshabibc7911792015-07-30 17:55:30 -070052import org.onosproject.openflow.controller.Dpid;
alshabibe27055b2015-07-09 21:43:10 -070053import org.onosproject.openflow.controller.OpenFlowController;
alshabibc7911792015-07-30 17:55:30 -070054import org.onosproject.openflow.controller.OpenFlowEventListener;
55import org.onosproject.openflow.controller.OpenFlowSwitch;
56import org.onosproject.openflow.controller.OpenFlowSwitchListener;
57import org.onosproject.openflow.controller.RoleState;
Jordi Ortizaa8de492016-12-01 00:21:36 +010058import org.onosproject.provider.of.meter.util.MeterFeaturesBuilder;
alshabibc7911792015-07-30 17:55:30 -070059import org.projectfloodlight.openflow.protocol.OFErrorMsg;
60import org.projectfloodlight.openflow.protocol.OFErrorType;
61import org.projectfloodlight.openflow.protocol.OFMessage;
alshabib7bb05012015-08-05 10:15:09 -070062import org.projectfloodlight.openflow.protocol.OFMeterBandStats;
63import org.projectfloodlight.openflow.protocol.OFMeterConfigStatsReply;
Jordi Ortizaa8de492016-12-01 00:21:36 +010064import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
alshabib7bb05012015-08-05 10:15:09 -070065import org.projectfloodlight.openflow.protocol.OFMeterStats;
66import org.projectfloodlight.openflow.protocol.OFMeterStatsReply;
alshabibc7911792015-07-30 17:55:30 -070067import org.projectfloodlight.openflow.protocol.OFPortStatus;
68import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib7bb05012015-08-05 10:15:09 -070069import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabibc7911792015-07-30 17:55:30 -070070import org.projectfloodlight.openflow.protocol.OFVersion;
71import org.projectfloodlight.openflow.protocol.errormsg.OFMeterModFailedErrorMsg;
alshabibe27055b2015-07-09 21:43:10 -070072import org.slf4j.Logger;
73
alshabib7bb05012015-08-05 10:15:09 -070074import java.util.Collection;
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -080075import java.util.EnumSet;
alshabib7bb05012015-08-05 10:15:09 -070076import java.util.List;
alshabibc7911792015-07-30 17:55:30 -070077import java.util.Map;
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -080078import java.util.Set;
alshabibc7911792015-07-30 17:55:30 -070079import java.util.concurrent.TimeUnit;
80import java.util.concurrent.atomic.AtomicLong;
alshabib7bb05012015-08-05 10:15:09 -070081import java.util.stream.Collectors;
Niraj Dubey47bde9f2019-10-07 18:03:57 +053082import java.util.concurrent.ConcurrentHashMap;
alshabibc7911792015-07-30 17:55:30 -070083
Jordi Ortizaa8de492016-12-01 00:21:36 +010084import static org.onosproject.net.DeviceId.deviceId;
85import static org.onosproject.openflow.controller.Dpid.uri;
alshabibe27055b2015-07-09 21:43:10 -070086import static org.slf4j.LoggerFactory.getLogger;
87
88/**
89 * Provider which uses an OpenFlow controller to handle meters.
90 */
alshabib58fe6dc2015-08-19 17:16:13 -070091@Component(immediate = true, enabled = true)
alshabibe27055b2015-07-09 21:43:10 -070092public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider {
93
94 private final Logger log = getLogger(getClass());
95
Ray Milkeyd84f89b2018-08-17 14:54:17 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibe27055b2015-07-09 21:43:10 -070097 protected OpenFlowController controller;
98
Ray Milkeyd84f89b2018-08-17 14:54:17 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibc7911792015-07-30 17:55:30 -0700100 protected MeterProviderRegistry providerRegistry;
101
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabib7bb05012015-08-05 10:15:09 -0700103 protected CoreService coreService;
104
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chana59f9b762017-07-30 18:09:44 -0700106 protected DriverService driverService;
107
alshabibc7911792015-07-30 17:55:30 -0700108 private MeterProviderService providerService;
109
110 private static final AtomicLong XID_COUNTER = new AtomicLong(1);
111
112 static final int POLL_INTERVAL = 10;
113 static final long TIMEOUT = 30;
114
alshabib7bb05012015-08-05 10:15:09 -0700115 private Cache<Long, MeterOperation> pendingOperations;
alshabibc7911792015-07-30 17:55:30 -0700116
117
118 private InternalMeterListener listener = new InternalMeterListener();
Niraj Dubey47bde9f2019-10-07 18:03:57 +0530119 private Map<Dpid, MeterStatsCollector> collectors = new ConcurrentHashMap<>();
alshabibe27055b2015-07-09 21:43:10 -0700120
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800121 private static final Set<Device.Type> NO_METER_SUPPORT =
122 ImmutableSet.copyOf(EnumSet.of(Device.Type.ROADM,
123 Device.Type.ROADM_OTN,
124 Device.Type.FIBER_SWITCH,
Andrea Campanella1c24fb92018-12-20 16:43:59 +0100125 Device.Type.OTN,
126 Device.Type.OLS,
127 Device.Type.TERMINAL_DEVICE));
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800128
alshabibe27055b2015-07-09 21:43:10 -0700129 /**
130 * Creates a OpenFlow meter provider.
131 */
132 public OpenFlowMeterProvider() {
133 super(new ProviderId("of", "org.onosproject.provider.meter"));
134 }
alshabibbc371962015-07-09 22:26:21 -0700135
alshabibc7911792015-07-30 17:55:30 -0700136 @Activate
137 public void activate() {
138 providerService = providerRegistry.register(this);
139
140 pendingOperations = CacheBuilder.newBuilder()
141 .expireAfterWrite(TIMEOUT, TimeUnit.SECONDS)
alshabib7bb05012015-08-05 10:15:09 -0700142 .removalListener((RemovalNotification<Long, MeterOperation> notification) -> {
alshabibc7911792015-07-30 17:55:30 -0700143 if (notification.getCause() == RemovalCause.EXPIRED) {
Gamze Abakaa34469f2019-04-19 08:30:16 +0000144 log.debug("Expired on meter provider. Meter key {} and operation {}",
145 notification.getKey(), notification.getValue());
alshabibc7911792015-07-30 17:55:30 -0700146 providerService.meterOperationFailed(notification.getValue(),
147 MeterFailReason.TIMEOUT);
148 }
149 }).build();
150
151 controller.addEventListener(listener);
152 controller.addListener(listener);
153
154 controller.getSwitches().forEach((sw -> createStatsCollection(sw)));
155 }
156
157 @Deactivate
158 public void deactivate() {
159 providerRegistry.unregister(this);
Charles Chanecfdfb72015-11-24 19:05:50 -0800160 collectors.values().forEach(MeterStatsCollector::stop);
161 collectors.clear();
alshabibc7911792015-07-30 17:55:30 -0700162 controller.removeEventListener(listener);
163 controller.removeListener(listener);
164 providerService = null;
165 }
166
alshabibbc371962015-07-09 22:26:21 -0700167 @Override
168 public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
alshabibc7911792015-07-30 17:55:30 -0700169 Dpid dpid = Dpid.dpid(deviceId.uri());
170 OpenFlowSwitch sw = controller.getSwitch(dpid);
171 if (sw == null) {
172 log.error("Unknown device {}", deviceId);
173 meterOps.operations().forEach(op ->
174 providerService.meterOperationFailed(op,
175 MeterFailReason.UNKNOWN_DEVICE)
176 );
177 return;
178 }
alshabibbc371962015-07-09 22:26:21 -0700179
alshabibc7911792015-07-30 17:55:30 -0700180 meterOps.operations().forEach(op -> performOperation(sw, op));
alshabibbc371962015-07-09 22:26:21 -0700181 }
182
183 @Override
184 public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
alshabibc7911792015-07-30 17:55:30 -0700185 Dpid dpid = Dpid.dpid(deviceId.uri());
186 OpenFlowSwitch sw = controller.getSwitch(dpid);
187 if (sw == null) {
188 log.error("Unknown device {}", deviceId);
189 providerService.meterOperationFailed(meterOp,
190 MeterFailReason.UNKNOWN_DEVICE);
191 return;
192 }
alshabibbc371962015-07-09 22:26:21 -0700193
alshabib7bb05012015-08-05 10:15:09 -0700194 performOperation(sw, meterOp);
195
Jordi Ortiz9fe79a22017-04-25 12:57:11 +0200196 if (meterOp.type().equals(MeterOperation.Type.REMOVE)) {
197 forceMeterStats(deviceId);
198 }
199
200 }
201
202 private void forceMeterStats(DeviceId deviceId) {
203 Dpid dpid = Dpid.dpid(deviceId.uri());
204 OpenFlowSwitch sw = controller.getSwitch(dpid);
205
206 MeterStatsCollector once = new MeterStatsCollector(sw, 1);
Palash Kalaf95c38b2017-05-15 23:52:48 +0900207 once.sendMeterStatisticRequest();
Jordi Ortiz9fe79a22017-04-25 12:57:11 +0200208
alshabibbc371962015-07-09 22:26:21 -0700209 }
alshabibc7911792015-07-30 17:55:30 -0700210
211 private void performOperation(OpenFlowSwitch sw, MeterOperation op) {
212
alshabibc7911792015-07-30 17:55:30 -0700213 Meter meter = op.meter();
214 MeterModBuilder builder = MeterModBuilder.builder(meter.id().id(), sw.factory());
215 if (meter.isBurst()) {
216 builder.burst();
217 }
218 builder.withBands(meter.bands())
219 .withId(meter.id())
220 .withRateUnit(meter.unit());
221
222 switch (op.type()) {
223 case ADD:
Gamze Abakaa34469f2019-04-19 08:30:16 +0000224 pendingOperations.put(op.meter().id().id(), op);
alshabibc7911792015-07-30 17:55:30 -0700225 sw.sendMsg(builder.add());
226 break;
227 case REMOVE:
228 sw.sendMsg(builder.remove());
229 break;
230 case MODIFY:
Gamze Abakaa34469f2019-04-19 08:30:16 +0000231 pendingOperations.put(op.meter().id().id(), op);
alshabibc7911792015-07-30 17:55:30 -0700232 sw.sendMsg(builder.modify());
233 break;
234 default:
235 log.warn("Unknown Meter command {}; not sending anything",
236 op.type());
237 providerService.meterOperationFailed(op,
238 MeterFailReason.UNKNOWN_COMMAND);
239 }
240
241 }
242
243 private void createStatsCollection(OpenFlowSwitch sw) {
Madan Jampani84382b92016-06-22 08:26:49 -0700244 if (sw != null && isMeterSupported(sw)) {
alshabibc7911792015-07-30 17:55:30 -0700245 MeterStatsCollector msc = new MeterStatsCollector(sw, POLL_INTERVAL);
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700246 stopCollectorIfNeeded(collectors.put(new Dpid(sw.getId()), msc));
Palash Kalaa439afe2017-05-16 14:53:15 +0900247 msc.start();
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700248 }
249 }
250
251 private void stopCollectorIfNeeded(MeterStatsCollector collector) {
252 if (collector != null) {
253 collector.stop();
alshabibc7911792015-07-30 17:55:30 -0700254 }
255 }
256
Charles Chan14967c22015-12-07 11:11:50 -0800257 // TODO: ONOS-3546 Support per device enabling/disabling via network config
alshabibc7911792015-07-30 17:55:30 -0700258 private boolean isMeterSupported(OpenFlowSwitch sw) {
259 if (sw.factory().getVersion() == OFVersion.OF_10 ||
260 sw.factory().getVersion() == OFVersion.OF_11 ||
Charles Chan14967c22015-12-07 11:11:50 -0800261 sw.factory().getVersion() == OFVersion.OF_12 ||
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800262 NO_METER_SUPPORT.contains(sw.deviceType()) ||
Charles Chana59f9b762017-07-30 18:09:44 -0700263 !isMeterCapable(sw)) {
sdn77b5cb82018-05-23 18:51:27 +0900264 log.debug("{} does not support Meter.\n", sw.getDpid());
alshabibc7911792015-07-30 17:55:30 -0700265 return false;
266 }
267
268 return true;
269 }
270
Charles Chana59f9b762017-07-30 18:09:44 -0700271 /**
272 * Determine whether the given switch is meter-capable.
273 *
274 * @param sw switch
275 * @return the boolean value of meterCapable property, or true if it is not configured.
276 */
277 private boolean isMeterCapable(OpenFlowSwitch sw) {
Charles Chanb9cfc3a2017-08-04 17:50:21 -0700278 Driver driver;
279
280 try {
281 driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(sw.getDpid())));
282 } catch (ItemNotFoundException e) {
283 driver = driverService.getDriver(sw.manufacturerDescription(), sw.hardwareDescription(),
284 sw.softwareDescription());
285 }
286
Charles Chana59f9b762017-07-30 18:09:44 -0700287 String isMeterCapable = driver.getProperty(METER_CAPABLE);
288 return isMeterCapable == null || Boolean.parseBoolean(isMeterCapable);
289 }
290
alshabibc7911792015-07-30 17:55:30 -0700291 private void pushMeterStats(Dpid dpid, OFStatsReply msg) {
alshabib7bb05012015-08-05 10:15:09 -0700292 DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
alshabibc7911792015-07-30 17:55:30 -0700293
alshabib7bb05012015-08-05 10:15:09 -0700294 if (msg.getStatsType() == OFStatsType.METER) {
295 OFMeterStatsReply reply = (OFMeterStatsReply) msg;
296 Collection<Meter> meters = buildMeters(deviceId, reply.getEntries());
297 //TODO do meter accounting here.
298 providerService.pushMeterMetrics(deviceId, meters);
299 } else if (msg.getStatsType() == OFStatsType.METER_CONFIG) {
300 OFMeterConfigStatsReply reply = (OFMeterConfigStatsReply) msg;
301 // FIXME: Map<Long, Meter> meters = collectMeters(deviceId, reply);
302 }
303
304 }
305
Jordi Ortizaa8de492016-12-01 00:21:36 +0100306 private MeterFeatures buildMeterFeatures(Dpid dpid, OFMeterFeatures mf) {
307 if (mf != null) {
308 return new MeterFeaturesBuilder(mf, deviceId(uri(dpid)))
309 .build();
310 } else {
311 // This will usually happen for OpenFlow devices prior to 1.3
312 return MeterFeaturesBuilder.noMeterFeatures(deviceId(uri(dpid)));
313 }
314 }
315
316 private void pushMeterFeatures(Dpid dpid, OFMeterFeatures meterFeatures) {
317 providerService.pushMeterFeatures(deviceId(uri(dpid)),
318 buildMeterFeatures(dpid, meterFeatures));
319 }
320
321 private void destroyMeterFeatures(Dpid dpid) {
322 providerService.deleteMeterFeatures(deviceId(uri(dpid)));
323 }
324
alshabib7bb05012015-08-05 10:15:09 -0700325 private Map<Long, Meter> collectMeters(DeviceId deviceId,
326 OFMeterConfigStatsReply reply) {
327 return Maps.newHashMap();
328 //TODO: Needs a fix to be applied to loxi MeterConfig stat is incorrect
329 }
330
331 private Collection<Meter> buildMeters(DeviceId deviceId,
332 List<OFMeterStats> entries) {
333 return entries.stream().map(stat -> {
334 DefaultMeter.Builder builder = DefaultMeter.builder();
335 Collection<Band> bands = buildBands(stat.getBandStats());
336 builder.forDevice(deviceId)
alshabib58fe6dc2015-08-19 17:16:13 -0700337 .withId(MeterId.meterId(stat.getMeterId()))
alshabib7bb05012015-08-05 10:15:09 -0700338 //FIXME: need to encode appId in meter id, but that makes
339 // things a little annoying for debugging
340 .fromApp(coreService.getAppId("org.onosproject.core"))
341 .withBands(bands);
342 DefaultMeter meter = builder.build();
343 meter.setState(MeterState.ADDED);
344 meter.setLife(stat.getDurationSec());
345 meter.setProcessedBytes(stat.getByteInCount().getValue());
346 meter.setProcessedPackets(stat.getPacketInCount().getValue());
Cem Türker3baff672017-10-12 15:09:01 +0300347 if (stat.getVersion().getWireVersion() < OFVersion.OF_15.getWireVersion()) {
348 meter.setReferenceCount(stat.getFlowCount());
349 }
alshabib7bb05012015-08-05 10:15:09 -0700350 // marks the meter as seen on the dataplane
351 pendingOperations.invalidate(stat.getMeterId());
352 return meter;
353 }).collect(Collectors.toSet());
354 }
355
356 private Collection<Band> buildBands(List<OFMeterBandStats> bandStats) {
357 return bandStats.stream().map(stat -> {
Jordi Ortizaf75c132017-06-22 16:06:36 +0200358 DefaultBand band = ((DefaultBand.Builder) DefaultBand.builder().ofType(DefaultBand.Type.DROP)).build();
alshabib7bb05012015-08-05 10:15:09 -0700359 band.setBytes(stat.getByteBandCount().getValue());
360 band.setPackets(stat.getPacketBandCount().getValue());
361 return band;
Jordi Ortizaf75c132017-06-22 16:06:36 +0200362 }).collect(Collectors.toList());
alshabibc7911792015-07-30 17:55:30 -0700363 }
364
365 private void signalMeterError(OFMeterModFailedErrorMsg meterError,
366 MeterOperation op) {
367 switch (meterError.getCode()) {
368 case UNKNOWN:
369 providerService.meterOperationFailed(op,
370 MeterFailReason.UNKNOWN_DEVICE);
371 break;
372 case METER_EXISTS:
373 providerService.meterOperationFailed(op,
374 MeterFailReason.EXISTING_METER);
375 break;
376 case INVALID_METER:
377 providerService.meterOperationFailed(op,
378 MeterFailReason.INVALID_METER);
379 break;
380 case UNKNOWN_METER:
381 providerService.meterOperationFailed(op,
382 MeterFailReason.UNKNOWN);
383 break;
384 case BAD_COMMAND:
385 providerService.meterOperationFailed(op,
386 MeterFailReason.UNKNOWN_COMMAND);
387 break;
388 case BAD_FLAGS:
389 providerService.meterOperationFailed(op,
390 MeterFailReason.UNKNOWN_FLAGS);
391 break;
392 case BAD_RATE:
393 providerService.meterOperationFailed(op,
394 MeterFailReason.BAD_RATE);
395 break;
396 case BAD_BURST:
397 providerService.meterOperationFailed(op,
398 MeterFailReason.BAD_BURST);
399 break;
400 case BAD_BAND:
401 providerService.meterOperationFailed(op,
402 MeterFailReason.BAD_BAND);
403 break;
404 case BAD_BAND_VALUE:
405 providerService.meterOperationFailed(op,
406 MeterFailReason.BAD_BAND_VALUE);
407 break;
408 case OUT_OF_METERS:
409 providerService.meterOperationFailed(op,
410 MeterFailReason.OUT_OF_METERS);
411 break;
412 case OUT_OF_BANDS:
413 providerService.meterOperationFailed(op,
414 MeterFailReason.OUT_OF_BANDS);
415 break;
416 default:
417 providerService.meterOperationFailed(op,
418 MeterFailReason.UNKNOWN);
419 }
420 }
421
422 private class InternalMeterListener
423 implements OpenFlowSwitchListener, OpenFlowEventListener {
424 @Override
425 public void handleMessage(Dpid dpid, OFMessage msg) {
426 switch (msg.getType()) {
427 case STATS_REPLY:
428 pushMeterStats(dpid, (OFStatsReply) msg);
429 break;
430 case ERROR:
431 OFErrorMsg error = (OFErrorMsg) msg;
432 if (error.getErrType() == OFErrorType.METER_MOD_FAILED) {
433 MeterOperation op =
434 pendingOperations.getIfPresent(error.getXid());
435 pendingOperations.invalidate(error.getXid());
436 if (op == null) {
437 log.warn("Unknown Meter operation failed {}", error);
438 } else {
439 OFMeterModFailedErrorMsg meterError =
440 (OFMeterModFailedErrorMsg) error;
441 signalMeterError(meterError, op);
442 }
443 }
444 break;
445 default:
446 break;
447 }
448
449 }
450
451 @Override
452 public void switchAdded(Dpid dpid) {
453 createStatsCollection(controller.getSwitch(dpid));
Jordi Ortizaa8de492016-12-01 00:21:36 +0100454 pushMeterFeatures(dpid, controller.getSwitch(dpid).getMeterFeatures());
alshabibc7911792015-07-30 17:55:30 -0700455 }
456
457 @Override
458 public void switchRemoved(Dpid dpid) {
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700459 stopCollectorIfNeeded(collectors.remove(dpid));
Jordi Ortizaa8de492016-12-01 00:21:36 +0100460 destroyMeterFeatures(dpid);
alshabibc7911792015-07-30 17:55:30 -0700461 }
462
463 @Override
464 public void switchChanged(Dpid dpid) {
465
466 }
467
468 @Override
469 public void portChanged(Dpid dpid, OFPortStatus status) {
470
471 }
472
473 @Override
474 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
475
476 }
477 }
478
479
480
alshabibe27055b2015-07-09 21:43:10 -0700481}