Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/apps/config/src/main/java/org/onlab/onos/config/AddressEntry.java b/apps/config/src/main/java/org/onlab/onos/config/AddressEntry.java
index 318aebd..081efed 100644
--- a/apps/config/src/main/java/org/onlab/onos/config/AddressEntry.java
+++ b/apps/config/src/main/java/org/onlab/onos/config/AddressEntry.java
@@ -3,8 +3,6 @@
import java.util.List;
import org.codehaus.jackson.annotate.JsonProperty;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
/**
* Represents a set of addresses bound to a port.
@@ -12,8 +10,8 @@
public class AddressEntry {
private String dpid;
private short portNumber;
- private List<IpPrefix> ipAddresses;
- private MacAddress macAddress;
+ private List<String> ipAddresses;
+ private String macAddress;
public String getDpid() {
return dpid;
@@ -33,21 +31,21 @@
this.portNumber = portNumber;
}
- public List<IpPrefix> getIpAddresses() {
+ public List<String> getIpAddresses() {
return ipAddresses;
}
@JsonProperty("ips")
- public void setIpAddresses(List<IpPrefix> ipAddresses) {
- this.ipAddresses = ipAddresses;
+ public void setIpAddresses(List<String> strIps) {
+ this.ipAddresses = strIps;
}
- public MacAddress getMacAddress() {
+ public String getMacAddress() {
return macAddress;
}
@JsonProperty("mac")
- public void setMacAddress(MacAddress macAddress) {
+ public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
}
diff --git a/apps/config/src/main/java/org/onlab/onos/config/NetworkConfigReader.java b/apps/config/src/main/java/org/onlab/onos/config/NetworkConfigReader.java
index 985c4a2..4f1a48a 100644
--- a/apps/config/src/main/java/org/onlab/onos/config/NetworkConfigReader.java
+++ b/apps/config/src/main/java/org/onlab/onos/config/NetworkConfigReader.java
@@ -5,6 +5,8 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -17,10 +19,10 @@
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.host.HostAdminService;
import org.onlab.onos.net.host.PortAddresses;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
import org.slf4j.Logger;
-import com.google.common.collect.Sets;
-
/**
* Simple configuration module to read in supplementary network configuration
* from a file.
@@ -51,9 +53,29 @@
DeviceId.deviceId(dpidToUri(entry.getDpid())),
PortNumber.portNumber(entry.getPortNumber()));
+ Set<IpPrefix> ipAddresses = new HashSet<IpPrefix>();
+
+ for (String strIp : entry.getIpAddresses()) {
+ try {
+ IpPrefix address = IpPrefix.valueOf(strIp);
+ ipAddresses.add(address);
+ } catch (IllegalArgumentException e) {
+ log.warn("Bad format for IP address in config: {}", strIp);
+ }
+ }
+
+ MacAddress macAddress = null;
+ if (entry.getMacAddress() != null) {
+ try {
+ macAddress = MacAddress.valueOf(entry.getMacAddress());
+ } catch (IllegalArgumentException e) {
+ log.warn("Bad format for MAC address in config: {}",
+ entry.getMacAddress());
+ }
+ }
+
PortAddresses addresses = new PortAddresses(cp,
- Sets.newHashSet(entry.getIpAddresses()),
- entry.getMacAddress());
+ ipAddresses, macAddress);
hostAdminService.bindAddressesToPort(addresses);
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostManager.java b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostManager.java
index e3f53fe..88b6923 100644
--- a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostManager.java
@@ -1,5 +1,10 @@
package org.onlab.onos.net.host.impl;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Set;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -12,6 +17,7 @@
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
+import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.host.HostAdminService;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.host.HostEvent;
@@ -23,6 +29,7 @@
import org.onlab.onos.net.host.HostStore;
import org.onlab.onos.net.host.HostStoreDelegate;
import org.onlab.onos.net.host.PortAddresses;
+import org.onlab.onos.net.packet.PacketService;
import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.onlab.packet.IpAddress;
@@ -31,11 +38,6 @@
import org.onlab.packet.VlanId;
import org.slf4j.Logger;
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
/**
* Provides basic implementation of the host SB & NB APIs.
*/
@@ -59,12 +61,22 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ private HostMonitor monitor;
@Activate
public void activate() {
+ log.info("Started");
store.setDelegate(delegate);
eventDispatcher.addSink(HostEvent.class, listenerRegistry);
- log.info("Started");
+
+ monitor = new HostMonitor(deviceService, packetService, this);
+
}
@Deactivate
@@ -76,6 +88,8 @@
@Override
protected HostProviderService createProviderService(HostProvider provider) {
+ monitor.registerHostProvider(provider);
+
return new InternalHostProviderService(provider);
}
@@ -126,12 +140,12 @@
@Override
public void startMonitoringIp(IpAddress ip) {
- // TODO pass through to HostMonitor
+ monitor.addMonitoringFor(ip);
}
@Override
public void stopMonitoringIp(IpAddress ip) {
- // TODO pass through to HostMonitor
+ monitor.stopMonitoring(ip);
}
@Override
diff --git a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
index a5aa13e..9f8dd48 100644
--- a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
@@ -2,10 +2,11 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.util.Timeout;
@@ -21,19 +22,19 @@
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.flow.instructions.Instructions;
import org.onlab.onos.net.host.HostProvider;
-import org.onlab.onos.net.host.HostService;
-import org.onlab.onos.net.host.HostStore;
import org.onlab.onos.net.host.PortAddresses;
import org.onlab.onos.net.packet.DefaultOutboundPacket;
import org.onlab.onos.net.packet.OutboundPacket;
import org.onlab.onos.net.packet.PacketService;
-import org.onlab.onos.net.topology.TopologyService;
+import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.util.Timer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Monitors hosts on the dataplane to detect changes in host data.
@@ -43,9 +44,7 @@
* probe for hosts that have not yet been detected (specified by IP address).
*/
public class HostMonitor implements TimerTask {
-
- private static final byte[] DEFAULT_MAC_ADDRESS =
- MacAddress.valueOf("00:00:00:00:00:01").getAddress();
+ private static final Logger log = LoggerFactory.getLogger(HostMonitor.class);
private static final byte[] ZERO_MAC_ADDRESS =
MacAddress.valueOf("00:00:00:00:00:00").getAddress();
@@ -54,59 +53,77 @@
private static final byte[] BROADCAST_MAC =
MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress();
- private final HostService hostService;
- private final TopologyService topologyService;
- private final DeviceService deviceService;
- private final HostProvider hostProvider;
- private final PacketService packetService;
- private final HostStore hostStore;
+ private DeviceService deviceService;
+ private PacketService packetService;
+ private HostManager hostManager;
private final Set<IpAddress> monitoredAddresses;
+ private final Map<ProviderId, HostProvider> hostProviders;
+
private final long probeRate;
private final Timeout timeout;
- public HostMonitor(HostService hostService, TopologyService topologyService,
+ public HostMonitor(
DeviceService deviceService,
- HostProvider hostProvider, PacketService packetService,
- HostStore hostStore) {
- this.hostService = hostService;
- this.topologyService = topologyService;
+ PacketService packetService,
+ HostManager hostService) {
+
this.deviceService = deviceService;
- this.hostProvider = hostProvider;
this.packetService = packetService;
- this.hostStore = hostStore;
+ this.hostManager = hostService;
monitoredAddresses = new HashSet<>();
+ hostProviders = new ConcurrentHashMap<>();
probeRate = 30000; // milliseconds
timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
+
+ addDefaultAddresses();
}
- public void addMonitoringFor(IpAddress ip) {
+ private void addDefaultAddresses() {
+ //monitoredAddresses.add(IpAddress.valueOf("10.0.0.1"));
+ }
+
+ void addMonitoringFor(IpAddress ip) {
monitoredAddresses.add(ip);
}
- public void stopMonitoring(IpAddress ip) {
+ void stopMonitoring(IpAddress ip) {
monitoredAddresses.remove(ip);
}
- public void shutdown() {
+ void shutdown() {
timeout.cancel();
}
+ void registerHostProvider(HostProvider provider) {
+ hostProviders.put(provider.id(), provider);
+ }
+
+ void unregisterHostProvider(HostProvider provider) {
+ // TODO find out how to call this
+ }
+
@Override
public void run(Timeout timeout) throws Exception {
for (IpAddress ip : monitoredAddresses) {
- Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip);
+ // TODO have to convert right now because the HostService API uses IpPrefix
+ IpPrefix prefix = IpPrefix.valueOf(ip.toOctets());
+
+ Set<Host> hosts = hostManager.getHostsByIp(prefix);
if (hosts.isEmpty()) {
sendArpRequest(ip);
} else {
for (Host host : hosts) {
- hostProvider.triggerProbe(host);
+ HostProvider provider = hostProviders.get(host.providerId());
+ if (provider != null) {
+ provider.triggerProbe(host);
+ }
}
}
}
@@ -120,29 +137,26 @@
* @param targetIp IP address to ARP for
*/
private void sendArpRequest(IpAddress targetIp) {
-
// Find ports with an IP address in the target's subnet and sent ARP
// probes out those ports.
for (Device device : deviceService.getDevices()) {
for (Port port : deviceService.getPorts(device.id())) {
ConnectPoint cp = new ConnectPoint(device.id(), port.number());
- PortAddresses addresses = hostStore.getAddressBindingsForPort(cp);
+ PortAddresses addresses = hostManager.getAddressBindingsForPort(cp);
- /*for (IpPrefix prefix : addresses.ips()) {
+ for (IpPrefix prefix : addresses.ips()) {
if (prefix.contains(targetIp)) {
- sendProbe(device.id(), port, addresses, targetIp);
+ sendProbe(device.id(), port, targetIp,
+ prefix.toIpAddress(), addresses.mac());
}
- }*/
+ }
}
}
-
- // TODO case where no address was found.
- // Broadcast out internal edge ports?
}
- private void sendProbe(DeviceId deviceId, Port port, PortAddresses portAddresses,
- IpAddress targetIp) {
- Ethernet arpPacket = createArpFor(targetIp, portAddresses);
+ private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp,
+ IpAddress sourceIp, MacAddress sourceMac) {
+ Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac);
List<Instruction> instructions = new ArrayList<>();
instructions.add(Instructions.createOutput(port.number()));
@@ -158,31 +172,26 @@
packetService.emit(outboundPacket);
}
- private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) {
+ private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
+ MacAddress sourceMac) {
ARP arp = new ARP();
arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
- .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
- .setProtocolType(ARP.PROTO_TYPE_IP)
- .setProtocolAddressLength((byte) IpPrefix.INET_LEN);
+ .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
+ .setProtocolType(ARP.PROTO_TYPE_IP)
+ .setProtocolAddressLength((byte) IpPrefix.INET_LEN)
+ .setOpCode(ARP.OP_REQUEST);
- byte[] sourceMacAddress;
- if (portAddresses.mac() == null) {
- sourceMacAddress = DEFAULT_MAC_ADDRESS;
- } else {
- sourceMacAddress = portAddresses.mac().getAddress();
- }
-
- arp.setSenderHardwareAddress(sourceMacAddress)
- //TODO .setSenderProtocolAddress(portAddresses.ips().toOctets())
- .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
- .setTargetProtocolAddress(targetIp.toOctets());
+ arp.setSenderHardwareAddress(sourceMac.getAddress())
+ .setSenderProtocolAddress(sourceIp.toOctets())
+ .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
+ .setTargetProtocolAddress(targetIp.toOctets());
Ethernet ethernet = new Ethernet();
ethernet.setEtherType(Ethernet.TYPE_ARP)
- .setDestinationMACAddress(BROADCAST_MAC)
- .setSourceMACAddress(sourceMacAddress)
- .setPayload(arp);
+ .setDestinationMACAddress(BROADCAST_MAC)
+ .setSourceMACAddress(sourceMac.getAddress())
+ .setPayload(arp);
return ethernet;
}
diff --git a/features/features.xml b/features/features.xml
index f008c14..68fa8c3 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -11,7 +11,7 @@
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
<bundle>mvn:com.hazelcast/hazelcast/3.3</bundle>
- <bundle>mvn:com.codahale.metrics/metrics-core/3.0.2</bundle>
+ <bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
<bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
<bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle>
diff --git a/utils/misc/pom.xml b/utils/misc/pom.xml
index bb25635..bd3cc08 100644
--- a/utils/misc/pom.xml
+++ b/utils/misc/pom.xml
@@ -56,9 +56,13 @@
<artifactId>objenesis</artifactId>
</dependency>
<dependency>
- <groupId>com.codahale.metrics</groupId>
+ <groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
- <version>3.0.2</version>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
</dependencies>
diff --git a/utils/misc/src/main/java/org/onlab/metrics/MetricsManager.java b/utils/misc/src/main/java/org/onlab/metrics/MetricsManager.java
index 2b13efb..e07d3f9 100644
--- a/utils/misc/src/main/java/org/onlab/metrics/MetricsManager.java
+++ b/utils/misc/src/main/java/org/onlab/metrics/MetricsManager.java
@@ -1,10 +1,18 @@
package org.onlab.metrics;
+import java.io.File;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
import com.codahale.metrics.Counter;
+import com.codahale.metrics.CsvReporter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
@@ -45,24 +53,44 @@
* </code>
* </pre>
*/
+@Component(immediate = true)
public final class MetricsManager implements MetricsService {
/**
* Registry to hold the Components defined in the system.
*/
- private ConcurrentMap<String, MetricsComponent> componentsRegistry =
- new ConcurrentHashMap<>();
+ private ConcurrentMap<String, MetricsComponent> componentsRegistry;
/**
* Registry for the Metrics objects created in the system.
*/
- private final MetricRegistry metricsRegistry = new MetricRegistry();
+ private final MetricRegistry metricsRegistry;
/**
- * Hide constructor. The only way to get the registry is through the
- * singleton getter.
+ * Default Reporter for this metrics manager.
*/
- private MetricsManager() {}
+ private final CsvReporter reporter;
+
+ public MetricsManager() {
+ this.componentsRegistry = new ConcurrentHashMap<>();
+ this.metricsRegistry = new MetricRegistry();
+
+ this.reporter = CsvReporter.forRegistry(metricsRegistry)
+ .formatFor(Locale.US)
+ .convertRatesTo(TimeUnit.SECONDS)
+ .convertDurationsTo(TimeUnit.MICROSECONDS)
+ .build(new File("/tmp/"));
+
+ reporter.start(10, TimeUnit.SECONDS);
+ }
+
+ @Activate
+ public void activate() {
+ }
+
+ @Deactivate
+ public void deactivate() {
+ }
/**
* Registers a component.
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
index b205f90..84acb82 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
@@ -250,6 +250,17 @@
return new IpPrefix(version, host, netmask);
}
+ /**
+ * Returns an IpAddress of the bytes contained in this prefix.
+ * FIXME this is a hack for now and only works because IpPrefix doesn't
+ * mask the input bytes on creation.
+ *
+ * @return the IpAddress
+ */
+ public IpAddress toIpAddress() {
+ return IpAddress.valueOf(octets);
+ }
+
public boolean isMasked() {
return mask() != 0;
}
@@ -278,6 +289,17 @@
return false;
}
+ public boolean contains(IpAddress address) {
+ // Need to get the network address because prefixes aren't automatically
+ // masked on creation
+ IpPrefix meMasked = network();
+
+ IpPrefix otherMasked =
+ IpPrefix.valueOf(address.octets, netmask).network();
+
+ return Arrays.equals(meMasked.octets, otherMasked.octets);
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -303,6 +325,7 @@
if (netmask != other.netmask) {
return false;
}
+ // TODO not quite right until we mask the input
if (!Arrays.equals(octets, other.octets)) {
return false;
}
diff --git a/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java b/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
index f6bf6f1..297a0f3 100644
--- a/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
@@ -76,7 +76,7 @@
}
@Test
- public void testContains() {
+ public void testContainsIpPrefix() {
IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32);
IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32);
@@ -96,4 +96,17 @@
assertTrue(slash8.contains(slash31));
assertFalse(slash31.contains(slash8));
}
+
+ @Test
+ public void testContainsIpAddress() {
+ IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
+ IpAddress slash32 = IpAddress.valueOf(BYTES1, 32);
+
+ assertTrue(slash31.contains(slash32));
+
+ IpPrefix intf = IpPrefix.valueOf("192.168.10.101/24");
+ IpAddress addr = IpAddress.valueOf("192.168.10.1");
+
+ assertTrue(intf.contains(addr));
+ }
}