X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Farphandler%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Farphandler%2Finternal%2FArpHandler.java;h=e345d65f7e527754981de650e8c75e47a72b47d8;hp=f3b22c75d8102a76beeb78229e7faabb89e60bd5;hb=9438cd96bbebb06f5b67c81f313eacd6e382f0d7;hpb=65662c5141097ed382ad2037ad4a78a9965aad22 diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java index f3b22c75d8..e345d65f7e 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java @@ -52,7 +52,6 @@ import org.opendaylight.controller.sal.packet.IPv4; import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.controller.sal.packet.PacketResult; import org.opendaylight.controller.sal.packet.RawPacket; -import org.opendaylight.controller.sal.topology.TopoEdgeUpdate; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NetUtils; @@ -76,7 +75,8 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA private ConcurrentMap countDownTimers; private Timer periodicTimer; private BlockingQueue ARPCacheEvents = new LinkedBlockingQueue(); - Thread cacheEventHandler; + private Thread cacheEventHandler; + private boolean stopping = false; /* * A cluster allocated cache. Used for synchronizing ARP request/reply * events across all cluster controllers. To raise an event, we put() a specific @@ -155,22 +155,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA byte[] tMAC, InetAddress tIP) { byte[] senderIP = sIP.getAddress(); byte[] targetIP = tIP.getAddress(); - ARP arp = new ARP(); - arp.setHardwareType(ARP.HW_TYPE_ETHERNET) - .setProtocolType(EtherTypes.IPv4.shortValue()) - .setHardwareAddressLength((byte) 6) - .setProtocolAddressLength((byte) 4) - .setOpCode(ARP.REPLY) - .setSenderHardwareAddress(sMAC) - .setSenderProtocolAddress(senderIP) - .setTargetHardwareAddress(tMAC) - .setTargetProtocolAddress(targetIP); + ARP arp = createARP(ARP.REPLY,sMAC,senderIP,tMAC,targetIP); - Ethernet ethernet = new Ethernet(); - ethernet.setSourceMACAddress(sMAC) - .setDestinationMACAddress(tMAC) - .setEtherType(EtherTypes.ARP.shortValue()) - .setPayload(arp); + Ethernet ethernet = createEthernet(sMAC, tMAC, arp); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); destPkt.setOutgoingNodeConnector(p); @@ -224,7 +211,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA try { requestor = new HostNodeConnector(sourceMAC, sourceIP, p, subnet.getVlan()); } catch (ConstructionException e) { - log.debug("Received ARP packet with invalid MAC: {}", sourceMAC); + log.debug("Received ARP packet with invalid MAC: {}", HexEncode.bytesToHexString(sourceMAC)); return; } /* @@ -268,7 +255,8 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA && (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(targetMAC, getControllerMAC()))) { if (connectionManager.isLocal(p.getNode())){ if (log.isTraceEnabled()){ - log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}", getControllerMAC()); + log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}", + HexEncode.bytesToHexString(getControllerMAC())); } sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP); } else { @@ -297,7 +285,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA //Raise a bcast request event, all controllers need to send one log.trace("Sending a bcast ARP request for {}", targetIP); arpRequestReplyEvent.put(new ARPRequest(targetIP, subnet), false); - } else { /* * Target host known (across the cluster), send ARP REPLY make sure that targetMAC @@ -337,6 +324,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA * the targetIP as the target Network Address */ protected void sendBcastARPRequest(InetAddress targetIP, Subnet subnet) { + log.trace("sendBcatARPRequest targetIP:{} subnet:{}", targetIP, subnet); Set nodeConnectors; if (subnet.isFlatLayer2()) { nodeConnectors = new HashSet(); @@ -346,36 +334,19 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } else { nodeConnectors = subnet.getNodeConnectors(); } - + byte[] targetHardwareAddress = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }; for (NodeConnector p : nodeConnectors) { - //fiter out any non-local or internal ports if (! connectionManager.isLocal(p.getNode()) || topologyManager.isInternal(p)) { continue; } - ARP arp = new ARP(); + log.trace("Sending toward nodeConnector:{}", p); byte[] senderIP = subnet.getNetworkAddress().getAddress(); byte[] targetIPByte = targetIP.getAddress(); - arp.setHardwareType(ARP.HW_TYPE_ETHERNET) - .setProtocolType(EtherTypes.IPv4.shortValue()) - .setHardwareAddressLength((byte) 6) - .setProtocolAddressLength((byte) 4) - .setOpCode(ARP.REQUEST) - .setSenderHardwareAddress(getControllerMAC()) - .setSenderProtocolAddress(senderIP) - .setTargetHardwareAddress( - new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }) - .setTargetProtocolAddress(targetIPByte); - - Ethernet ethernet = new Ethernet(); - ethernet.setSourceMACAddress(getControllerMAC()) - .setDestinationMACAddress(new byte[] {(byte) -1, - (byte) -1, - (byte) -1, - (byte) -1, - (byte) -1, - (byte) -1 }) - .setEtherType(EtherTypes.ARP.shortValue()).setPayload(arp); + ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetHardwareAddress, targetIPByte); + + byte[] destMACAddress = NetUtils.getBroadcastMACAddr(); + Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp); // TODO For now send port-by-port, see how to optimize to // send to multiple ports at once @@ -393,7 +364,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA * The sender MAC is the controller's MAC */ protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) { - + log.trace("sendUcastARPRequest host:{} subnet:{}", host, subnet); NodeConnector outPort = host.getnodeConnector(); if (outPort == null) { log.error("Failed sending UcastARP because cannot extract output port from Host: {}", host); @@ -403,22 +374,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA byte[] senderIP = subnet.getNetworkAddress().getAddress(); byte[] targetIP = host.getNetworkAddress().getAddress(); byte[] targetMAC = host.getDataLayerAddressBytes(); - ARP arp = new ARP(); - arp.setHardwareType(ARP.HW_TYPE_ETHERNET) - .setProtocolType(EtherTypes.IPv4.shortValue()) - .setHardwareAddressLength((byte) 6) - .setProtocolAddressLength((byte) 4) - .setOpCode(ARP.REQUEST) - .setSenderHardwareAddress(getControllerMAC()) - .setSenderProtocolAddress(senderIP) - .setTargetHardwareAddress(targetMAC) - .setTargetProtocolAddress(targetIP); + ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetMAC, targetIP); - Ethernet ethernet = new Ethernet(); - ethernet.setSourceMACAddress(getControllerMAC()) - .setDestinationMACAddress(targetMAC) - .setEtherType(EtherTypes.ARP.shortValue()) - .setPayload(arp); + Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); destPkt.setOutgoingNodeConnector(outPort); @@ -426,6 +384,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA this.dataPacketService.transmitDataPacket(destPkt); } + @Override public void find(InetAddress networkAddress) { log.trace("Received find IP {}", networkAddress); @@ -445,6 +404,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA /* * Probe the host by sending a unicast ARP Request to the host */ + @Override public void probe(HostNodeConnector host) { log.trace("Received probe host {}", host); @@ -562,6 +522,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA * */ void destroy() { + cacheEventHandler.interrupt(); } /** @@ -571,9 +532,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA * */ void start() { + stopping = false; startPeriodicTimer(); cacheEventHandler.start(); - } /** @@ -586,6 +547,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } void stopping() { + stopping = true; cancelPeriodicTimer(); } @@ -622,6 +584,29 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA return PacketResult.IGNORED; } + private ARP createARP(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress, byte[] targetIP) { + ARP arp = new ARP(); + arp.setHardwareType(ARP.HW_TYPE_ETHERNET); + arp.setProtocolType(EtherTypes.IPv4.shortValue()); + arp.setHardwareAddressLength((byte) 6); + arp.setProtocolAddressLength((byte) 4); + arp.setOpCode(opCode); + arp.setSenderHardwareAddress(senderMacAddress) ; + arp.setSenderProtocolAddress(senderIP); + arp.setTargetHardwareAddress(targetMacAddress); + arp.setTargetProtocolAddress(targetIP); + return arp; + } + + private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp) { + Ethernet ethernet = new Ethernet(); + ethernet.setSourceMACAddress(sourceMAC); + ethernet.setDestinationMACAddress(targetMAC); + ethernet.setEtherType(EtherTypes.ARP.shortValue()); + ethernet.setPayload(arp); + return ethernet; + } + private void startPeriodicTimer() { this.periodicTimer = new Timer("ArpHandler Periodic Timer"); this.periodicTimer.scheduleAtFixedRate(new TimerTask() { @@ -666,15 +651,25 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC) { + if (log.isTraceEnabled()) { + log.trace("generateAndSendReply called with params sourceIP:{} sourceMAC:{}", sourceIP, + HexEncode.bytesToHexString(sourceMAC)); + } Set hosts = arpRequestors.remove(sourceIP); if ((hosts == null) || hosts.isEmpty()) { + log.trace("Bailing out no requestors Hosts"); return; } countDownTimers.remove(sourceIP); for (HostNodeConnector host : hosts) { - log.trace("Sending ARP Reply with src {}/{}, target {}/{}", - new Object[] { sourceMAC, sourceIP, host.getDataLayerAddressBytes(), host.getNetworkAddress() }); - + if (log.isTraceEnabled()) { + log.trace("Sending ARP Reply with src {}/{}, target {}/{}", + new Object[] { + HexEncode.bytesToHexString(sourceMAC), + sourceIP, + HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), + host.getNetworkAddress() }); + } if (connectionManager.isLocal(host.getnodeconnectorNode())){ sendARPReply(host.getnodeConnector(), sourceMAC, @@ -682,6 +677,12 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA host.getDataLayerAddressBytes(), host.getNetworkAddress()); } else { + /* + * In the remote event a requestor moved to another + * controller it may turn out it now we need to send + * the ARP reply from a different controller, this + * cover the case + */ arpRequestReplyEvent.put( new ARPReply( host.getnodeConnector(), @@ -696,6 +697,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA @Override public void entryUpdated(ARPEvent key, Boolean new_value, String cacheName, boolean originLocal) { + log.trace("Got and entryUpdated for cacheName {} key {} isNew {}", cacheName, key, new_value); enqueueARPCacheEvent(key, new_value); } @@ -713,6 +715,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA ARPCacheEvent cacheEvent = new ARPCacheEvent(event, new_value); if (!ARPCacheEvents.contains(cacheEvent)) { this.ARPCacheEvents.add(cacheEvent); + log.trace("Enqueued {}", event); } } catch (Exception e) { log.debug("enqueueARPCacheEvent caught Interrupt Exception for event {}", event); @@ -725,7 +728,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA private class ARPCacheEventHandler implements Runnable { @Override public void run() { - while (true) { + while (!stopping) { try { ARPCacheEvent ev = ARPCacheEvents.take(); ARPEvent event = ev.getEvent(); @@ -733,20 +736,23 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA ARPRequest req = (ARPRequest) event; // If broadcast request if (req.getHost() == null) { + log.trace("Trigger and ARP Broadcast Request upon receipt of {}", req); sendBcastARPRequest(req.getTargetIP(), req.getSubnet()); //If unicast and local, send reply } else if (connectionManager.isLocal(req.getHost().getnodeconnectorNode())) { + log.trace("ARPCacheEventHandler - sendUcatARPRequest upon receipt of {}", req); sendUcastARPRequest(req.getHost(), req.getSubnet()); } } else if (event instanceof ARPReply) { ARPReply rep = (ARPReply) event; // New reply received by controller, notify all awaiting requestors across the cluster if (ev.isNewReply()) { + log.trace("Trigger a generateAndSendReply in response to {}", rep); generateAndSendReply(rep.getTargetIP(), rep.getTargetMac()); - // Otherwise, a specific reply. If local, send out. } else if (connectionManager.isLocal(rep.getPort().getNode())) { + log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep); sendARPReply(rep.getPort(), rep.getSourceMac(), rep.getSourceIP(),