Jonathan Hart

Implemented HostMonitor for probing IP addresses to detect hosts

package org.onlab.onos.net.host.impl;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.TimerTask;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficTreatment;
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.packet.PacketProvider;
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.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;
/**
* Monitors hosts on the dataplane to detect changes in host data.
* <p/>
* The HostMonitor can monitor hosts that have already been detected for
* changes. At an application's request, it can also monitor and actively
* 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 byte[] ZERO_MAC_ADDRESS =
MacAddress.valueOf("00:00:00:00:00:00").getAddress();
// TODO put on Ethernet
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 PacketProvider packetProvider;
private final PacketService packetService;
private final HostStore hostStore;
private final Set<IpPrefix> monitoredAddresses;
private final Set<IpAddress> monitoredAddresses;
private final long probeRate;
......@@ -32,12 +69,14 @@ public class HostMonitor implements TimerTask {
public HostMonitor(HostService hostService, TopologyService topologyService,
DeviceService deviceService,
HostProvider hostProvider, PacketProvider packetProvider) {
HostProvider hostProvider, PacketService packetService,
HostStore hostStore) {
this.hostService = hostService;
this.topologyService = topologyService;
this.deviceService = deviceService;
this.hostProvider = hostProvider;
this.packetProvider = packetProvider;
this.packetService = packetService;
this.hostStore = hostStore;
monitoredAddresses = new HashSet<>();
......@@ -46,11 +85,11 @@ public class HostMonitor implements TimerTask {
timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
}
public void addMonitoringFor(IpPrefix ip) {
public void addMonitoringFor(IpAddress ip) {
monitoredAddresses.add(ip);
}
public void stopMonitoring(IpPrefix ip) {
public void stopMonitoring(IpAddress ip) {
monitoredAddresses.remove(ip);
}
......@@ -60,8 +99,8 @@ public class HostMonitor implements TimerTask {
@Override
public void run(Timeout timeout) throws Exception {
for (IpPrefix ip : monitoredAddresses) {
Set<Host> hosts = hostService.getHostsByIp(ip);
for (IpAddress ip : monitoredAddresses) {
Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip);
if (hosts.isEmpty()) {
sendArpRequest(ip);
......@@ -80,28 +119,70 @@ public class HostMonitor implements TimerTask {
*
* @param targetIp IP address to ARP for
*/
private void sendArpRequest(IpPrefix targetIp) {
// emit ARP packet out appropriate ports
// if ip in one of the configured (external) subnets
// sent out that port
// else (ip isn't in any configured subnet)
// send out all non-external edge ports
private void sendArpRequest(IpAddress targetIp) {
/*for (Device device : deviceService.getDevices()) {
// 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())) {
for (IpPrefix ip : port.ipAddresses()) {
if (ip.contains(targetIp)) {
sendProbe(port, targetIp);
continue;
ConnectPoint cp = new ConnectPoint(device.id(), port.number());
PortAddresses addresses = hostStore.getAddressBindingsForPort(cp);
if (addresses.ip().contains(targetIp)) {
sendProbe(device.id(), port, addresses, targetIp);
}
}
}
// 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);
List<Instruction> instructions = new ArrayList<>();
instructions.add(Instructions.createOutput(port.number()));
TrafficTreatment treatment =
new DefaultTrafficTreatment.Builder()
.add(Instructions.createOutput(port.number()))
.build();
OutboundPacket outboundPacket =
new DefaultOutboundPacket(deviceId, treatment,
ByteBuffer.wrap(arpPacket.serialize()));
packetService.emit(outboundPacket);
}
}*/
private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) {
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);
byte[] sourceMacAddress;
if (portAddresses.mac() == null) {
sourceMacAddress = DEFAULT_MAC_ADDRESS;
} else {
sourceMacAddress = portAddresses.mac().getAddress();
}
private void sendProbe(Port port, IpPrefix targetIp) {
arp.setSenderHardwareAddress(sourceMacAddress)
.setSenderProtocolAddress(portAddresses.ip().toOctets())
.setTargetHardwareAddress(ZERO_MAC_ADDRESS)
.setTargetProtocolAddress(targetIp.toOctets());
Ethernet ethernet = new Ethernet();
ethernet.setEtherType(Ethernet.TYPE_ARP)
.setDestinationMACAddress(BROADCAST_MAC)
.setSourceMACAddress(sourceMacAddress)
.setPayload(arp);
return ethernet;
}
}
......