blob: 2294a6061256058122b89d2e86343682721d521b [file] [log] [blame]
Jonathan Hartc7ca35d2013-06-25 20:54:25 +12001package net.onrc.onos.ofcontroller.proxyarp;
2
Jonathan Hartc7ca35d2013-06-25 20:54:25 +12003import java.net.InetAddress;
4import java.net.UnknownHostException;
5import java.util.ArrayList;
6import java.util.Collection;
Jonathan Harte93aed42013-12-05 18:39:50 -08007import java.util.HashMap;
Jonathan Hart6261dcd2013-07-22 17:58:35 +12008import java.util.Iterator;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +12009import java.util.List;
10import java.util.Map;
11import java.util.Set;
Jonathan Hart6261dcd2013-07-22 17:58:35 +120012import java.util.Timer;
13import java.util.TimerTask;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +120014
15import net.floodlightcontroller.core.FloodlightContext;
16import net.floodlightcontroller.core.IFloodlightProviderService;
17import net.floodlightcontroller.core.IOFMessageListener;
18import net.floodlightcontroller.core.IOFSwitch;
Jonathan Harte93aed42013-12-05 18:39:50 -080019import net.floodlightcontroller.core.module.FloodlightModuleContext;
20import net.floodlightcontroller.core.module.IFloodlightModule;
21import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart5afde492013-10-01 12:30:53 +130022import net.floodlightcontroller.restserver.IRestApiService;
Jonathan Hart8ec133c2013-06-26 15:25:18 +120023import net.floodlightcontroller.util.MACAddress;
Jonathan Hart18ad55c2013-11-11 22:49:55 -080024import net.onrc.onos.datagrid.IDatagridService;
Jonathan Hart2f790d22013-08-15 14:01:24 +120025import net.onrc.onos.ofcontroller.bgproute.Interface;
Jonathan Hartebba1e12013-10-29 11:37:02 -070026import net.onrc.onos.ofcontroller.core.config.IConfigInfoService;
Jonathan Hart7804bea2014-01-07 10:50:52 -080027import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
Jonathan Hartba9ced92013-11-24 16:52:13 -080028import net.onrc.onos.ofcontroller.util.SwitchPort;
Jonathan Hart96892d12014-03-26 20:21:29 -070029import net.onrc.onos.packet.ARP;
30import net.onrc.onos.packet.Ethernet;
31import net.onrc.onos.packet.IPv4;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +120032
33import org.openflow.protocol.OFMessage;
34import org.openflow.protocol.OFPacketIn;
35import org.openflow.protocol.OFPacketOut;
36import org.openflow.protocol.OFPort;
37import org.openflow.protocol.OFType;
38import org.openflow.protocol.action.OFAction;
39import org.openflow.protocol.action.OFActionOutput;
Jonathan Hart8ec133c2013-06-26 15:25:18 +120040import org.openflow.util.HexString;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +120041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
Jonathan Hart4dfc3652013-08-02 20:22:36 +120044import com.google.common.collect.HashMultimap;
45import com.google.common.collect.Multimaps;
46import com.google.common.collect.SetMultimap;
47
Jonathan Hart18ad55c2013-11-11 22:49:55 -080048public class ProxyArpManager implements IProxyArpService, IOFMessageListener,
Jonathan Hart7804bea2014-01-07 10:50:52 -080049 IPacketOutEventHandler, IArpReplyEventHandler,
50 IFloodlightModule {
Jonathan Hart5b803bc2013-09-23 14:46:11 +120051 private final static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +120052
pingping-lin017a8922013-12-11 11:15:33 +080053 private final long ARP_TIMER_PERIOD = 100; //ms
54
Jonathan Hart18ad9502013-12-15 18:28:00 -080055 private static final int ARP_REQUEST_TIMEOUT = 2000; //ms
Jonathan Hart6261dcd2013-07-22 17:58:35 +120056
Jonathan Harta8887642013-10-28 13:46:54 -070057 private IFloodlightProviderService floodlightProvider;
Jonathan Hart18ad55c2013-11-11 22:49:55 -080058 private IDatagridService datagrid;
Jonathan Harta8887642013-10-28 13:46:54 -070059 private IConfigInfoService configService;
60 private IRestApiService restApi;
Jonathan Hart7804bea2014-01-07 10:50:52 -080061 private IFlowPusherService flowPusher;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +120062
Jonathan Hart1cf9de02013-10-21 17:42:29 -070063 private short vlan;
64 private static final short NO_VLAN = 0;
65
Jonathan Hart18ad9502013-12-15 18:28:00 -080066 //private ArpCache arpCache;
Jonathan Hartdf6ec332013-08-04 01:37:14 +120067
Jonathan Harta8887642013-10-28 13:46:54 -070068 private SetMultimap<InetAddress, ArpRequest> arpRequests;
Jonathan Hart6261dcd2013-07-22 17:58:35 +120069
Jonathan Hartabad6a52013-09-30 18:17:21 +130070 private static class ArpRequest {
Jonathan Hart5b803bc2013-09-23 14:46:11 +120071 private final IArpRequester requester;
Jonathan Hartabad6a52013-09-30 18:17:21 +130072 private final boolean retry;
Naoki Shiota78e403c2014-02-20 17:13:36 -080073 private boolean sent = false;
Jonathan Hart6261dcd2013-07-22 17:58:35 +120074 private long requestTime;
75
Jonathan Hart4dfc3652013-08-02 20:22:36 +120076 public ArpRequest(IArpRequester requester, boolean retry){
Jonathan Hart4dfc3652013-08-02 20:22:36 +120077 this.requester = requester;
78 this.retry = retry;
Jonathan Hart6261dcd2013-07-22 17:58:35 +120079 }
80
Jonathan Hart4dfc3652013-08-02 20:22:36 +120081 public ArpRequest(ArpRequest old) {
82 this.requester = old.requester;
83 this.retry = old.retry;
Jonathan Hart4dfc3652013-08-02 20:22:36 +120084 }
85
Jonathan Hart4dfc3652013-08-02 20:22:36 +120086 public boolean isExpired() {
Naoki Shiota78e403c2014-02-20 17:13:36 -080087 return sent && ((System.currentTimeMillis() - requestTime) > ARP_REQUEST_TIMEOUT);
Jonathan Hart6261dcd2013-07-22 17:58:35 +120088 }
89
Jonathan Hart4dfc3652013-08-02 20:22:36 +120090 public boolean shouldRetry() {
91 return retry;
92 }
93
Jonathan Hartabad6a52013-09-30 18:17:21 +130094 public void dispatchReply(InetAddress ipAddress, MACAddress replyMacAddress) {
Jonathan Hart4dfc3652013-08-02 20:22:36 +120095 requester.arpResponse(ipAddress, replyMacAddress);
Jonathan Hart6261dcd2013-07-22 17:58:35 +120096 }
Naoki Shiota78e403c2014-02-20 17:13:36 -080097
98 public void setRequestTime() {
99 this.requestTime = System.currentTimeMillis();
100 this.sent = true;
101 }
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200102 }
103
Jonathan Hartda4d0e12013-09-30 21:00:20 +1300104 private class HostArpRequester implements IArpRequester {
105 private final ARP arpRequest;
106 private final long dpid;
107 private final short port;
108
109 public HostArpRequester(ARP arpRequest, long dpid, short port) {
110 this.arpRequest = arpRequest;
111 this.dpid = dpid;
112 this.port = port;
113 }
114
115 @Override
116 public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
117 ProxyArpManager.this.sendArpReply(arpRequest, dpid, port, macAddress);
118 }
119 }
120
Jonathan Harte93aed42013-12-05 18:39:50 -0800121 @Override
122 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
123 Collection<Class<? extends IFloodlightService>> l
124 = new ArrayList<Class<? extends IFloodlightService>>();
125 l.add(IProxyArpService.class);
126 return l;
Jonathan Harta8887642013-10-28 13:46:54 -0700127 }
Jonathan Harte93aed42013-12-05 18:39:50 -0800128
129 @Override
130 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
131 Map<Class<? extends IFloodlightService>, IFloodlightService> m
132 = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
133 m.put(IProxyArpService.class, this);
134 return m;
135 }
136
137 @Override
138 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
139 Collection<Class<? extends IFloodlightService>> dependencies
140 = new ArrayList<Class<? extends IFloodlightService>>();
141 dependencies.add(IFloodlightProviderService.class);
Jonathan Harte93aed42013-12-05 18:39:50 -0800142 dependencies.add(IRestApiService.class);
143 dependencies.add(IDatagridService.class);
144 dependencies.add(IConfigInfoService.class);
Jonathan Hart7804bea2014-01-07 10:50:52 -0800145 dependencies.add(IFlowPusherService.class);
Jonathan Harte93aed42013-12-05 18:39:50 -0800146 return dependencies;
147 }
Jonathan Harta8887642013-10-28 13:46:54 -0700148
Jonathan Harte93aed42013-12-05 18:39:50 -0800149 @Override
150 public void init(FloodlightModuleContext context){
151 this.floodlightProvider =
152 context.getServiceImpl(IFloodlightProviderService.class);
Jonathan Harte93aed42013-12-05 18:39:50 -0800153 this.datagrid = context.getServiceImpl(IDatagridService.class);
154 this.configService = context.getServiceImpl(IConfigInfoService.class);
155 this.restApi = context.getServiceImpl(IRestApiService.class);
Jonathan Hart7804bea2014-01-07 10:50:52 -0800156 this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200157
Jonathan Hart18ad9502013-12-15 18:28:00 -0800158 //arpCache = new ArpCache();
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200159
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200160 arpRequests = Multimaps.synchronizedSetMultimap(
161 HashMultimap.<InetAddress, ArpRequest>create());
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800162
Jonathan Hart2f790d22013-08-15 14:01:24 +1200163 }
164
Jonathan Harte93aed42013-12-05 18:39:50 -0800165 @Override
166 public void startUp(FloodlightModuleContext context) {
Jonathan Harta8887642013-10-28 13:46:54 -0700167 this.vlan = configService.getVlan();
Jonathan Hart1cf9de02013-10-21 17:42:29 -0700168 log.info("vlan set to {}", this.vlan);
169
Jonathan Hart5afde492013-10-01 12:30:53 +1300170 restApi.addRestletRoutable(new ArpWebRoutable());
Jonathan Harta8887642013-10-28 13:46:54 -0700171 floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
Jonathan Hart5afde492013-10-01 12:30:53 +1300172
Jonathan Hart7804bea2014-01-07 10:50:52 -0800173 datagrid.registerPacketOutEventHandler(this);
Jonathan Hart016f03b2014-01-23 13:56:43 -0800174 datagrid.registerArpReplyEventHandler(this);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800175
Jonathan Hart4aa2b4e2013-09-24 14:50:23 +1200176 Timer arpTimer = new Timer("arp-processing");
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200177 arpTimer.scheduleAtFixedRate(new TimerTask() {
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200178 @Override
179 public void run() {
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200180 doPeriodicArpProcessing();
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200181 }
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200182 }, 0, ARP_TIMER_PERIOD);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200183 }
184
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200185 /*
186 * Function that runs periodically to manage the asynchronous request mechanism.
187 * It basically cleans up old ARP requests if we don't get a response for them.
188 * The caller can designate that a request should be retried indefinitely, and
189 * this task will handle that as well.
190 */
191 private void doPeriodicArpProcessing() {
192 SetMultimap<InetAddress, ArpRequest> retryList
193 = HashMultimap.<InetAddress, ArpRequest>create();
194
195 //Have to synchronize externally on the Multimap while using an iterator,
196 //even though it's a synchronizedMultimap
Jonathan Hart18ad9502013-12-15 18:28:00 -0800197 synchronized (arpRequests) {
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200198 Iterator<Map.Entry<InetAddress, ArpRequest>> it
199 = arpRequests.entries().iterator();
200
201 while (it.hasNext()) {
202 Map.Entry<InetAddress, ArpRequest> entry
203 = it.next();
204 ArpRequest request = entry.getValue();
205 if (request.isExpired()) {
206 log.debug("Cleaning expired ARP request for {}",
207 entry.getKey().getHostAddress());
208
Jonathan Hart18ad9502013-12-15 18:28:00 -0800209 // If the ARP request is expired and then delete the device
210 // TODO check whether this is OK from this thread
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700211 // TODO: Fix the code below after deviceStorage was removed
212 /*
pingping-lin017a8922013-12-11 11:15:33 +0800213 IDeviceObject targetDevice =
214 deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(entry.getKey()));
Jonathan Hart18ad9502013-12-15 18:28:00 -0800215 if (targetDevice != null) {
216 deviceStorage.removeDevice(targetDevice);
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800217 if (log.isDebugEnabled()) {
218 log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice);
219 }
Jonathan Hartd857ad62013-12-14 18:08:17 -0800220 }
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700221 */
pingping-lin017a8922013-12-11 11:15:33 +0800222
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200223 it.remove();
224
225 if (request.shouldRetry()) {
226 retryList.put(entry.getKey(), request);
227 }
228 }
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200229 }
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200230 }
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200231
232 for (Map.Entry<InetAddress, Collection<ArpRequest>> entry
233 : retryList.asMap().entrySet()) {
234
235 InetAddress address = entry.getKey();
236
237 log.debug("Resending ARP request for {}", address.getHostAddress());
238
pingping-linba5c52f2014-02-11 16:52:01 -0800239 // Only ARP requests sent by the controller will have the retry flag
240 // set, so for now we can just send a new ARP request for that address.
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200241 sendArpRequestForAddress(address);
242
243 for (ArpRequest request : entry.getValue()) {
244 arpRequests.put(address, new ArpRequest(request));
245 }
246 }
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200247 }
248
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200249 @Override
250 public String getName() {
Jonathan Harta18e4792013-10-31 10:10:54 -0700251 return "proxyarpmanager";
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200252 }
253
254 @Override
255 public boolean isCallbackOrderingPrereq(OFType type, String name) {
Jonathan Harta18e4792013-10-31 10:10:54 -0700256 if (type == OFType.PACKET_IN) {
Jonathan Hartd857ad62013-12-14 18:08:17 -0800257 return "devicemanager".equals(name) || "onosdevicemanager".equals(name);
Jonathan Harta18e4792013-10-31 10:10:54 -0700258 }
259 else {
260 return false;
261 }
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200262 }
263
264 @Override
265 public boolean isCallbackOrderingPostreq(OFType type, String name) {
Jonathan Hartd857ad62013-12-14 18:08:17 -0800266 return type == OFType.PACKET_IN && "onosforwarding".equals(name);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200267 }
268
269 @Override
270 public Command receive(
271 IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
272
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200273 OFPacketIn pi = (OFPacketIn) msg;
274
275 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
276 IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
277
278 if (eth.getEtherType() == Ethernet.TYPE_ARP){
Jonathan Hart5ea7cc02013-11-12 11:56:23 -0800279 ARP arp = (ARP) eth.getPayload();
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200280 if (arp.getOpCode() == ARP.OP_REQUEST) {
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800281 handleArpRequest(sw, pi, arp, eth);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200282 }
283 else if (arp.getOpCode() == ARP.OP_REPLY) {
Jonathan Hart016f03b2014-01-23 13:56:43 -0800284 // For replies we simply send a notification via Hazelcast
Jonathan Hartc6325622014-01-14 16:37:50 -0800285 sendArpReplyNotification(eth, pi);
Jonathan Hart016f03b2014-01-23 13:56:43 -0800286
287 //handleArpReply(sw, pi, arp);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200288 }
Jonathan Hart17672992013-12-12 16:15:16 -0800289
290 // Stop ARP packets here
291 return Command.STOP;
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200292 }
293
Jonathan Hart17672992013-12-12 16:15:16 -0800294 // Propagate everything else
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200295 return Command.CONTINUE;
296 }
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200297
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800298 private void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp, Ethernet eth) {
Jonathan Hart08ee8522013-09-22 17:34:43 +1200299 if (log.isTraceEnabled()) {
300 log.trace("ARP request received for {}",
301 inetAddressToString(arp.getTargetProtocolAddress()));
302 }
Jonathan Hart2f790d22013-08-15 14:01:24 +1200303
304 InetAddress target;
305 try {
pingping-linb8757bf2013-12-13 01:48:58 +0800306 target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
Jonathan Hart2f790d22013-08-15 14:01:24 +1200307 } catch (UnknownHostException e) {
308 log.debug("Invalid address in ARP request", e);
309 return;
310 }
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200311
Jonathan Harta8887642013-10-28 13:46:54 -0700312 if (configService.fromExternalNetwork(sw.getId(), pi.getInPort())) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200313 //If the request came from outside our network, we only care if
314 //it was a request for one of our interfaces.
Jonathan Harta8887642013-10-28 13:46:54 -0700315 if (configService.isInterfaceAddress(target)) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200316 log.trace("ARP request for our interface. Sending reply {} => {}",
Jonathan Harta8887642013-10-28 13:46:54 -0700317 target.getHostAddress(), configService.getRouterMacAddress());
pingping-linb8757bf2013-12-13 01:48:58 +0800318
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200319 sendArpReply(arp, sw.getId(), pi.getInPort(),
Jonathan Harta8887642013-10-28 13:46:54 -0700320 configService.getRouterMacAddress());
Jonathan Hart2f790d22013-08-15 14:01:24 +1200321 }
pingping-linb8757bf2013-12-13 01:48:58 +0800322
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200323 return;
324 }
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200325
Jonathan Harta18e4792013-10-31 10:10:54 -0700326 //MACAddress macAddress = arpCache.lookup(target);
pingping-linb8757bf2013-12-13 01:48:58 +0800327
328 arpRequests.put(target, new ArpRequest(
329 new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
330
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700331 // TODO: Fix the code below after deviceStorage was removed
332 /*
Jonathan Hart18ad9502013-12-15 18:28:00 -0800333 IDeviceObject targetDevice =
334 deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700335 */
Pavlin Radoslavov4cf8ee52014-03-26 18:19:58 -0700336
337 // TODO: Fix the code below after deviceStorage was removed
338 /*
Jonathan Hart18ad9502013-12-15 18:28:00 -0800339 if (targetDevice == null) {
340 if (log.isTraceEnabled()) {
341 log.trace("No device info found for {} - broadcasting",
342 target.getHostAddress());
343 }
344
345 // We don't know the device so broadcast the request out
Jonathan Hart7804bea2014-01-07 10:50:52 -0800346 datagrid.sendPacketOutNotification(
Naoki Shiota78e403c2014-02-20 17:13:36 -0800347 new BroadcastPacketOutNotification(eth.serialize(),
348 target, sw.getId(), pi.getInPort()));
Jonathan Hart18ad9502013-12-15 18:28:00 -0800349 }
350 else {
351 // Even if the device exists in our database, we do not reply to
352 // the request directly, but check whether the device is still valid
Jonathan Harta18e4792013-10-31 10:10:54 -0700353 MACAddress macAddress = MACAddress.valueOf(targetDevice.getMACAddress());
pingping-linb8757bf2013-12-13 01:48:58 +0800354
Jonathan Harta18e4792013-10-31 10:10:54 -0700355 if (log.isTraceEnabled()) {
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800356 log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}",
Jonathan Hart18ad9502013-12-15 18:28:00 -0800357 new Object [] {
Jonathan Harta18e4792013-10-31 10:10:54 -0700358 inetAddressToString(arp.getTargetProtocolAddress()),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800359 macAddress,
Jonathan Harta18e4792013-10-31 10:10:54 -0700360 HexString.toHexString(sw.getId()), pi.getInPort()});
361 }
pingping-linb8757bf2013-12-13 01:48:58 +0800362
363 // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
364
Jonathan Hart18ad9502013-12-15 18:28:00 -0800365 Iterable<IPortObject> outPorts = targetDevice.getAttachedPorts();
pingping-linb8757bf2013-12-13 01:48:58 +0800366
Jonathan Hart18ad9502013-12-15 18:28:00 -0800367 if (!outPorts.iterator().hasNext()){
368 if (log.isTraceEnabled()) {
369 log.trace("Device {} exists but is not connected to any ports" +
370 " - broadcasting", macAddress);
371 }
372
Jonathan Hart7804bea2014-01-07 10:50:52 -0800373 datagrid.sendPacketOutNotification(
374 new BroadcastPacketOutNotification(eth.serialize(),
Naoki Shiota78e403c2014-02-20 17:13:36 -0800375 target, sw.getId(), pi.getInPort()));
Jonathan Hart18ad9502013-12-15 18:28:00 -0800376 }
377 else {
pingping-linb8757bf2013-12-13 01:48:58 +0800378 for (IPortObject portObject : outPorts) {
Jonathan Hart7804bea2014-01-07 10:50:52 -0800379 //long outSwitch = 0;
380 //short outPort = 0;
pingping-linb8757bf2013-12-13 01:48:58 +0800381
Pavlin Radoslavov4cf8ee52014-03-26 18:19:58 -0700382 // if (!portObject.getLinkedPorts().iterator().hasNext()) {
383 // outPort = portObject.getNumber();
384 // }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800385 if (portObject.getLinkedPorts().iterator().hasNext()) {
386 continue;
pingping-linb8757bf2013-12-13 01:48:58 +0800387 }
pingping-linb8757bf2013-12-13 01:48:58 +0800388
Jonathan Hart7804bea2014-01-07 10:50:52 -0800389 short outPort = portObject.getNumber();
pingping-lin568c6012013-12-14 05:57:11 +0800390 ISwitchObject outSwitchObject = portObject.getSwitch();
Jonathan Hart7804bea2014-01-07 10:50:52 -0800391 long outSwitch = HexString.toLong(outSwitchObject.getDPID());
Jonathan Hart18ad9502013-12-15 18:28:00 -0800392
393 if (log.isTraceEnabled()) {
394 log.trace("Probing device {} on port {}/{}",
395 new Object[] {macAddress,
396 HexString.toHexString(outSwitch), outPort});
397 }
pingping-lin568c6012013-12-14 05:57:11 +0800398
Jonathan Hart7804bea2014-01-07 10:50:52 -0800399 datagrid.sendPacketOutNotification(
400 new SinglePacketOutNotification(eth.serialize(),
Naoki Shiota78e403c2014-02-20 17:13:36 -0800401 target, outSwitch, outPort));
pingping-linb8757bf2013-12-13 01:48:58 +0800402 }
Jonathan Hart08ee8522013-09-22 17:34:43 +1200403 }
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200404 }
Pavlin Radoslavov4cf8ee52014-03-26 18:19:58 -0700405 */
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200406 }
407
Jonathan Hart1912afc2013-10-11 12:02:44 +1300408 private void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
Jonathan Hart08ee8522013-09-22 17:34:43 +1200409 if (log.isTraceEnabled()) {
410 log.trace("ARP reply recieved: {} => {}, on {}/{}", new Object[] {
411 inetAddressToString(arp.getSenderProtocolAddress()),
412 HexString.toHexString(arp.getSenderHardwareAddress()),
413 HexString.toHexString(sw.getId()), pi.getInPort()});
414 }
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200415
Jonathan Hartabad6a52013-09-30 18:17:21 +1300416 InetAddress senderIpAddress;
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200417 try {
Jonathan Hartabad6a52013-09-30 18:17:21 +1300418 senderIpAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200419 } catch (UnknownHostException e) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200420 log.debug("Invalid address in ARP reply", e);
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200421 return;
422 }
423
Jonathan Hartabad6a52013-09-30 18:17:21 +1300424 MACAddress senderMacAddress = MACAddress.valueOf(arp.getSenderHardwareAddress());
425
Jonathan Hartabad6a52013-09-30 18:17:21 +1300426 //See if anyone's waiting for this ARP reply
427 Set<ArpRequest> requests = arpRequests.get(senderIpAddress);
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200428
429 //Synchronize on the Multimap while using an iterator for one of the sets
Jonathan Harte751e1c2013-08-23 00:48:47 +1200430 List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(requests.size());
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200431 synchronized (arpRequests) {
432 Iterator<ArpRequest> it = requests.iterator();
433 while (it.hasNext()) {
434 ArpRequest request = it.next();
435 it.remove();
Jonathan Harte751e1c2013-08-23 00:48:47 +1200436 requestsToSend.add(request);
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200437 }
438 }
Jonathan Harte751e1c2013-08-23 00:48:47 +1200439
440 //Don't hold an ARP lock while dispatching requests
441 for (ArpRequest request : requestsToSend) {
Jonathan Hartabad6a52013-09-30 18:17:21 +1300442 request.dispatchReply(senderIpAddress, senderMacAddress);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200443 }
444 }
445
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200446 private void sendArpRequestForAddress(InetAddress ipAddress) {
Jonathan Hart08ee8522013-09-22 17:34:43 +1200447 //TODO what should the sender IP address and MAC address be if no
448 //IP addresses are configured? Will there ever be a need to send
449 //ARP requests from the controller in that case?
450 //All-zero MAC address doesn't seem to work - hosts don't respond to it
451
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200452 byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
453 byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
Jonathan Hart08ee8522013-09-22 17:34:43 +1200454 byte[] genericNonZeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x01};
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200455 byte[] broadcastMac = {(byte)0xff, (byte)0xff, (byte)0xff,
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200456 (byte)0xff, (byte)0xff, (byte)0xff};
457
458 ARP arpRequest = new ARP();
459
460 arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
461 .setProtocolType(ARP.PROTO_TYPE_IP)
462 .setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
Jonathan Hart08ee8522013-09-22 17:34:43 +1200463 .setProtocolAddressLength((byte)IPv4.ADDRESS_LENGTH)
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200464 .setOpCode(ARP.OP_REQUEST)
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200465 .setTargetHardwareAddress(zeroMac)
466 .setTargetProtocolAddress(ipAddress.getAddress());
Jonathan Hart2f790d22013-08-15 14:01:24 +1200467
Jonathan Harta8887642013-10-28 13:46:54 -0700468 MACAddress routerMacAddress = configService.getRouterMacAddress();
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200469 //TODO hack for now as it's unclear what the MAC address should be
470 byte[] senderMacAddress = genericNonZeroMac;
Jonathan Hart08ee8522013-09-22 17:34:43 +1200471 if (routerMacAddress != null) {
472 senderMacAddress = routerMacAddress.toBytes();
Jonathan Hart2f790d22013-08-15 14:01:24 +1200473 }
Jonathan Hart08ee8522013-09-22 17:34:43 +1200474 arpRequest.setSenderHardwareAddress(senderMacAddress);
475
476 byte[] senderIPAddress = zeroIpv4;
Jonathan Harta8887642013-10-28 13:46:54 -0700477 Interface intf = configService.getOutgoingInterface(ipAddress);
Jonathan Hart08ee8522013-09-22 17:34:43 +1200478 if (intf != null) {
479 senderIPAddress = intf.getIpAddress().getAddress();
480 }
Jonathan Hart2f790d22013-08-15 14:01:24 +1200481
482 arpRequest.setSenderProtocolAddress(senderIPAddress);
483
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200484 Ethernet eth = new Ethernet();
Jonathan Hart08ee8522013-09-22 17:34:43 +1200485 eth.setSourceMACAddress(senderMacAddress)
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200486 .setDestinationMACAddress(broadcastMac)
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200487 .setEtherType(Ethernet.TYPE_ARP)
488 .setPayload(arpRequest);
489
Jonathan Hart1cf9de02013-10-21 17:42:29 -0700490 if (vlan != NO_VLAN) {
491 eth.setVlanID(vlan)
492 .setPriorityCode((byte)0);
493 }
494
pingping-linba5c52f2014-02-11 16:52:01 -0800495 //sendArpRequestToSwitches(ipAddress, eth.serialize());
Naoki Shiota78e403c2014-02-20 17:13:36 -0800496 datagrid.sendPacketOutNotification(new SinglePacketOutNotification(eth.serialize(),
497 ipAddress, intf.getDpid(),intf.getPort()));
Jonathan Hart2f790d22013-08-15 14:01:24 +1200498 }
499
500 private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200501 sendArpRequestToSwitches(dstAddress, arpRequest,
502 0, OFPort.OFPP_NONE.getValue());
Jonathan Hart2f790d22013-08-15 14:01:24 +1200503 }
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200504
Jonathan Hart2f790d22013-08-15 14:01:24 +1200505 private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest,
506 long inSwitch, short inPort) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200507
Jonathan Harta8887642013-10-28 13:46:54 -0700508 if (configService.hasLayer3Configuration()) {
509 Interface intf = configService.getOutgoingInterface(dstAddress);
Jonathan Hart08ee8522013-09-22 17:34:43 +1200510 if (intf != null) {
511 sendArpRequestOutPort(arpRequest, intf.getDpid(), intf.getPort());
512 }
513 else {
514 //TODO here it should be broadcast out all non-interface edge ports.
515 //I think we can assume that if it's not a request for an external
516 //network, it's an ARP for a host in our own network. So we want to
517 //send it out all edge ports that don't have an interface configured
518 //to ensure it reaches all hosts in our network.
519 log.debug("No interface found to send ARP request for {}",
520 dstAddress.getHostAddress());
521 }
522 }
523 else {
pingping-linba5c52f2014-02-11 16:52:01 -0800524 //broadcastArpRequestOutEdge(arpRequest, inSwitch, inPort);
525 broadcastArpRequestOutMyEdge(arpRequest, inSwitch, inPort);
Jonathan Hart08ee8522013-09-22 17:34:43 +1200526 }
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200527 }
528
Jonathan Hartc6325622014-01-14 16:37:50 -0800529 private void sendArpReplyNotification(Ethernet eth, OFPacketIn pi) {
pingping-lin017a8922013-12-11 11:15:33 +0800530 ARP arp = (ARP) eth.getPayload();
531
532 if (log.isTraceEnabled()) {
Jonathan Hart18ad9502013-12-15 18:28:00 -0800533 log.trace("Sending ARP reply for {} to other ONOS instances",
534 inetAddressToString(arp.getSenderProtocolAddress()));
pingping-lin017a8922013-12-11 11:15:33 +0800535 }
536
537 InetAddress targetAddress;
538 MACAddress mac = new MACAddress(arp.getSenderHardwareAddress());
539
540 try {
Jonathan Hart18ad9502013-12-15 18:28:00 -0800541 targetAddress = InetAddress.getByAddress(arp.getSenderProtocolAddress());
pingping-lin017a8922013-12-11 11:15:33 +0800542 } catch (UnknownHostException e) {
Jonathan Hart18ad9502013-12-15 18:28:00 -0800543 log.error("Unknown host", e);
544 return;
pingping-lin017a8922013-12-11 11:15:33 +0800545 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800546
547 datagrid.sendArpReplyNotification(new ArpReplyNotification(targetAddress, mac));
pingping-lin017a8922013-12-11 11:15:33 +0800548 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800549
Jonathan Hartf9bd98d2013-12-13 11:40:55 -0800550 private void broadcastArpRequestOutMyEdge(byte[] arpRequest,
551 long inSwitch, short inPort) {
Jonathan Hartba9ced92013-11-24 16:52:13 -0800552 List<SwitchPort> switchPorts = new ArrayList<SwitchPort>();
553
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800554 for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
555
556 OFPacketOut po = new OFPacketOut();
557 po.setInPort(OFPort.OFPP_NONE)
558 .setBufferId(-1)
559 .setPacketData(arpRequest);
560
561 List<OFAction> actions = new ArrayList<OFAction>();
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700562
563 // TODO: Fix the code below after topoSwitchService was removed
564 /*
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800565 Iterable<IPortObject> ports
566 = topoSwitchService.getPortsOnSwitch(sw.getStringId());
567 if (ports == null) {
568 continue;
569 }
570
571 for (IPortObject portObject : ports) {
572 if (!portObject.getLinkedPorts().iterator().hasNext()) {
Jonathan Hartf9bd98d2013-12-13 11:40:55 -0800573 short portNumber = portObject.getNumber();
574
575 if (sw.getId() == inSwitch && portNumber == inPort) {
576 // This is the port that the ARP message came in,
577 // so don't broadcast out this port
578 continue;
579 }
580
Jonathan Hartba9ced92013-11-24 16:52:13 -0800581 switchPorts.add(new SwitchPort(new Dpid(sw.getId()),
Jonathan Hartf9bd98d2013-12-13 11:40:55 -0800582 new Port(portNumber)));
583 actions.add(new OFActionOutput(portNumber));
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800584 }
585 }
Pavlin Radoslavov5fe71882014-03-21 16:27:21 -0700586 */
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800587
588 po.setActions(actions);
589 short actionsLength = (short)
590 (actions.size() * OFActionOutput.MINIMUM_LENGTH);
591 po.setActionsLength(actionsLength);
592 po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
593 + arpRequest.length);
594
Jonathan Hart7804bea2014-01-07 10:50:52 -0800595 flowPusher.add(sw, po);
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800596 }
Jonathan Hartba9ced92013-11-24 16:52:13 -0800597
Jonathan Hart18ad9502013-12-15 18:28:00 -0800598 if (log.isTraceEnabled()) {
599 log.trace("Broadcast ARP request to: {}", switchPorts);
600 }
Jonathan Hart9a21e0d2013-11-14 15:09:09 -0800601 }
602
Jonathan Hart2f790d22013-08-15 14:01:24 +1200603 private void sendArpRequestOutPort(byte[] arpRequest, long dpid, short port) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200604 if (log.isTraceEnabled()) {
605 log.trace("Sending ARP request out {}/{}",
606 HexString.toHexString(dpid), port);
607 }
Jonathan Hart2f790d22013-08-15 14:01:24 +1200608
609 OFPacketOut po = new OFPacketOut();
610 po.setInPort(OFPort.OFPP_NONE)
611 .setBufferId(-1)
612 .setPacketData(arpRequest);
613
614 List<OFAction> actions = new ArrayList<OFAction>();
615 actions.add(new OFActionOutput(port));
616 po.setActions(actions);
617 short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
618 po.setActionsLength(actionsLength);
619 po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength
620 + arpRequest.length);
621
622 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
623
624 if (sw == null) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200625 log.warn("Switch not found when sending ARP request");
Jonathan Hart2f790d22013-08-15 14:01:24 +1200626 return;
627 }
628
Jonathan Hart7804bea2014-01-07 10:50:52 -0800629 flowPusher.add(sw, po);
Jonathan Hart2f790d22013-08-15 14:01:24 +1200630 }
631
Jonathan Hartda4d0e12013-09-30 21:00:20 +1300632 private void sendArpReply(ARP arpRequest, long dpid, short port, MACAddress targetMac) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200633 if (log.isTraceEnabled()) {
634 log.trace("Sending reply {} => {} to {}", new Object[] {
635 inetAddressToString(arpRequest.getTargetProtocolAddress()),
Jonathan Hartabad6a52013-09-30 18:17:21 +1300636 targetMac,
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200637 inetAddressToString(arpRequest.getSenderProtocolAddress())});
638 }
Jonathan Hart1633a402013-08-24 11:38:56 +1200639
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200640 ARP arpReply = new ARP();
641 arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
642 .setProtocolType(ARP.PROTO_TYPE_IP)
643 .setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
Jonathan Hart08ee8522013-09-22 17:34:43 +1200644 .setProtocolAddressLength((byte)IPv4.ADDRESS_LENGTH)
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200645 .setOpCode(ARP.OP_REPLY)
Jonathan Hartabad6a52013-09-30 18:17:21 +1300646 .setSenderHardwareAddress(targetMac.toBytes())
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200647 .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
648 .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
649 .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
650
Jonathan Hart1cf9de02013-10-21 17:42:29 -0700651
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200652 Ethernet eth = new Ethernet();
653 eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
Jonathan Hartabad6a52013-09-30 18:17:21 +1300654 .setSourceMACAddress(targetMac.toBytes())
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200655 .setEtherType(Ethernet.TYPE_ARP)
656 .setPayload(arpReply);
657
Jonathan Hart1cf9de02013-10-21 17:42:29 -0700658 if (vlan != NO_VLAN) {
659 eth.setVlanID(vlan)
660 .setPriorityCode((byte)0);
661 }
662
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200663 List<OFAction> actions = new ArrayList<OFAction>();
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200664 actions.add(new OFActionOutput(port));
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200665
666 OFPacketOut po = new OFPacketOut();
667 po.setInPort(OFPort.OFPP_NONE)
668 .setBufferId(-1)
Jonathan Hart8ec133c2013-06-26 15:25:18 +1200669 .setPacketData(eth.serialize())
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200670 .setActions(actions)
671 .setActionsLength((short)OFActionOutput.MINIMUM_LENGTH)
672 .setLengthU(OFPacketOut.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH
673 + po.getPacketData().length);
674
675 List<OFMessage> msgList = new ArrayList<OFMessage>();
676 msgList.add(po);
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200677
678 IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
679
680 if (sw == null) {
Jonathan Hart5b803bc2013-09-23 14:46:11 +1200681 log.warn("Switch {} not found when sending ARP reply",
Jonathan Hart1633a402013-08-24 11:38:56 +1200682 HexString.toHexString(dpid));
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200683 return;
684 }
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200685
Jonathan Hart7804bea2014-01-07 10:50:52 -0800686 flowPusher.add(sw, po);
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200687 }
Jonathan Hartda4d0e12013-09-30 21:00:20 +1300688
689 private String inetAddressToString(byte[] bytes) {
690 try {
691 return InetAddress.getByAddress(bytes).getHostAddress();
692 } catch (UnknownHostException e) {
693 log.debug("Invalid IP address", e);
694 return "";
695 }
696 }
697
698 /*
699 * IProxyArpService methods
700 */
Jonathan Hartc824ad02013-07-03 15:58:45 +1200701
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200702 @Override
Jonathan Hartabad6a52013-09-30 18:17:21 +1300703 public MACAddress getMacAddress(InetAddress ipAddress) {
Jonathan Hart18ad9502013-12-15 18:28:00 -0800704 //return arpCache.lookup(ipAddress);
705 return null;
Jonathan Hart6261dcd2013-07-22 17:58:35 +1200706 }
Jonathan Hart4dfc3652013-08-02 20:22:36 +1200707
708 @Override
709 public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
710 boolean retry) {
Jonathan Hartdf6ec332013-08-04 01:37:14 +1200711 arpRequests.put(ipAddress, new ArpRequest(requester, retry));
Jonathan Hartf0c0dcb2013-07-24 15:28:42 +1200712
Jonathan Hart6e618212013-08-21 22:28:43 +1200713 //Sanity check to make sure we don't send a request for our own address
Jonathan Harta8887642013-10-28 13:46:54 -0700714 if (!configService.isInterfaceAddress(ipAddress)) {
Jonathan Hart6e618212013-08-21 22:28:43 +1200715 sendArpRequestForAddress(ipAddress);
716 }
717 }
Jonathan Hart5afde492013-10-01 12:30:53 +1300718
719 @Override
720 public List<String> getMappings() {
Jonathan Hart18ad9502013-12-15 18:28:00 -0800721 //return arpCache.getMappings();
722 return new ArrayList<String>();
Jonathan Hart5afde492013-10-01 12:30:53 +1300723 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800724
725 /*
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800726 @Override
Jonathan Hartd3003252013-11-15 09:44:46 -0800727 public void arpRequestNotification(ArpMessage arpMessage) {
pingping-lin017a8922013-12-11 11:15:33 +0800728 log.debug("Received ARP notification from other instances");
pingping-linb8757bf2013-12-13 01:48:58 +0800729
Jonathan Hartd3003252013-11-15 09:44:46 -0800730 switch (arpMessage.getType()){
731 case REQUEST:
pingping-linb8757bf2013-12-13 01:48:58 +0800732 if(arpMessage.getOutSwitch() == -1 || arpMessage.getOutPort() == -1){
Jonathan Hartf9bd98d2013-12-13 11:40:55 -0800733 broadcastArpRequestOutMyEdge(arpMessage.getPacket(),
734 arpMessage.getInSwitch(), arpMessage.getInPort());
pingping-linb8757bf2013-12-13 01:48:58 +0800735 }else{
736 sendArpRequestOutPort(arpMessage.getPacket(),arpMessage.getOutSwitch(),arpMessage.getOutPort());
737 log.debug("OutSwitch in ARP request message is: {}; OutPort in ARP request message is: {}",arpMessage.getOutSwitch(),arpMessage.getOutPort());
738 }
Jonathan Hartd3003252013-11-15 09:44:46 -0800739 break;
740 case REPLY:
Jonathan Hartba9ced92013-11-24 16:52:13 -0800741 log.debug("Received ARP reply notification for {}",
742 arpMessage.getAddress());
pingping-lin017a8922013-12-11 11:15:33 +0800743 sendArpReplyToWaitingRequesters(arpMessage.getAddress(),arpMessage.getMAC());
Jonathan Hartd3003252013-11-15 09:44:46 -0800744 break;
745 }
746 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800747 */
Jonathan Hartd3003252013-11-15 09:44:46 -0800748
pingping-lin017a8922013-12-11 11:15:33 +0800749 private void sendArpReplyToWaitingRequesters(InetAddress address, MACAddress mac) {
Jonathan Hartd3003252013-11-15 09:44:46 -0800750 log.debug("Sending ARP reply for {} to requesters",
751 address.getHostAddress());
752
753 //See if anyone's waiting for this ARP reply
754 Set<ArpRequest> requests = arpRequests.get(address);
755
756 //Synchronize on the Multimap while using an iterator for one of the sets
757 List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(requests.size());
758 synchronized (arpRequests) {
759 Iterator<ArpRequest> it = requests.iterator();
760 while (it.hasNext()) {
761 ArpRequest request = it.next();
762 it.remove();
763 requestsToSend.add(request);
764 }
765 }
766
pingping-lin017a8922013-12-11 11:15:33 +0800767 /*IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
Jonathan Hartd3003252013-11-15 09:44:46 -0800768 InetAddresses.coerceToInteger(address));
769
770 MACAddress mac = MACAddress.valueOf(deviceObject.getMACAddress());
771
772 log.debug("Found {} at {} in network map",
pingping-lin017a8922013-12-11 11:15:33 +0800773 address.getHostAddress(), mac);*/
Jonathan Hartd3003252013-11-15 09:44:46 -0800774
775 //Don't hold an ARP lock while dispatching requests
776 for (ArpRequest request : requestsToSend) {
777 request.dispatchReply(address, mac);
778 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800779 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800780
781 @Override
782 public void arpReplyEvent(ArpReplyNotification arpReply) {
783 log.debug("Received ARP reply notification for {}",
784 arpReply.getTargetAddress());
785 sendArpReplyToWaitingRequesters(arpReply.getTargetAddress(),
786 arpReply.getTargetMacAddress());
787 }
788
789 @Override
790 public void packetOutNotification(
791 PacketOutNotification packetOutNotification) {
792
793 if (packetOutNotification instanceof SinglePacketOutNotification) {
794 SinglePacketOutNotification notification =
795 (SinglePacketOutNotification) packetOutNotification;
796 sendArpRequestOutPort(notification.packet, notification.getOutSwitch(),
797 notification.getOutPort());
Naoki Shiota78e403c2014-02-20 17:13:36 -0800798
799 // set timestamp
800 InetAddress addr = notification.getTargetAddress();
801 if (addr != null) {
802 for (ArpRequest request : arpRequests.get(addr)) {
803 request.setRequestTime();
804 }
805 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800806 }
807 else if (packetOutNotification instanceof BroadcastPacketOutNotification) {
808 BroadcastPacketOutNotification notification =
809 (BroadcastPacketOutNotification) packetOutNotification;
810 broadcastArpRequestOutMyEdge(notification.packet,
811 notification.getInSwitch(), notification.getInPort());
Naoki Shiota78e403c2014-02-20 17:13:36 -0800812
813 // set timestamp
814 InetAddress addr = notification.getTargetAddress();
815 if (addr != null) {
816 for (ArpRequest request : arpRequests.get(addr)) {
817 request.setRequestTime();
818 }
819 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800820 }
821 else {
822 log.warn("Unknown packet out notification received");
823 }
824 }
Jonathan Hartc7ca35d2013-06-25 20:54:25 +1200825}