fix ARP (single onos instance & multiple onos instances)

1. make sure that ARP requests coming from host in a LAN
   are not broadcasted to all other edge ports (other ASes)
2. make sure the ARP requests from BGPd host can be singlecast
   to other ASes
3. add a 'get external network switch ports' function
4. make the arp work for both single onos instance & multiple
   onos instances
5. add a switch ports blacklist. Arp requests are not to be sent
   to those switch ports on this list.

Change-Id: I4ffdd73e2ad202517c54690a86109cfa1fbe400f
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index 6758b7a..3e4e1c4 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -249,7 +249,7 @@
             log.trace("Sending broadcast packet to other ONOS instances");
         }
 
-        packetService.broadcastPacketOutEdge(eth,
+        packetService.broadcastPacketOutInternalEdge(eth,
                 new SwitchPort(sw.getDpid(), inPort.getNumber()));
     }
 
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
index cfdd9c1..197b40d 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
@@ -404,13 +404,17 @@
         }
 
         InetAddress target;
+        InetAddress sender;
         try {
             target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+            sender = InetAddress.getByAddress(arp.getSenderProtocolAddress());
+
         } catch (UnknownHostException e) {
             log.debug("Invalid address in ARP request", e);
             return;
         }
 
+        // Handle ARP from external network
         if (configService.fromExternalNetwork(dpid, inPort)) {
             // If the request came from outside our network, we only care if
             // it was a request for one of our interfaces.
@@ -420,6 +424,7 @@
                         target.getHostAddress(),
                         configService.getRouterMacAddress());
 
+                //TODO: learn MAC address dynamically rather than from configuration
                 sendArpReply(arp, dpid, inPort,
                         configService.getRouterMacAddress());
             }
@@ -427,6 +432,17 @@
             return;
         }
 
+        // Handle ARP to external network
+        if (configService.inConnectedNetwork(target)
+                && configService.isInterfaceAddress(sender)) {
+            SwitchPort switchPort =
+                    configService.getOutgoingInterface(target).getSwitchPort();
+            arpRequests.put(target, new ArpRequest(
+                    new HostArpRequester(arp, dpid, inPort), false));
+            packetService.sendPacket(eth, switchPort);
+            return;
+        }
+
         //MACAddress mac = arpCache.lookup(target);
 
         arpRequests.put(target, new ArpRequest(
@@ -444,7 +460,7 @@
             }
 
             // We don't know the device so broadcast the request out
-            packetService.broadcastPacketOutEdge(eth,
+            packetService.broadcastPacketOutInternalEdge(eth,
                     new SwitchPort(dpid, inPort));
         } else {
             // Even if the device exists in our database, we do not reply to
@@ -468,7 +484,7 @@
                             " - broadcasting", macAddress);
                 }
 
-                packetService.broadcastPacketOutEdge(eth,
+                packetService.broadcastPacketOutInternalEdge(eth,
                         new SwitchPort(dpid, inPort));
             } else {
                 for (Port portObject : outPorts) {
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
index cd1c2de..ed7a8ee 100644
--- a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
+++ b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
@@ -5,6 +5,7 @@
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -108,6 +109,7 @@
     private SwitchPort bgpdAttachmentPoint;
     private MACAddress bgpdMacAddress;
     private short vlan;
+    private Set<SwitchPort> externalNetworkSwitchPorts;
 
     private SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;
 
@@ -132,6 +134,8 @@
             interfaces = new HashMap<>();
             for (Interface intf : config.getInterfaces()) {
                 interfaces.put(intf.getName(), intf);
+                externalNetworkSwitchPorts.add(new SwitchPort(intf.getDpid(),
+                        intf.getPort()));
             }
             bgpPeers = new HashMap<>();
             for (BgpPeer peer : config.getPeers()) {
@@ -193,6 +197,7 @@
                 new DefaultByteArrayNodeFactory());
         interfaceRoutes = new ConcurrentInvertedRadixTree<>(
                 new DefaultByteArrayNodeFactory());
+        externalNetworkSwitchPorts = new HashSet<SwitchPort>();
 
         ribUpdates = new LinkedBlockingQueue<>();
 
@@ -906,4 +911,9 @@
         return vlan;
     }
 
+    @Override
+    public Set<SwitchPort> getExternalSwitchPorts() {
+        return Collections.unmodifiableSet(externalNetworkSwitchPorts);
+    }
+
 }