Altering ARPHandler and SimpleBroadcastHandler to forward traffic immediately.
[controller.git] / opendaylight / arphandler / src / main / java / org / opendaylight / controller / arphandler / internal / ArpHandler.java
index 627ab267399978950d66f7dd1625f25a2c405021..7925c05f59466a5c3de3e4fa517f12e4d8368db8 100644 (file)
@@ -41,6 +41,7 @@ import org.opendaylight.controller.hosttracker.IfHostListener;
 import org.opendaylight.controller.hosttracker.IfIptoHost;
 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
 import org.opendaylight.controller.hosttracker.hostAware.IHostFinder;
+import org.opendaylight.controller.sal.connection.ConnectionLocality;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -52,7 +53,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;
@@ -156,22 +156,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);
@@ -267,7 +254,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
          */
         if ((targetIP.equals(subnet.getNetworkAddress()))
                 && (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(targetMAC, getControllerMAC()))) {
-            if (connectionManager.isLocal(p.getNode())){
+            if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL){
                 if (log.isTraceEnabled()){
                     log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}",
                             HexEncode.bytesToHexString(getControllerMAC()));
@@ -306,7 +293,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
              */
             if (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(host.getDataLayerAddressBytes(), targetMAC)) {
                 log.trace("Received ARP req. for known host {}, sending reply...", targetIP);
-                if (connectionManager.isLocal(p.getNode())) {
+                if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) {
                     sendARPReply(p,
                             host.getDataLayerAddressBytes(),
                             host.getNetworkAddress(),
@@ -331,7 +318,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    /*
+    /**
      *  Send a broadcast ARP Request to the switch/ ports  using
      *  the networkAddress of the subnet as sender IP
      *  the controller's MAC as sender MAC
@@ -348,36 +335,21 @@ 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 };
 
+        //TODO: should use IBroadcastHandler instead
         for (NodeConnector p : nodeConnectors) {
-            //fiter out any non-local or internal ports
-            if (! connectionManager.isLocal(p.getNode()) || topologyManager.isInternal(p)) {
+            //filter out any non-local or internal ports
+            if (!(connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) || topologyManager.isInternal(p)) {
                 continue;
             }
             log.trace("Sending toward nodeConnector:{}", p);
-            ARP arp = new ARP();
             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
@@ -388,7 +360,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    /*
+    /**
      * Send a unicast ARP Request to the known host on a specific switch/port as
      * defined in the host.
      * The sender IP is the networkAddress of the subnet
@@ -405,22 +377,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);
@@ -462,7 +421,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             return;
         }
 
-        if (connectionManager.isLocal(host.getnodeconnectorNode())){
+        if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL){
             log.trace("Send a ucast ARP req. to: {}", host);
             sendUcastARPRequest(host, subnet);
         } else {
@@ -471,10 +430,13 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    /*
+    /**
      * An IP packet is punted to the controller, this means that the
      * destination host is not known to the controller.
      * Need to discover it by sending a Broadcast ARP Request
+     *
+     * @param pkt
+     * @param p
      */
     protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p) {
 
@@ -483,6 +445,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
            return;
         }
 
+        // try to find a matching subnet
         Subnet subnet = null;
         if (switchManager != null) {
             subnet = switchManager.getSubnetByNetworkAddress(dIP);
@@ -491,12 +454,28 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
             log.debug("Can't find subnet matching {}, drop packet", dIP);
             return;
         }
-        log.trace("Punted IP pkt from {}, sending bcast ARP event...", dIP);
-        /*
-         * unknown destination host, initiate bcast ARP request
-         */
-        arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false);
-        return;
+
+        // see if we know about the host
+        HostNodeConnector host = hostTracker.hostFind(dIP);
+
+        if (host == null) {
+            // if we don't, know about the host, try to find it
+            log.trace("Punted IP pkt from {}, sending bcast ARP event...",
+                      dIP);
+            /*
+             * unknown destination host, initiate bcast ARP request
+             */
+            arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false);
+        }else{
+
+            // we know about the host, send the packet the right place
+            NodeConnector nc = host.getnodeConnector();
+
+            // re-encode the Ethernet packet (the parent of the IPv4 packet)
+            RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent());
+            rp.setOutgoingNodeConnector(nc);
+            this.dataPacketService.transmitDataPacket(rp);
+        }
     }
 
     public byte[] getControllerMAC() {
@@ -520,7 +499,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         retrieveCaches();
     }
 
-    @SuppressWarnings({ "unchecked", "deprecation" })
+    @SuppressWarnings({ "unchecked" })
     private void retrieveCaches() {
         ConcurrentMap<?,?> map;
 
@@ -537,7 +516,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
-    @SuppressWarnings("deprecation")
     private void allocateCaches() {
         if (clusterContainerService == null){
             nonClusterObjectCreate();
@@ -628,10 +606,32 @@ 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() {
-            @SuppressWarnings("deprecation")
             @Override
             public void run() {
                 Set<InetAddress> targetIPs = countDownTimers.keySet();
@@ -691,7 +691,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                               HexEncode.bytesToHexString(host.getDataLayerAddressBytes()),
                               host.getNetworkAddress() });
             }
-            if (connectionManager.isLocal(host.getnodeconnectorNode())){
+            if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL){
                 sendARPReply(host.getnodeConnector(),
                         sourceMAC,
                         sourceIP,
@@ -761,7 +761,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                             sendBcastARPRequest(req.getTargetIP(), req.getSubnet());
 
                         //If unicast and local, send reply
-                        } else if (connectionManager.isLocal(req.getHost().getnodeconnectorNode())) {
+                        } else if (connectionManager.getLocalityStatus(req.getHost().getnodeconnectorNode()) == ConnectionLocality.LOCAL) {
                             log.trace("ARPCacheEventHandler - sendUcatARPRequest upon receipt of {}", req);
                             sendUcastARPRequest(req.getHost(), req.getSubnet());
                         }
@@ -772,7 +772,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
                             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())) {
+                        } else if (connectionManager.getLocalityStatus(rep.getPort().getNode()) == ConnectionLocality.LOCAL) {
                             log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep);
                             sendARPReply(rep.getPort(),
                                     rep.getSourceMac(),