Various fixes and addition to the Fabric

Changes:
- Punts ARP packets to the controller using fobj;
- Disables intercepts in HLP when SR app is activated;

Change-Id: Ife098994f6d3c79fd73847657df0c08d856e7246
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index ba918c6..5396f54 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -611,6 +611,7 @@
      */
     public void populatePortAddressingRules(DeviceId deviceId) {
         rulePopulator.populateRouterIpPunts(deviceId);
+        rulePopulator.populateArpNdpPunts(deviceId);
 
         // Although device is added, sometimes device store does not have the
         // ports for this device yet. It results in missing filtering rules in the
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 4e35571..47f6cbd 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -25,7 +25,9 @@
 import org.onlab.packet.VlanId;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.flowobjective.DefaultObjectiveContext;
+import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.net.flowobjective.ObjectiveContext;
+import org.onosproject.net.flowobjective.ObjectiveError;
 import org.onosproject.net.packet.PacketPriority;
 import org.onosproject.segmentrouting.DefaultRoutingHandler.PortFilterInfo;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
@@ -57,6 +59,10 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.packet.Ethernet.TYPE_ARP;
+import static org.onlab.packet.Ethernet.TYPE_IPV6;
+import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
+import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
 
 /**
  * Populator of segment routing flow rules.
@@ -642,6 +648,82 @@
     }
 
     /**
+     * Creates forwarding objectives to punt ARP and NDP packets, to the controller.
+     * Furthermore, these are applied only by the master instance. Deferred actions
+     * are not cleared such that packets can be flooded in the cross connect use case
+     *
+     * @param deviceId the switch dpid for the router
+     */
+    public void populateArpNdpPunts(DeviceId deviceId) {
+        /*
+         * We are not the master just skip.
+         */
+        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
+            log.debug("Not installing ARP/NDP punts - not the master for dev:{} ",
+                      deviceId);
+            return;
+        }
+
+        // We punt all ARP packets towards the controller.
+        ForwardingObjective puntFwd = puntArpFwdObjective()
+                .add(new ObjectiveContext() {
+                    @Override
+                    public void onError(Objective objective, ObjectiveError error) {
+                        log.warn("Failed to install packet request for ARP to {}: {}",
+                                 deviceId, error);
+                    }
+                });
+        srManager.flowObjectiveService.forward(deviceId, puntFwd);
+
+        // TODO: The driver does not support NDP at this moment. Turn it back on later.
+        // We punt all NDP packets towards the controller.
+        /*
+        puntFwd = puntNdpFwdObjective()
+                .add(new ObjectiveContext() {
+                    @Override
+                    public void onError(Objective objective, ObjectiveError error) {
+                        log.warn("Failed to install packet request for NDP to {}: {}",
+                                 deviceId, error);
+                    }
+                });
+        srManager.flowObjectiveService.forward(deviceId, puntFwd);
+        */
+    }
+
+    private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector) {
+
+        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+        tBuilder.punt();
+
+        return DefaultForwardingObjective.builder()
+                .withPriority(PacketPriority.CONTROL.priorityValue())
+                .withSelector(selector)
+                .fromApp(srManager.appId)
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .withTreatment(tBuilder.build())
+                .makePermanent();
+    }
+
+    private ForwardingObjective.Builder puntArpFwdObjective() {
+
+        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+        sBuilder.matchEthType(TYPE_ARP);
+
+        return fwdObjBuilder(sBuilder.build());
+    }
+
+    private ForwardingObjective.Builder puntNdpFwdObjective() {
+
+        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+        sBuilder.matchEthType(TYPE_IPV6)
+                .matchIPProtocol(PROTOCOL_ICMP6)
+                .matchIcmpv6Type(NEIGHBOR_SOLICITATION)
+                .build();
+
+        return fwdObjBuilder(sBuilder.build());
+    }
+
+    /**
      * Populates a forwarding objective to send packets that miss other high
      * priority Bridging Table entries to a group that contains all ports of
      * its subnet.
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 1a540ef..a09b0e4 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -51,7 +51,6 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
@@ -60,7 +59,6 @@
 import org.onosproject.net.mcast.McastEvent;
 import org.onosproject.net.mcast.McastListener;
 import org.onosproject.net.mcast.MulticastRouteService;
-import org.onosproject.net.packet.PacketPriority;
 import org.onosproject.net.topology.TopologyService;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
@@ -97,7 +95,6 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -333,11 +330,13 @@
                 .build();
 
         compCfgService.preSetProperty("org.onosproject.net.group.impl.GroupManager",
-                "purgeOnDisconnection", "true");
+                                      "purgeOnDisconnection", "true");
         compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
-                "purgeOnDisconnection", "true");
+                                      "purgeOnDisconnection", "true");
         compCfgService.preSetProperty("org.onosproject.vrouter.Vrouter",
-                "fibInstalledEnabled", "false");
+                                      "fibInstalledEnabled", "false");
+        compCfgService.preSetProperty("org.onosproject.provider.host.impl.HostLocationProvider",
+                                      "requestInterceptsEnabled", "false");
 
         processor = new InternalPacketProcessor();
         linkListener = new InternalLinkListener();
@@ -361,14 +360,6 @@
         multicastRouteService.addListener(mcastListener);
         cordConfigService.addListener(cordConfigListener);
 
-        /* Request ARP packet-in.
-         * Copy flag set to true since in cross-connect case we still want to
-         * forward ARP packet to the flood group.
-         */
-        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
-        selector.matchEthType(Ethernet.TYPE_ARP);
-        packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId, true);
-
         cfgListener.configureNetwork();
 
         routeService.addListener(routeListener);
@@ -401,11 +392,6 @@
         cfgService.unregisterConfigFactory(xConnectConfigFactory);
         cfgService.unregisterConfigFactory(mcastConfigFactory);
 
-        // Withdraw ARP packet-in
-        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
-        selector.matchEthType(Ethernet.TYPE_ARP);
-        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId, Optional.empty());
-
         packetService.removeProcessor(processor);
         linkService.removeListener(linkListener);
         deviceService.removeListener(deviceListener);