blob: 91e2f64531ae5bdb3d1e171b014b9d76d5c01a57 [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;
alshabibc7911792015-07-30 17:55:30 -070082
Jordi Ortizaa8de492016-12-01 00:21:36 +010083import static org.onosproject.net.DeviceId.deviceId;
84import static org.onosproject.openflow.controller.Dpid.uri;
alshabibe27055b2015-07-09 21:43:10 -070085import static org.slf4j.LoggerFactory.getLogger;
86
87/**
88 * Provider which uses an OpenFlow controller to handle meters.
89 */
alshabib58fe6dc2015-08-19 17:16:13 -070090@Component(immediate = true, enabled = true)
alshabibe27055b2015-07-09 21:43:10 -070091public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider {
92
93 private final Logger log = getLogger(getClass());
94
Ray Milkeyd84f89b2018-08-17 14:54:17 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibe27055b2015-07-09 21:43:10 -070096 protected OpenFlowController controller;
97
Ray Milkeyd84f89b2018-08-17 14:54:17 -070098 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabibc7911792015-07-30 17:55:30 -070099 protected MeterProviderRegistry providerRegistry;
100
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY)
alshabib7bb05012015-08-05 10:15:09 -0700102 protected CoreService coreService;
103
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Charles Chana59f9b762017-07-30 18:09:44 -0700105 protected DriverService driverService;
106
alshabibc7911792015-07-30 17:55:30 -0700107 private MeterProviderService providerService;
108
109 private static final AtomicLong XID_COUNTER = new AtomicLong(1);
110
111 static final int POLL_INTERVAL = 10;
112 static final long TIMEOUT = 30;
113
alshabib7bb05012015-08-05 10:15:09 -0700114 private Cache<Long, MeterOperation> pendingOperations;
alshabibc7911792015-07-30 17:55:30 -0700115
116
117 private InternalMeterListener listener = new InternalMeterListener();
118 private Map<Dpid, MeterStatsCollector> collectors = Maps.newHashMap();
alshabibe27055b2015-07-09 21:43:10 -0700119
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800120 private static final Set<Device.Type> NO_METER_SUPPORT =
121 ImmutableSet.copyOf(EnumSet.of(Device.Type.ROADM,
122 Device.Type.ROADM_OTN,
123 Device.Type.FIBER_SWITCH,
Andrea Campanella1c24fb92018-12-20 16:43:59 +0100124 Device.Type.OTN,
125 Device.Type.OLS,
126 Device.Type.TERMINAL_DEVICE));
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800127
alshabibe27055b2015-07-09 21:43:10 -0700128 /**
129 * Creates a OpenFlow meter provider.
130 */
131 public OpenFlowMeterProvider() {
132 super(new ProviderId("of", "org.onosproject.provider.meter"));
133 }
alshabibbc371962015-07-09 22:26:21 -0700134
alshabibc7911792015-07-30 17:55:30 -0700135 @Activate
136 public void activate() {
137 providerService = providerRegistry.register(this);
138
139 pendingOperations = CacheBuilder.newBuilder()
140 .expireAfterWrite(TIMEOUT, TimeUnit.SECONDS)
alshabib7bb05012015-08-05 10:15:09 -0700141 .removalListener((RemovalNotification<Long, MeterOperation> notification) -> {
alshabibc7911792015-07-30 17:55:30 -0700142 if (notification.getCause() == RemovalCause.EXPIRED) {
Gamze Abakaa34469f2019-04-19 08:30:16 +0000143 log.debug("Expired on meter provider. Meter key {} and operation {}",
144 notification.getKey(), notification.getValue());
alshabibc7911792015-07-30 17:55:30 -0700145 providerService.meterOperationFailed(notification.getValue(),
146 MeterFailReason.TIMEOUT);
147 }
148 }).build();
149
150 controller.addEventListener(listener);
151 controller.addListener(listener);
152
153 controller.getSwitches().forEach((sw -> createStatsCollection(sw)));
154 }
155
156 @Deactivate
157 public void deactivate() {
158 providerRegistry.unregister(this);
Charles Chanecfdfb72015-11-24 19:05:50 -0800159 collectors.values().forEach(MeterStatsCollector::stop);
160 collectors.clear();
alshabibc7911792015-07-30 17:55:30 -0700161 controller.removeEventListener(listener);
162 controller.removeListener(listener);
163 providerService = null;
164 }
165
alshabibbc371962015-07-09 22:26:21 -0700166 @Override
167 public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
alshabibc7911792015-07-30 17:55:30 -0700168 Dpid dpid = Dpid.dpid(deviceId.uri());
169 OpenFlowSwitch sw = controller.getSwitch(dpid);
170 if (sw == null) {
171 log.error("Unknown device {}", deviceId);
172 meterOps.operations().forEach(op ->
173 providerService.meterOperationFailed(op,
174 MeterFailReason.UNKNOWN_DEVICE)
175 );
176 return;
177 }
alshabibbc371962015-07-09 22:26:21 -0700178
alshabibc7911792015-07-30 17:55:30 -0700179 meterOps.operations().forEach(op -> performOperation(sw, op));
alshabibbc371962015-07-09 22:26:21 -0700180 }
181
182 @Override
183 public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
alshabibc7911792015-07-30 17:55:30 -0700184 Dpid dpid = Dpid.dpid(deviceId.uri());
185 OpenFlowSwitch sw = controller.getSwitch(dpid);
186 if (sw == null) {
187 log.error("Unknown device {}", deviceId);
188 providerService.meterOperationFailed(meterOp,
189 MeterFailReason.UNKNOWN_DEVICE);
190 return;
191 }
alshabibbc371962015-07-09 22:26:21 -0700192
alshabib7bb05012015-08-05 10:15:09 -0700193 performOperation(sw, meterOp);
194
Jordi Ortiz9fe79a22017-04-25 12:57:11 +0200195 if (meterOp.type().equals(MeterOperation.Type.REMOVE)) {
196 forceMeterStats(deviceId);
197 }
198
199 }
200
201 private void forceMeterStats(DeviceId deviceId) {
202 Dpid dpid = Dpid.dpid(deviceId.uri());
203 OpenFlowSwitch sw = controller.getSwitch(dpid);
204
205 MeterStatsCollector once = new MeterStatsCollector(sw, 1);
Palash Kalaf95c38b2017-05-15 23:52:48 +0900206 once.sendMeterStatisticRequest();
Jordi Ortiz9fe79a22017-04-25 12:57:11 +0200207
alshabibbc371962015-07-09 22:26:21 -0700208 }
alshabibc7911792015-07-30 17:55:30 -0700209
210 private void performOperation(OpenFlowSwitch sw, MeterOperation op) {
211
alshabibc7911792015-07-30 17:55:30 -0700212 Meter meter = op.meter();
213 MeterModBuilder builder = MeterModBuilder.builder(meter.id().id(), sw.factory());
214 if (meter.isBurst()) {
215 builder.burst();
216 }
217 builder.withBands(meter.bands())
218 .withId(meter.id())
219 .withRateUnit(meter.unit());
220
221 switch (op.type()) {
222 case ADD:
Gamze Abakaa34469f2019-04-19 08:30:16 +0000223 pendingOperations.put(op.meter().id().id(), op);
alshabibc7911792015-07-30 17:55:30 -0700224 sw.sendMsg(builder.add());
225 break;
226 case REMOVE:
227 sw.sendMsg(builder.remove());
228 break;
229 case MODIFY:
Gamze Abakaa34469f2019-04-19 08:30:16 +0000230 pendingOperations.put(op.meter().id().id(), op);
alshabibc7911792015-07-30 17:55:30 -0700231 sw.sendMsg(builder.modify());
232 break;
233 default:
234 log.warn("Unknown Meter command {}; not sending anything",
235 op.type());
236 providerService.meterOperationFailed(op,
237 MeterFailReason.UNKNOWN_COMMAND);
238 }
239
240 }
241
242 private void createStatsCollection(OpenFlowSwitch sw) {
Madan Jampani84382b92016-06-22 08:26:49 -0700243 if (sw != null && isMeterSupported(sw)) {
alshabibc7911792015-07-30 17:55:30 -0700244 MeterStatsCollector msc = new MeterStatsCollector(sw, POLL_INTERVAL);
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700245 stopCollectorIfNeeded(collectors.put(new Dpid(sw.getId()), msc));
Palash Kalaa439afe2017-05-16 14:53:15 +0900246 msc.start();
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700247 }
248 }
249
250 private void stopCollectorIfNeeded(MeterStatsCollector collector) {
251 if (collector != null) {
252 collector.stop();
alshabibc7911792015-07-30 17:55:30 -0700253 }
254 }
255
Charles Chan14967c22015-12-07 11:11:50 -0800256 // TODO: ONOS-3546 Support per device enabling/disabling via network config
alshabibc7911792015-07-30 17:55:30 -0700257 private boolean isMeterSupported(OpenFlowSwitch sw) {
258 if (sw.factory().getVersion() == OFVersion.OF_10 ||
259 sw.factory().getVersion() == OFVersion.OF_11 ||
Charles Chan14967c22015-12-07 11:11:50 -0800260 sw.factory().getVersion() == OFVersion.OF_12 ||
Yuta HIGUCHI67f2cca2017-01-19 19:31:58 -0800261 NO_METER_SUPPORT.contains(sw.deviceType()) ||
Charles Chana59f9b762017-07-30 18:09:44 -0700262 !isMeterCapable(sw)) {
sdn77b5cb82018-05-23 18:51:27 +0900263 log.debug("{} does not support Meter.\n", sw.getDpid());
alshabibc7911792015-07-30 17:55:30 -0700264 return false;
265 }
266
267 return true;
268 }
269
Charles Chana59f9b762017-07-30 18:09:44 -0700270 /**
271 * Determine whether the given switch is meter-capable.
272 *
273 * @param sw switch
274 * @return the boolean value of meterCapable property, or true if it is not configured.
275 */
276 private boolean isMeterCapable(OpenFlowSwitch sw) {
Charles Chanb9cfc3a2017-08-04 17:50:21 -0700277 Driver driver;
278
279 try {
280 driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(sw.getDpid())));
281 } catch (ItemNotFoundException e) {
282 driver = driverService.getDriver(sw.manufacturerDescription(), sw.hardwareDescription(),
283 sw.softwareDescription());
284 }
285
Charles Chana59f9b762017-07-30 18:09:44 -0700286 String isMeterCapable = driver.getProperty(METER_CAPABLE);
287 return isMeterCapable == null || Boolean.parseBoolean(isMeterCapable);
288 }
289
alshabibc7911792015-07-30 17:55:30 -0700290 private void pushMeterStats(Dpid dpid, OFStatsReply msg) {
alshabib7bb05012015-08-05 10:15:09 -0700291 DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
alshabibc7911792015-07-30 17:55:30 -0700292
alshabib7bb05012015-08-05 10:15:09 -0700293 if (msg.getStatsType() == OFStatsType.METER) {
294 OFMeterStatsReply reply = (OFMeterStatsReply) msg;
295 Collection<Meter> meters = buildMeters(deviceId, reply.getEntries());
296 //TODO do meter accounting here.
297 providerService.pushMeterMetrics(deviceId, meters);
298 } else if (msg.getStatsType() == OFStatsType.METER_CONFIG) {
299 OFMeterConfigStatsReply reply = (OFMeterConfigStatsReply) msg;
300 // FIXME: Map<Long, Meter> meters = collectMeters(deviceId, reply);
301 }
302
303 }
304
Jordi Ortizaa8de492016-12-01 00:21:36 +0100305 private MeterFeatures buildMeterFeatures(Dpid dpid, OFMeterFeatures mf) {
306 if (mf != null) {
307 return new MeterFeaturesBuilder(mf, deviceId(uri(dpid)))
308 .build();
309 } else {
310 // This will usually happen for OpenFlow devices prior to 1.3
311 return MeterFeaturesBuilder.noMeterFeatures(deviceId(uri(dpid)));
312 }
313 }
314
315 private void pushMeterFeatures(Dpid dpid, OFMeterFeatures meterFeatures) {
316 providerService.pushMeterFeatures(deviceId(uri(dpid)),
317 buildMeterFeatures(dpid, meterFeatures));
318 }
319
320 private void destroyMeterFeatures(Dpid dpid) {
321 providerService.deleteMeterFeatures(deviceId(uri(dpid)));
322 }
323
alshabib7bb05012015-08-05 10:15:09 -0700324 private Map<Long, Meter> collectMeters(DeviceId deviceId,
325 OFMeterConfigStatsReply reply) {
326 return Maps.newHashMap();
327 //TODO: Needs a fix to be applied to loxi MeterConfig stat is incorrect
328 }
329
330 private Collection<Meter> buildMeters(DeviceId deviceId,
331 List<OFMeterStats> entries) {
332 return entries.stream().map(stat -> {
333 DefaultMeter.Builder builder = DefaultMeter.builder();
334 Collection<Band> bands = buildBands(stat.getBandStats());
335 builder.forDevice(deviceId)
alshabib58fe6dc2015-08-19 17:16:13 -0700336 .withId(MeterId.meterId(stat.getMeterId()))
alshabib7bb05012015-08-05 10:15:09 -0700337 //FIXME: need to encode appId in meter id, but that makes
338 // things a little annoying for debugging
339 .fromApp(coreService.getAppId("org.onosproject.core"))
340 .withBands(bands);
341 DefaultMeter meter = builder.build();
342 meter.setState(MeterState.ADDED);
343 meter.setLife(stat.getDurationSec());
344 meter.setProcessedBytes(stat.getByteInCount().getValue());
345 meter.setProcessedPackets(stat.getPacketInCount().getValue());
Cem Türker3baff672017-10-12 15:09:01 +0300346 if (stat.getVersion().getWireVersion() < OFVersion.OF_15.getWireVersion()) {
347 meter.setReferenceCount(stat.getFlowCount());
348 }
alshabib7bb05012015-08-05 10:15:09 -0700349 // marks the meter as seen on the dataplane
350 pendingOperations.invalidate(stat.getMeterId());
351 return meter;
352 }).collect(Collectors.toSet());
353 }
354
355 private Collection<Band> buildBands(List<OFMeterBandStats> bandStats) {
356 return bandStats.stream().map(stat -> {
Jordi Ortizaf75c132017-06-22 16:06:36 +0200357 DefaultBand band = ((DefaultBand.Builder) DefaultBand.builder().ofType(DefaultBand.Type.DROP)).build();
alshabib7bb05012015-08-05 10:15:09 -0700358 band.setBytes(stat.getByteBandCount().getValue());
359 band.setPackets(stat.getPacketBandCount().getValue());
360 return band;
Jordi Ortizaf75c132017-06-22 16:06:36 +0200361 }).collect(Collectors.toList());
alshabibc7911792015-07-30 17:55:30 -0700362 }
363
364 private void signalMeterError(OFMeterModFailedErrorMsg meterError,
365 MeterOperation op) {
366 switch (meterError.getCode()) {
367 case UNKNOWN:
368 providerService.meterOperationFailed(op,
369 MeterFailReason.UNKNOWN_DEVICE);
370 break;
371 case METER_EXISTS:
372 providerService.meterOperationFailed(op,
373 MeterFailReason.EXISTING_METER);
374 break;
375 case INVALID_METER:
376 providerService.meterOperationFailed(op,
377 MeterFailReason.INVALID_METER);
378 break;
379 case UNKNOWN_METER:
380 providerService.meterOperationFailed(op,
381 MeterFailReason.UNKNOWN);
382 break;
383 case BAD_COMMAND:
384 providerService.meterOperationFailed(op,
385 MeterFailReason.UNKNOWN_COMMAND);
386 break;
387 case BAD_FLAGS:
388 providerService.meterOperationFailed(op,
389 MeterFailReason.UNKNOWN_FLAGS);
390 break;
391 case BAD_RATE:
392 providerService.meterOperationFailed(op,
393 MeterFailReason.BAD_RATE);
394 break;
395 case BAD_BURST:
396 providerService.meterOperationFailed(op,
397 MeterFailReason.BAD_BURST);
398 break;
399 case BAD_BAND:
400 providerService.meterOperationFailed(op,
401 MeterFailReason.BAD_BAND);
402 break;
403 case BAD_BAND_VALUE:
404 providerService.meterOperationFailed(op,
405 MeterFailReason.BAD_BAND_VALUE);
406 break;
407 case OUT_OF_METERS:
408 providerService.meterOperationFailed(op,
409 MeterFailReason.OUT_OF_METERS);
410 break;
411 case OUT_OF_BANDS:
412 providerService.meterOperationFailed(op,
413 MeterFailReason.OUT_OF_BANDS);
414 break;
415 default:
416 providerService.meterOperationFailed(op,
417 MeterFailReason.UNKNOWN);
418 }
419 }
420
421 private class InternalMeterListener
422 implements OpenFlowSwitchListener, OpenFlowEventListener {
423 @Override
424 public void handleMessage(Dpid dpid, OFMessage msg) {
425 switch (msg.getType()) {
426 case STATS_REPLY:
427 pushMeterStats(dpid, (OFStatsReply) msg);
428 break;
429 case ERROR:
430 OFErrorMsg error = (OFErrorMsg) msg;
431 if (error.getErrType() == OFErrorType.METER_MOD_FAILED) {
432 MeterOperation op =
433 pendingOperations.getIfPresent(error.getXid());
434 pendingOperations.invalidate(error.getXid());
435 if (op == null) {
436 log.warn("Unknown Meter operation failed {}", error);
437 } else {
438 OFMeterModFailedErrorMsg meterError =
439 (OFMeterModFailedErrorMsg) error;
440 signalMeterError(meterError, op);
441 }
442 }
443 break;
444 default:
445 break;
446 }
447
448 }
449
450 @Override
451 public void switchAdded(Dpid dpid) {
452 createStatsCollection(controller.getSwitch(dpid));
Jordi Ortizaa8de492016-12-01 00:21:36 +0100453 pushMeterFeatures(dpid, controller.getSwitch(dpid).getMeterFeatures());
alshabibc7911792015-07-30 17:55:30 -0700454 }
455
456 @Override
457 public void switchRemoved(Dpid dpid) {
Thomas Vachuskaa394b952016-06-14 15:02:09 -0700458 stopCollectorIfNeeded(collectors.remove(dpid));
Jordi Ortizaa8de492016-12-01 00:21:36 +0100459 destroyMeterFeatures(dpid);
alshabibc7911792015-07-30 17:55:30 -0700460 }
461
462 @Override
463 public void switchChanged(Dpid dpid) {
464
465 }
466
467 @Override
468 public void portChanged(Dpid dpid, OFPortStatus status) {
469
470 }
471
472 @Override
473 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
474
475 }
476 }
477
478
479
alshabibe27055b2015-07-09 21:43:10 -0700480}