CORD-48 First checkin for enabling OF-DPA driver to support the SR app.
Filtering Objective support added. Driver renamed from OFDPA1 to OFDPA2.
Code refactored within driver to reflect test-code which will be used by
static flow-pusher app in the future.

Change-Id: I7132d8b8eaf28df7c11646c5a35035f258c65af4
diff --git a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index f42f84b..55192a9 100644
--- a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -112,7 +112,7 @@
 
 
     private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) {
-        List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
+        List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
         if (gatewayIpAddresses != null) {
             Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest
                     .getTargetProtocolAddress());
diff --git a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 40ee55f..665ad66 100644
--- a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -499,14 +499,13 @@
     }
 
     /**
-     * Populates table miss entries for all tables, and pipeline rules for VLAN
-     * and TCAM tables. XXX rename/rethink
+     * Populates filtering rules for permitting Router DstMac and VLAN.
      *
      * @param deviceId Switch ID to set the rules
      */
-    public void populateTtpRules(DeviceId deviceId) {
-        rulePopulator.populateTableVlan(deviceId);
-        rulePopulator.populateTableTMac(deviceId);
+    public void populatePortAddressingRules(DeviceId deviceId) {
+        rulePopulator.populateRouterMacVlanFilters(deviceId);
+        rulePopulator.populateRouterIpPunts(deviceId);
     }
 
     /**
diff --git a/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index 0bc155b..1d45d0a 100644
--- a/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -126,7 +126,7 @@
     }
 
     /**
-     * Returns the segment id of a segment router.
+     * Returns the Node segment id of a segment router.
      *
      * @param deviceId device identifier
      * @return segment id
@@ -147,7 +147,7 @@
     }
 
     /**
-     * Returns the segment id of a segment router given its mac address.
+     * Returns the Node segment id of a segment router given its Router mac address.
      *
      * @param routerMac router mac address
      * @return segment id
@@ -164,7 +164,7 @@
     }
 
     /**
-     * Returns the segment id of a segment router given its router ip address.
+     * Returns the Node segment id of a segment router given its Router ip address.
      *
      * @param routerAddress router ip address
      * @return segment id
@@ -223,7 +223,7 @@
 
     /**
      * Indicates if the segment router is a edge router or
-     * a transit/back bone router.
+     * a core/backbone router.
      *
      * @param deviceId device identifier
      * @return boolean
@@ -244,9 +244,9 @@
     }
 
     /**
-     * Returns the segment ids of all configured segment routers.
+     * Returns the node segment ids of all configured segment routers.
      *
-     * @return list of segment ids
+     * @return list of node segment ids
      */
     @Override
     public List<Integer> getAllDeviceSegmentIds() {
@@ -290,12 +290,14 @@
     }
 
     /**
-     * Returns the configured subnet gateway ip addresses for a segment router.
+     * Returns the configured port ip addresses for a segment router.
+     * These addresses serve as gateway IP addresses for the subnets configured
+     * on those ports.
      *
      * @param deviceId device identifier
-     * @return list of ip addresses
+     * @return list of ip addresses configured on the ports
      */
-    public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
+    public List<Ip4Address> getPortIPs(DeviceId deviceId) {
         if (deviceConfigMap.get(deviceId) != null) {
             log.trace("getSubnetGatewayIps for device{} is {}",
                     deviceId,
@@ -307,6 +309,20 @@
     }
 
     /**
+     * Returns the configured IP addresses per port
+     * for a segment router.
+     *
+     * @param deviceId device identifier
+     * @return map of port to gateway IP addresses
+     */
+    public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) {
+        if (deviceConfigMap.get(deviceId) != null) {
+            return deviceConfigMap.get(deviceId).gatewayIps;
+        }
+        return null;
+    }
+
+    /**
      * Returns the configured subnet prefixes for a segment router.
      *
      * @param deviceId device identifier
diff --git a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index f65f03e..a77ec95 100644
--- a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -70,7 +70,7 @@
         DeviceId deviceId = connectPoint.deviceId();
         Ip4Address destinationAddress =
                 Ip4Address.valueOf(ipv4.getDestinationAddress());
-        List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
+        List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
         Ip4Address routerIp = config.getRouterIp(deviceId);
         IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
         Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address();
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 7641571..5b14342 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -38,6 +38,7 @@
 import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.net.flowobjective.ObjectiveError;
 import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
 import org.onosproject.net.flowobjective.ObjectiveContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -57,6 +58,9 @@
     private AtomicLong rulePopulationCounter;
     private SegmentRoutingManager srManager;
     private DeviceConfiguration config;
+
+    private static final int HIGHEST_PRIORITY = 0xffff;
+
     /**
      * Creates a RoutingRulePopulator object.
      *
@@ -98,7 +102,7 @@
         TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
         TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
 
-        sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32));
+        sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
         sbuilder.matchEthType(Ethernet.TYPE_IPV4);
 
         tbuilder.deferred()
@@ -350,16 +354,22 @@
     }
 
     /**
-     * Populates VLAN flows rules. All packets are forwarded to TMAC table.
+     * Creates a filtering objective to permit all untagged packets with a
+     * dstMac corresponding to the router's MAC address.
      *
-     * @param deviceId switch ID to set the rules
+     * @param deviceId  the switch dpid for the router
      */
-    public void populateTableVlan(DeviceId deviceId) {
+    public void populateRouterMacVlanFilters(DeviceId deviceId) {
         FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
         fob.withKey(Criteria.matchInPort(PortNumber.ALL))
-                .addCondition(Criteria.matchVlanId(VlanId.NONE));
+                .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId)))
+                .addCondition(Criteria.matchVlanId(VlanId.NONE))
+                .addCondition(Criteria.matchIPDst(
+                                  IpPrefix.valueOf(config.getRouterIp(deviceId),
+                                                   IpPrefix.MAX_INET_MASK_LENGTH)));
+
         fob.permit().fromApp(srManager.appId);
-        log.debug("populateTableVlan: Installing filtering objective for untagged packets");
+        log.debug("Installing filtering objective for untagged packets");
         srManager.flowObjectiveService.
             filter(deviceId,
                    fob.add(new SRObjectiveContext(deviceId,
@@ -367,23 +377,35 @@
     }
 
     /**
-     * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS
-     * packets are forwarded to MPLS table.
+     * Creates a forwarding objective to punt all IP packets, destined to the
+     * router's port IP addresses, to the controller. Note that it the input
+     * port should not be matched on, as these packets can come from any input.
      *
-     * @param deviceId switch ID to set the rules
+     * @param deviceId the switch dpid for the router
      */
-    public void populateTableTMac(DeviceId deviceId) {
+    public void populateRouterIpPunts(DeviceId deviceId) {
+        ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder();
 
-        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-        fob.withKey(Criteria.matchInPort(PortNumber.ALL))
-                .addCondition(Criteria.matchEthDst(config
-                                      .getDeviceMac(deviceId)));
-        fob.permit().fromApp(srManager.appId);
-        log.debug("populateTableTMac: Installing filtering objective for router mac");
-        srManager.flowObjectiveService.
-            filter(deviceId,
-                   fob.add(new SRObjectiveContext(deviceId,
-                                                  SRObjectiveContext.ObjectiveType.FILTER)));
+        List<Ip4Address> gws = config.getPortIPs(deviceId);
+        for (Ip4Address ipaddr : gws) {
+            TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+            selector.matchEthType(Ethernet.TYPE_IPV4);
+            selector.matchIPDst(IpPrefix.valueOf(ipaddr,
+                                                 IpPrefix.MAX_INET_MASK_LENGTH));
+            treatment.setOutput(PortNumber.CONTROLLER);
+            puntIp.withSelector(selector.build());
+            puntIp.withTreatment(treatment.build());
+            puntIp.withFlag(Flag.VERSATILE)
+                .withPriority(HIGHEST_PRIORITY)
+                .makePermanent()
+                .fromApp(srManager.appId);
+            log.debug("Installing forwarding objective to punt port IP addresses");
+            srManager.flowObjectiveService.
+                forward(deviceId,
+                        puntIp.add(new SRObjectiveContext(deviceId,
+                                           SRObjectiveContext.ObjectiveType.FORWARDING)));
+        }
     }
 
     private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index eb2cf56..1faebca 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -497,7 +497,7 @@
                                    flowObjectiveService,
                                    nsNextObjStore);
         groupHandlerMap.put(device.id(), dgh);
-        defaultRoutingHandler.populateTtpRules(device.id());
+        defaultRoutingHandler.populatePortAddressingRules(device.id());
     }
 
     private void processPortRemoved(Device device, Port port) {
@@ -542,7 +542,7 @@
                                             flowObjectiveService,
                                             nsNextObjStore);
                 groupHandlerMap.put(device.id(), groupHandler);
-                defaultRoutingHandler.populateTtpRules(device.id());
+                defaultRoutingHandler.populatePortAddressingRules(device.id());
             }
 
             defaultRoutingHandler.startPopulationProcess();