Dusan Pajin

Configurable Port Stats Collection interval

Change-Id: I4999338ecf1c608f93b66ba979126b2a5deda165
......@@ -30,5 +30,10 @@
<packaging>bundle</packaging>
<description>ONOS OpenFlow protocol device provider</description>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
</dependencies>
</project>
......
......@@ -19,12 +19,16 @@ import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
......@@ -52,6 +56,7 @@ import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.RoleState;
import org.osgi.service.component.ComponentContext;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
......@@ -73,10 +78,13 @@ import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.Port.Type.COPPER;
import static org.onosproject.net.Port.Type.FIBER;
......@@ -100,12 +108,18 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpenFlowController controller;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService cfgService;
private DeviceProviderService providerService;
private final InternalDeviceProvider listener = new InternalDeviceProvider();
// TODO: We need to make the poll interval configurable.
static final int POLL_INTERVAL = 5;
@Property(name = "PortStatsPollFrequency", intValue = POLL_INTERVAL,
label = "Frequency (in seconds) for polling switch Port statistics")
private int portStatsPollFrequency = POLL_INTERVAL;
private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap();
......@@ -117,7 +131,8 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
@Activate
public void activate() {
public void activate(ComponentContext context) {
cfgService.registerProperties(getClass());
providerService = providerRegistry.register(this);
controller.addListener(listener);
controller.addEventListener(listener);
......@@ -130,7 +145,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
// disconnect to trigger switch-add later
sw.disconnectSwitch();
}
PortStatsCollector psc = new PortStatsCollector(sw, POLL_INTERVAL);
PortStatsCollector psc = new PortStatsCollector(sw, portStatsPollFrequency);
psc.start();
collectors.put(new Dpid(sw.getId()), psc);
}
......@@ -138,7 +153,8 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
@Deactivate
public void deactivate() {
public void deactivate(ComponentContext context) {
cfgService.unregisterProperties(getClass(), false);
providerRegistry.unregister(this);
controller.removeListener(listener);
collectors.values().forEach(PortStatsCollector::stop);
......@@ -146,6 +162,25 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
LOG.info("Stopped");
}
@Modified
public void modified(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
int newPortStatsPollFrequency;
try {
String s = get(properties, "PortStatsPollFrequency");
newPortStatsPollFrequency = isNullOrEmpty(s) ? portStatsPollFrequency : Integer.parseInt(s.trim());
} catch (NumberFormatException | ClassCastException e) {
newPortStatsPollFrequency = portStatsPollFrequency;
}
if (newPortStatsPollFrequency != portStatsPollFrequency) {
portStatsPollFrequency = newPortStatsPollFrequency;
collectors.values().forEach(psc -> psc.adjustPollInterval(portStatsPollFrequency));
}
LOG.info("Settings: portStatsPollFrequency={}", portStatsPollFrequency);
}
@Override
public boolean isReachable(DeviceId deviceId) {
......@@ -275,7 +310,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
providerService.updatePorts(did, buildPortDescriptions(sw));
PortStatsCollector psc =
new PortStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
new PortStatsCollector(controller.getSwitch(dpid), portStatsPollFrequency);
psc.start();
collectors.put(dpid, psc);
}
......
......@@ -41,7 +41,7 @@ public class PortStatsCollector implements TimerTask {
private final HashedWheelTimer timer = Timer.getTimer();
private final OpenFlowSwitch sw;
private final Logger log = getLogger(getClass());
private final int refreshInterval;
private int refreshInterval;
private final AtomicLong xidAtomic = new AtomicLong(1);
private Timeout timeout;
......@@ -74,6 +74,13 @@ public class PortStatsCollector implements TimerTask {
}
}
synchronized void adjustPollInterval(int pollInterval) {
this.refreshInterval = pollInterval;
// task.cancel();
// task = new InternalTimerTask();
// timer.scheduleAtFixedRate(task, pollInterval * SECONDS, pollInterval * 1000);
}
private void sendPortStatistic() {
if (sw.getRole() != RoleState.MASTER) {
return;
......
......@@ -18,9 +18,11 @@ package org.onosproject.provider.of.device.impl;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
......@@ -84,8 +86,9 @@ public class OpenFlowDeviceProviderTest {
public void startUp() {
provider.providerRegistry = registry;
provider.controller = controller;
provider.cfgService = new ComponentConfigAdapter();
controller.switchMap.put(DPID1, SW1);
provider.activate();
provider.activate(null);
assertNotNull("provider should be registered", registry.provider);
assertNotNull("listener should be registered", controller.listener);
assertEquals("devices not added", 1, registry.connected.size());
......@@ -94,7 +97,7 @@ public class OpenFlowDeviceProviderTest {
@After
public void tearDown() {
provider.deactivate();
provider.deactivate(null);
assertNull("listener should be removed", controller.listener);
provider.controller = null;
provider.providerRegistry = null;
......