blob: a5aa13e5cfec5ba95d773b085ffc012dc479cf62 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.host.impl;
Jonathan Hartfca736c2014-09-19 17:26:59 -07002
Jonathan Hart87fbbad2014-09-23 08:43:50 -07003import java.nio.ByteBuffer;
4import java.util.ArrayList;
5import java.util.Collections;
Jonathan Hartfca736c2014-09-19 17:26:59 -07006import java.util.HashSet;
Jonathan Hart87fbbad2014-09-23 08:43:50 -07007import java.util.List;
Jonathan Hartfca736c2014-09-19 17:26:59 -07008import java.util.Set;
9import java.util.concurrent.TimeUnit;
10
11import org.jboss.netty.util.Timeout;
12import org.jboss.netty.util.TimerTask;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070013import org.onlab.onos.net.ConnectPoint;
14import org.onlab.onos.net.Device;
15import org.onlab.onos.net.DeviceId;
Jonathan Hartfca736c2014-09-19 17:26:59 -070016import org.onlab.onos.net.Host;
17import org.onlab.onos.net.Port;
18import org.onlab.onos.net.device.DeviceService;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070019import org.onlab.onos.net.flow.DefaultTrafficTreatment;
20import org.onlab.onos.net.flow.TrafficTreatment;
21import org.onlab.onos.net.flow.instructions.Instruction;
22import org.onlab.onos.net.flow.instructions.Instructions;
Jonathan Hartfca736c2014-09-19 17:26:59 -070023import org.onlab.onos.net.host.HostProvider;
24import org.onlab.onos.net.host.HostService;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070025import org.onlab.onos.net.host.HostStore;
26import org.onlab.onos.net.host.PortAddresses;
27import org.onlab.onos.net.packet.DefaultOutboundPacket;
28import org.onlab.onos.net.packet.OutboundPacket;
29import org.onlab.onos.net.packet.PacketService;
Jonathan Hartfca736c2014-09-19 17:26:59 -070030import org.onlab.onos.net.topology.TopologyService;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070031import org.onlab.packet.ARP;
32import org.onlab.packet.Ethernet;
33import org.onlab.packet.IpAddress;
Jonathan Hartfca736c2014-09-19 17:26:59 -070034import org.onlab.packet.IpPrefix;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070035import org.onlab.packet.MacAddress;
Jonathan Hartfca736c2014-09-19 17:26:59 -070036import org.onlab.util.Timer;
37
Jonathan Hart87fbbad2014-09-23 08:43:50 -070038/**
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 */
tom202175a2014-09-19 19:00:11 -070045public class HostMonitor implements TimerTask {
Jonathan Hartfca736c2014-09-19 17:26:59 -070046
Jonathan Hart87fbbad2014-09-23 08:43:50 -070047 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
Jonathan Hartfca736c2014-09-19 17:26:59 -070057 private final HostService hostService;
58 private final TopologyService topologyService;
59 private final DeviceService deviceService;
60 private final HostProvider hostProvider;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070061 private final PacketService packetService;
62 private final HostStore hostStore;
Jonathan Hartfca736c2014-09-19 17:26:59 -070063
Jonathan Hart87fbbad2014-09-23 08:43:50 -070064 private final Set<IpAddress> monitoredAddresses;
Jonathan Hartfca736c2014-09-19 17:26:59 -070065
66 private final long probeRate;
67
alshabib010c31d2014-09-26 10:01:12 -070068 private final Timeout timeout;
Jonathan Hartfca736c2014-09-19 17:26:59 -070069
tom202175a2014-09-19 19:00:11 -070070 public HostMonitor(HostService hostService, TopologyService topologyService,
alshabib010c31d2014-09-26 10:01:12 -070071 DeviceService deviceService,
72 HostProvider hostProvider, PacketService packetService,
73 HostStore hostStore) {
Jonathan Hartfca736c2014-09-19 17:26:59 -070074 this.hostService = hostService;
75 this.topologyService = topologyService;
76 this.deviceService = deviceService;
77 this.hostProvider = hostProvider;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070078 this.packetService = packetService;
79 this.hostStore = hostStore;
Jonathan Hartfca736c2014-09-19 17:26:59 -070080
81 monitoredAddresses = new HashSet<>();
82
83 probeRate = 30000; // milliseconds
84
85 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
86 }
87
Jonathan Hart87fbbad2014-09-23 08:43:50 -070088 public void addMonitoringFor(IpAddress ip) {
Jonathan Hartfca736c2014-09-19 17:26:59 -070089 monitoredAddresses.add(ip);
90 }
91
Jonathan Hart87fbbad2014-09-23 08:43:50 -070092 public void stopMonitoring(IpAddress ip) {
Jonathan Hartfca736c2014-09-19 17:26:59 -070093 monitoredAddresses.remove(ip);
94 }
95
96 public void shutdown() {
97 timeout.cancel();
98 }
99
100 @Override
101 public void run(Timeout timeout) throws Exception {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700102 for (IpAddress ip : monitoredAddresses) {
103 Set<Host> hosts = Collections.emptySet(); //TODO hostService.getHostsByIp(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700104
105 if (hosts.isEmpty()) {
106 sendArpRequest(ip);
107 } else {
108 for (Host host : hosts) {
109 hostProvider.triggerProbe(host);
110 }
111 }
112 }
113
114 timeout = Timer.getTimer().newTimeout(this, probeRate, TimeUnit.MILLISECONDS);
115 }
116
117 /**
118 * Sends an ARP request for the given IP address.
119 *
120 * @param targetIp IP address to ARP for
121 */
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700122 private void sendArpRequest(IpAddress targetIp) {
Jonathan Hartfca736c2014-09-19 17:26:59 -0700123
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700124 // Find ports with an IP address in the target's subnet and sent ARP
125 // probes out those ports.
126 for (Device device : deviceService.getDevices()) {
Jonathan Hartfca736c2014-09-19 17:26:59 -0700127 for (Port port : deviceService.getPorts(device.id())) {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700128 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
129 PortAddresses addresses = hostStore.getAddressBindingsForPort(cp);
130
Jonathan Hart09585c62014-09-23 16:58:04 -0700131 /*for (IpPrefix prefix : addresses.ips()) {
132 if (prefix.contains(targetIp)) {
133 sendProbe(device.id(), port, addresses, targetIp);
134 }
135 }*/
Jonathan Hartfca736c2014-09-19 17:26:59 -0700136 }
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700137 }
Jonathan Hartfca736c2014-09-19 17:26:59 -0700138
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700139 // TODO case where no address was found.
140 // Broadcast out internal edge ports?
Jonathan Hartfca736c2014-09-19 17:26:59 -0700141 }
142
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700143 private void sendProbe(DeviceId deviceId, Port port, PortAddresses portAddresses,
144 IpAddress targetIp) {
145 Ethernet arpPacket = createArpFor(targetIp, portAddresses);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700146
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700147 List<Instruction> instructions = new ArrayList<>();
148 instructions.add(Instructions.createOutput(port.number()));
149
alshabib010c31d2014-09-26 10:01:12 -0700150 TrafficTreatment treatment = new DefaultTrafficTreatment.Builder()
151 .setOutput(port.number())
152 .build();
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700153
154 OutboundPacket outboundPacket =
155 new DefaultOutboundPacket(deviceId, treatment,
156 ByteBuffer.wrap(arpPacket.serialize()));
157
158 packetService.emit(outboundPacket);
159 }
160
161 private Ethernet createArpFor(IpAddress targetIp, PortAddresses portAddresses) {
162
163 ARP arp = new ARP();
164 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
alshabib010c31d2014-09-26 10:01:12 -0700165 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
166 .setProtocolType(ARP.PROTO_TYPE_IP)
167 .setProtocolAddressLength((byte) IpPrefix.INET_LEN);
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700168
169 byte[] sourceMacAddress;
170 if (portAddresses.mac() == null) {
171 sourceMacAddress = DEFAULT_MAC_ADDRESS;
172 } else {
173 sourceMacAddress = portAddresses.mac().getAddress();
174 }
175
176 arp.setSenderHardwareAddress(sourceMacAddress)
alshabib010c31d2014-09-26 10:01:12 -0700177 //TODO .setSenderProtocolAddress(portAddresses.ips().toOctets())
178 .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
179 .setTargetProtocolAddress(targetIp.toOctets());
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700180
181 Ethernet ethernet = new Ethernet();
182 ethernet.setEtherType(Ethernet.TYPE_ARP)
alshabib010c31d2014-09-26 10:01:12 -0700183 .setDestinationMACAddress(BROADCAST_MAC)
184 .setSourceMACAddress(sourceMacAddress)
185 .setPayload(arp);
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700186
187 return ethernet;
Jonathan Hartfca736c2014-09-19 17:26:59 -0700188 }
189}