Jonathan Hart

Implemented HostMonitor for probing IP addresses to detect hosts

1 package org.onlab.onos.net.host.impl; 1 package org.onlab.onos.net.host.impl;
2 2
3 +import java.nio.ByteBuffer;
4 +import java.util.ArrayList;
5 +import java.util.Collections;
3 import java.util.HashSet; 6 import java.util.HashSet;
7 +import java.util.List;
4 import java.util.Set; 8 import java.util.Set;
5 import java.util.concurrent.TimeUnit; 9 import java.util.concurrent.TimeUnit;
6 10
7 import org.jboss.netty.util.Timeout; 11 import org.jboss.netty.util.Timeout;
8 import org.jboss.netty.util.TimerTask; 12 import org.jboss.netty.util.TimerTask;
13 +import org.onlab.onos.net.ConnectPoint;
14 +import org.onlab.onos.net.Device;
15 +import org.onlab.onos.net.DeviceId;
9 import org.onlab.onos.net.Host; 16 import org.onlab.onos.net.Host;
10 import org.onlab.onos.net.Port; 17 import org.onlab.onos.net.Port;
11 import org.onlab.onos.net.device.DeviceService; 18 import org.onlab.onos.net.device.DeviceService;
19 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
20 +import org.onlab.onos.net.flow.TrafficTreatment;
21 +import org.onlab.onos.net.flow.instructions.Instruction;
22 +import org.onlab.onos.net.flow.instructions.Instructions;
12 import org.onlab.onos.net.host.HostProvider; 23 import org.onlab.onos.net.host.HostProvider;
13 import org.onlab.onos.net.host.HostService; 24 import org.onlab.onos.net.host.HostService;
14 -import org.onlab.onos.net.packet.PacketProvider; 25 +import org.onlab.onos.net.host.HostStore;
26 +import org.onlab.onos.net.host.PortAddresses;
27 +import org.onlab.onos.net.packet.DefaultOutboundPacket;
28 +import org.onlab.onos.net.packet.OutboundPacket;
29 +import org.onlab.onos.net.packet.PacketService;
15 import org.onlab.onos.net.topology.TopologyService; 30 import org.onlab.onos.net.topology.TopologyService;
31 +import org.onlab.packet.ARP;
32 +import org.onlab.packet.Ethernet;
33 +import org.onlab.packet.IpAddress;
16 import org.onlab.packet.IpPrefix; 34 import org.onlab.packet.IpPrefix;
35 +import org.onlab.packet.MacAddress;
17 import org.onlab.util.Timer; 36 import org.onlab.util.Timer;
18 37
38 +/**
39 + * Monitors hosts on the dataplane to detect changes in host data.
40 + * <p/>
41 + * The HostMonitor can monitor hosts that have already been detected for
42 + * changes. At an application's request, it can also monitor and actively
43 + * probe for hosts that have not yet been detected (specified by IP address).
44 + */
19 public class HostMonitor implements TimerTask { 45 public class HostMonitor implements TimerTask {
20 46
47 + private static final byte[] DEFAULT_MAC_ADDRESS =
48 + MacAddress.valueOf("00:00:00:00:00:01").getAddress();
49 +
50 + private static final byte[] ZERO_MAC_ADDRESS =
51 + MacAddress.valueOf("00:00:00:00:00:00").getAddress();
52 +
53 + // TODO put on Ethernet
54 + private static final byte[] BROADCAST_MAC =
55 + MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress();
56 +
21 private final HostService hostService; 57 private final HostService hostService;
22 private final TopologyService topologyService; 58 private final TopologyService topologyService;
23 private final DeviceService deviceService; 59 private final DeviceService deviceService;
24 private final HostProvider hostProvider; 60 private final HostProvider hostProvider;
25 - private final PacketProvider packetProvider; 61 + private final PacketService packetService;
62 + private final HostStore hostStore;
26 63
27 - private final Set<IpPrefix> monitoredAddresses; 64 + private final Set<IpAddress> monitoredAddresses;
28 65
29 private final long probeRate; 66 private final long probeRate;
30 67
...@@ -32,12 +69,14 @@ public class HostMonitor implements TimerTask { ...@@ -32,12 +69,14 @@ public class HostMonitor implements TimerTask {
32 69
33 public HostMonitor(HostService hostService, TopologyService topologyService, 70 public HostMonitor(HostService hostService, TopologyService topologyService,
34 DeviceService deviceService, 71 DeviceService deviceService,
35 - HostProvider hostProvider, PacketProvider packetProvider) { 72 + HostProvider hostProvider, PacketService packetService,
73 + HostStore hostStore) {
36 this.hostService = hostService; 74 this.hostService = hostService;
37 this.topologyService = topologyService; 75 this.topologyService = topologyService;
38 this.deviceService = deviceService; 76 this.deviceService = deviceService;
39 this.hostProvider = hostProvider; 77 this.hostProvider = hostProvider;
40 - this.packetProvider = packetProvider; 78 + this.packetService = packetService;
79 + this.hostStore = hostStore;
41 80
42 monitoredAddresses = new HashSet<>(); 81 monitoredAddresses = new HashSet<>();
43 82
...@@ -46,11 +85,11 @@ public class HostMonitor implements TimerTask { ...@@ -46,11 +85,11 @@ public class HostMonitor implements TimerTask {
46 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS); 85 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
47 } 86 }
48 87
49 - public void addMonitoringFor(IpPrefix ip) { 88 + public void addMonitoringFor(IpAddress ip) {
50 monitoredAddresses.add(ip); 89 monitoredAddresses.add(ip);
51 } 90 }
52 91
53 - public void stopMonitoring(IpPrefix ip) { 92 + public void stopMonitoring(IpAddress ip) {
54 monitoredAddresses.remove(ip); 93 monitoredAddresses.remove(ip);
55 } 94 }
56 95
...@@ -60,8 +99,8 @@ public class HostMonitor implements TimerTask { ...@@ -60,8 +99,8 @@ public class HostMonitor implements TimerTask {
60 99
61 @Override 100 @Override
62 public void run(Timeout timeout) throws Exception { 101 public void run(Timeout timeout) throws Exception {
63 - for (IpPrefix ip : monitoredAddresses) { 102 + for (IpAddress ip : monitoredAddresses) {
64 - Set<Host> hosts = hostService.getHostsByIp(ip); 103 + Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip);
65 104
66 if (hosts.isEmpty()) { 105 if (hosts.isEmpty()) {
67 sendArpRequest(ip); 106 sendArpRequest(ip);
...@@ -80,28 +119,70 @@ public class HostMonitor implements TimerTask { ...@@ -80,28 +119,70 @@ public class HostMonitor implements TimerTask {
80 * 119 *
81 * @param targetIp IP address to ARP for 120 * @param targetIp IP address to ARP for
82 */ 121 */
83 - private void sendArpRequest(IpPrefix targetIp) { 122 + private void sendArpRequest(IpAddress targetIp) {
84 - // emit ARP packet out appropriate ports
85 123
86 - // if ip in one of the configured (external) subnets 124 + // Find ports with an IP address in the target's subnet and sent ARP
87 - // sent out that port 125 + // probes out those ports.
88 - // else (ip isn't in any configured subnet) 126 + for (Device device : deviceService.getDevices()) {
89 - // send out all non-external edge ports
90 -
91 - /*for (Device device : deviceService.getDevices()) {
92 for (Port port : deviceService.getPorts(device.id())) { 127 for (Port port : deviceService.getPorts(device.id())) {
93 - for (IpPrefix ip : port.ipAddresses()) { 128 + ConnectPoint cp = new ConnectPoint(device.id(), port.number());
94 - if (ip.contains(targetIp)) { 129 + PortAddresses addresses = hostStore.getAddressBindingsForPort(cp);
95 - sendProbe(port, targetIp); 130 +
96 - continue; 131 + if (addresses.ip().contains(targetIp)) {
97 - } 132 + sendProbe(device.id(), port, addresses, targetIp);
98 } 133 }
99 } 134 }
100 - }*/ 135 + }
101 136
137 + // TODO case where no address was found.
138 + // Broadcast out internal edge ports?
102 } 139 }
103 140
104 - private void sendProbe(Port port, IpPrefix targetIp) { 141 + private void sendProbe(DeviceId deviceId, Port port, PortAddresses portAddresses,
142 + IpAddress targetIp) {
143 + Ethernet arpPacket = createArpFor(targetIp, portAddresses);
144 +
145 + List<Instruction> instructions = new ArrayList<>();
146 + instructions.add(Instructions.createOutput(port.number()));
147 +
148 + TrafficTreatment treatment =
149 + new DefaultTrafficTreatment.Builder()
150 + .add(Instructions.createOutput(port.number()))
151 + .build();
152 +
153 + OutboundPacket outboundPacket =
154 + new DefaultOutboundPacket(deviceId, treatment,
155 + ByteBuffer.wrap(arpPacket.serialize()));
156 +
157 + packetService.emit(outboundPacket);
158 + }
159 +
160 + private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) {
161 +
162 + ARP arp = new ARP();
163 + arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
164 + .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
165 + .setProtocolType(ARP.PROTO_TYPE_IP)
166 + .setProtocolAddressLength((byte) IpPrefix.INET_LEN);
167 +
168 + byte[] sourceMacAddress;
169 + if (portAddresses.mac() == null) {
170 + sourceMacAddress = DEFAULT_MAC_ADDRESS;
171 + } else {
172 + sourceMacAddress = portAddresses.mac().getAddress();
173 + }
174 +
175 + arp.setSenderHardwareAddress(sourceMacAddress)
176 + .setSenderProtocolAddress(portAddresses.ip().toOctets())
177 + .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
178 + .setTargetProtocolAddress(targetIp.toOctets());
179 +
180 + Ethernet ethernet = new Ethernet();
181 + ethernet.setEtherType(Ethernet.TYPE_ARP)
182 + .setDestinationMACAddress(BROADCAST_MAC)
183 + .setSourceMACAddress(sourceMacAddress)
184 + .setPayload(arp);
105 185
186 + return ethernet;
106 } 187 }
107 } 188 }
......