blob: b5833cf05cfdc400a2bd0f5bd95d37f151239752 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.host.impl;
Jonathan Hartfca736c2014-09-19 17:26:59 -070017
Jonathan Hartfca736c2014-09-19 17:26:59 -070018import org.jboss.netty.util.Timeout;
19import org.jboss.netty.util.TimerTask;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080020import org.onlab.packet.ARP;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.VlanId;
25import org.onlab.util.Timer;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.net.ConnectPoint;
27import org.onosproject.net.Device;
28import org.onosproject.net.DeviceId;
29import org.onosproject.net.Host;
30import org.onosproject.net.Port;
31import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.TrafficTreatment;
34import org.onosproject.net.flow.instructions.Instruction;
35import org.onosproject.net.flow.instructions.Instructions;
36import org.onosproject.net.host.HostProvider;
37import org.onosproject.net.host.InterfaceIpAddress;
38import org.onosproject.net.host.PortAddresses;
39import org.onosproject.net.packet.DefaultOutboundPacket;
40import org.onosproject.net.packet.OutboundPacket;
41import org.onosproject.net.packet.PacketService;
42import org.onosproject.net.provider.ProviderId;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080043
44import java.nio.ByteBuffer;
45import java.util.ArrayList;
46import java.util.Collections;
47import java.util.List;
48import java.util.Set;
49import java.util.concurrent.ConcurrentHashMap;
50import java.util.concurrent.ConcurrentMap;
51import java.util.concurrent.TimeUnit;
Jonathan Hartfca736c2014-09-19 17:26:59 -070052
Jonathan Hart87fbbad2014-09-23 08:43:50 -070053/**
54 * Monitors hosts on the dataplane to detect changes in host data.
Thomas Vachuska4b420772014-10-30 16:46:17 -070055 * <p>
Jonathan Hart87fbbad2014-09-23 08:43:50 -070056 * The HostMonitor can monitor hosts that have already been detected for
57 * changes. At an application's request, it can also monitor and actively
58 * probe for hosts that have not yet been detected (specified by IP address).
Thomas Vachuska4b420772014-10-30 16:46:17 -070059 * </p>
Jonathan Hart87fbbad2014-09-23 08:43:50 -070060 */
tom202175a2014-09-19 19:00:11 -070061public class HostMonitor implements TimerTask {
Jonathan Hart70da5122014-10-01 16:37:42 -070062 private DeviceService deviceService;
63 private PacketService packetService;
64 private HostManager hostManager;
Jonathan Hartfca736c2014-09-19 17:26:59 -070065
Jonathan Hart87fbbad2014-09-23 08:43:50 -070066 private final Set<IpAddress> monitoredAddresses;
Jonathan Hartfca736c2014-09-19 17:26:59 -070067
Jonathan Hart34ed2fd2014-10-02 19:08:55 -070068 private final ConcurrentMap<ProviderId, HostProvider> hostProviders;
Jonathan Hart70da5122014-10-01 16:37:42 -070069
Jonathan Hart34ed2fd2014-10-02 19:08:55 -070070 private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -080071 private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes();
Jonathan Hart34ed2fd2014-10-02 19:08:55 -070072 private long probeRate = DEFAULT_PROBE_RATE;
Jonathan Hartfca736c2014-09-19 17:26:59 -070073
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070074 private Timeout timeout;
Jonathan Hartfca736c2014-09-19 17:26:59 -070075
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070076 /**
77 * Creates a new host monitor.
78 *
79 * @param deviceService device service used to find edge ports
80 * @param packetService packet service used to send packets on the data plane
Jonathan Hartb4758a92014-09-24 10:46:45 -070081 * @param hostManager host manager used to look up host information and
82 * probe existing hosts
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070083 */
Jonathan Hart34ed2fd2014-10-02 19:08:55 -070084 public HostMonitor(DeviceService deviceService, PacketService packetService,
Jonathan Hartb4758a92014-09-24 10:46:45 -070085 HostManager hostManager) {
Jonathan Hart70da5122014-10-01 16:37:42 -070086
Jonathan Hartfca736c2014-09-19 17:26:59 -070087 this.deviceService = deviceService;
Jonathan Hart87fbbad2014-09-23 08:43:50 -070088 this.packetService = packetService;
Jonathan Hartb4758a92014-09-24 10:46:45 -070089 this.hostManager = hostManager;
Jonathan Hartfca736c2014-09-19 17:26:59 -070090
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070091 monitoredAddresses = Collections.newSetFromMap(
92 new ConcurrentHashMap<IpAddress, Boolean>());
Jonathan Hart70da5122014-10-01 16:37:42 -070093 hostProviders = new ConcurrentHashMap<>();
Jonathan Hart70da5122014-10-01 16:37:42 -070094 }
95
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -070096 /**
97 * Adds an IP address to be monitored by the host monitor. The monitor will
98 * periodically probe the host to detect changes.
99 *
100 * @param ip IP address of the host to monitor
101 */
Jonathan Hart70da5122014-10-01 16:37:42 -0700102 void addMonitoringFor(IpAddress ip) {
Jonathan Hartfca736c2014-09-19 17:26:59 -0700103 monitoredAddresses.add(ip);
104 }
105
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700106 /**
107 * Stops monitoring the given IP address.
108 *
109 * @param ip IP address to stop monitoring on
110 */
Jonathan Hart70da5122014-10-01 16:37:42 -0700111 void stopMonitoring(IpAddress ip) {
Jonathan Hartfca736c2014-09-19 17:26:59 -0700112 monitoredAddresses.remove(ip);
113 }
114
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700115 /**
116 * Starts the host monitor. Does nothing if the monitor is already running.
117 */
118 void start() {
119 synchronized (this) {
120 if (timeout == null) {
121 timeout = Timer.getTimer().newTimeout(this, 0, TimeUnit.MILLISECONDS);
122 }
123 }
Jonathan Hartfca736c2014-09-19 17:26:59 -0700124 }
125
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700126 /**
127 * Stops the host monitor.
128 */
129 void shutdown() {
130 synchronized (this) {
131 timeout.cancel();
132 timeout = null;
133 }
134 }
135
136 /**
137 * Registers a host provider with the host monitor. The monitor can use the
138 * provider to probe hosts.
139 *
140 * @param provider the host provider to register
141 */
Jonathan Hart70da5122014-10-01 16:37:42 -0700142 void registerHostProvider(HostProvider provider) {
143 hostProviders.put(provider.id(), provider);
144 }
145
Jonathan Hartfca736c2014-09-19 17:26:59 -0700146 @Override
147 public void run(Timeout timeout) throws Exception {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700148 for (IpAddress ip : monitoredAddresses) {
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700149 Set<Host> hosts = hostManager.getHostsByIp(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700150
151 if (hosts.isEmpty()) {
152 sendArpRequest(ip);
153 } else {
154 for (Host host : hosts) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700155 HostProvider provider = hostProviders.get(host.providerId());
Jonathan Hart34ed2fd2014-10-02 19:08:55 -0700156 if (provider == null) {
157 hostProviders.remove(host.providerId(), null);
158 } else {
Jonathan Hart70da5122014-10-01 16:37:42 -0700159 provider.triggerProbe(host);
160 }
Jonathan Hartfca736c2014-09-19 17:26:59 -0700161 }
162 }
163 }
164
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700165 this.timeout = Timer.getTimer().newTimeout(this, probeRate, TimeUnit.MILLISECONDS);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700166 }
167
168 /**
169 * Sends an ARP request for the given IP address.
170 *
171 * @param targetIp IP address to ARP for
172 */
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700173 private void sendArpRequest(IpAddress targetIp) {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700174 // Find ports with an IP address in the target's subnet and sent ARP
175 // probes out those ports.
176 for (Device device : deviceService.getDevices()) {
Jonathan Hartfca736c2014-09-19 17:26:59 -0700177 for (Port port : deviceService.getPorts(device.id())) {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700178 ConnectPoint cp = new ConnectPoint(device.id(), port.number());
Jonathan Harta887ba82014-11-03 15:20:52 -0800179 Set<PortAddresses> portAddressSet =
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700180 hostManager.getAddressBindingsForPort(cp);
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700181
Jonathan Harta887ba82014-11-03 15:20:52 -0800182 for (PortAddresses portAddresses : portAddressSet) {
183 for (InterfaceIpAddress ia : portAddresses.ipAddresses()) {
184 if (ia.subnetAddress().contains(targetIp)) {
185 sendProbe(device.id(), port, targetIp,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800186 ia.ipAddress(), portAddresses.mac(),
187 portAddresses.vlan());
Jonathan Harta887ba82014-11-03 15:20:52 -0800188 }
Jonathan Hart09585c62014-09-23 16:58:04 -0700189 }
Jonathan Hart70da5122014-10-01 16:37:42 -0700190 }
Jonathan Hartfca736c2014-09-19 17:26:59 -0700191 }
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700192 }
Jonathan Hartfca736c2014-09-19 17:26:59 -0700193 }
194
Jonathan Hart70da5122014-10-01 16:37:42 -0700195 private void sendProbe(DeviceId deviceId, Port port, IpAddress targetIp,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800196 IpAddress sourceIp, MacAddress sourceMac, VlanId vlan) {
197 Ethernet arpPacket = buildArpRequest(targetIp, sourceIp, sourceMac, vlan);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700198
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700199 List<Instruction> instructions = new ArrayList<>();
200 instructions.add(Instructions.createOutput(port.number()));
201
tom9a693fd2014-10-03 11:32:19 -0700202 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
alshabib010c31d2014-09-26 10:01:12 -0700203 .setOutput(port.number())
204 .build();
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700205
206 OutboundPacket outboundPacket =
207 new DefaultOutboundPacket(deviceId, treatment,
208 ByteBuffer.wrap(arpPacket.serialize()));
209
210 packetService.emit(outboundPacket);
211 }
212
Jonathan Hart70da5122014-10-01 16:37:42 -0700213 private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800214 MacAddress sourceMac, VlanId vlan) {
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700215
216 ARP arp = new ARP();
217 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
Jonathan Hart70da5122014-10-01 16:37:42 -0700218 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
219 .setProtocolType(ARP.PROTO_TYPE_IP)
Pavlin Radoslavov52307e62014-10-29 15:07:37 -0700220 .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH)
Jonathan Hart70da5122014-10-01 16:37:42 -0700221 .setOpCode(ARP.OP_REQUEST);
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700222
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800223 arp.setSenderHardwareAddress(sourceMac.toBytes())
Jonathan Hart70da5122014-10-01 16:37:42 -0700224 .setSenderProtocolAddress(sourceIp.toOctets())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800225 .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
Jonathan Hart70da5122014-10-01 16:37:42 -0700226 .setTargetProtocolAddress(targetIp.toOctets());
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700227
228 Ethernet ethernet = new Ethernet();
229 ethernet.setEtherType(Ethernet.TYPE_ARP)
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800230 .setDestinationMACAddress(MacAddress.BROADCAST)
231 .setSourceMACAddress(sourceMac)
Jonathan Hart70da5122014-10-01 16:37:42 -0700232 .setPayload(arp);
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700233
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800234 if (!vlan.equals(VlanId.NONE)) {
235 ethernet.setVlanID(vlan.toShort());
236 }
237
Jonathan Hart87fbbad2014-09-23 08:43:50 -0700238 return ethernet;
Jonathan Hartfca736c2014-09-19 17:26:59 -0700239 }
240}