Segment Routing refactor with flow objectives

Change-Id: I0b87f89bb8b18522b9d38bdf5e96f55485b6f1e3
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index d47c78f..ebfa635 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -19,10 +19,11 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
-import java.util.Collections;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 
 import org.jboss.netty.channel.Channel;
 import org.onlab.packet.IpAddress;
@@ -64,7 +65,7 @@
 
     private OFVersion ofVersion;
 
-    protected OFPortDescStatsReply ports;
+    protected List<OFPortDescStatsReply> ports = new ArrayList<>();
 
     protected boolean tableFull;
 
@@ -251,7 +252,12 @@
 
     @Override
     public void setPortDescReply(OFPortDescStatsReply portDescReply) {
-        this.ports = portDescReply;
+        this.ports.add(portDescReply);
+    }
+
+    @Override
+    public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
+        this.ports.addAll(portDescReplies);
     }
 
     @Override
@@ -379,7 +385,10 @@
 
     @Override
     public List<OFPortDesc> getPorts() {
-        return Collections.unmodifiableList(ports.getEntries());
+        return this.ports.stream()
+                  .flatMap((portReply) -> (portReply.getEntries().stream()))
+                  .collect(Collectors.toList());
+        //return Collections.unmodifiableList(ports.getEntries());
     }
 
     @Override
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
index c6f83e2..a83b608 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowSwitchDriver.java
@@ -137,6 +137,12 @@
     public void setPortDescReply(OFPortDescStatsReply portDescReply);
 
     /**
+     * Sets the ports on this switch.
+     * @param portDescReplies list of port set and descriptions
+     */
+    public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies);
+
+    /**
      * Sets the features reply for this switch.
      * @param featuresReply the features to set.
      */
diff --git a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
index d95bb1d..4779c5d 100644
--- a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
+++ b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
@@ -97,7 +97,8 @@
 
     // Temporary storage for switch-features and port-description
     private OFFeaturesReply featuresReply;
-    private OFPortDescStatsReply portDescReply;
+    private List<OFPortDescStatsReply> portDescReplies;
+    //private OFPortDescStatsReply portDescReply;
     // a concurrent ArrayList to temporarily store port status messages
     // before we are ready to deal with them
     private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg;
@@ -121,6 +122,7 @@
         this.controller = controller;
         this.state = ChannelState.INIT;
         this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>();
+        this.portDescReplies = new ArrayList<OFPortDescStatsReply>();
         factory13 = controller.getOFMessageFactory13();
         factory10 = controller.getOFMessageFactory10();
         duplicateDpidFound = Boolean.FALSE;
@@ -294,10 +296,15 @@
                 }
                 if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
                     log.warn("Stats reply indicates more stats from sw {} for "
-                            + "port description - not currently handled",
+                            + "port description",
                             h.getSwitchInfoString());
+                    h.portDescReplies.add((OFPortDescStatsReply)m);
+                    return;
                 }
-                h.portDescReply = (OFPortDescStatsReply) m; // temp store
+                else {
+                    h.portDescReplies.add((OFPortDescStatsReply)m);
+                }
+                //h.portDescReply = (OFPortDescStatsReply) m; // temp store
                 log.info("Received port desc reply for switch at {}",
                         h.getSwitchInfoString());
                 try {
@@ -418,7 +425,8 @@
 
                 h.sw.setOFVersion(h.ofVersion);
                 h.sw.setFeaturesReply(h.featuresReply);
-                h.sw.setPortDescReply(h.portDescReply);
+                //h.sw.setPortDescReply(h.portDescReply);
+                h.sw.setPortDescReplies(h.portDescReplies);
                 h.sw.setConnected(true);
                 h.sw.setChannel(h.channel);
 //                boolean success = h.sw.connectSwitch();
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
index 5a74e9a..fb0e406 100644
--- a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
@@ -255,6 +255,10 @@
         }
 
         @Override
+        public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
+        }
+
+        @Override
         public void setFeaturesReply(OFFeaturesReply featuresReply) {
         }
 
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/DriverManager.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/DriverManager.java
index 746cdd5..c10c3a9 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/DriverManager.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/DriverManager.java
@@ -32,6 +32,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * A simple implementation of a driver manager that differentiates between
@@ -73,6 +74,14 @@
             return new OFSwitchImplSpringOpenTTP(dpid, desc);
         }
 
+        //TODO: Temporary work around until the configuration based
+        // driver manager framework is ready
+        if (vendor.contains("Dell")
+                &&
+                hw.contains("OpenFlow switch HW ver. 1.0")) {
+            return new OFSwitchImplSpringOpenTTPDellOSR(dpid, desc);
+        }
+
         if (hw.startsWith("Open vSwitch")) {
             if (ofv == OFVersion.OF_10) {
                 return new OFSwitchImplOVS10(dpid, desc);
@@ -140,7 +149,9 @@
                 if (this.factory().getVersion() == OFVersion.OF_10) {
                     return Collections.unmodifiableList(features.getPorts());
                 } else {
-                    return Collections.unmodifiableList(ports.getEntries());
+                    return Collections.unmodifiableList(this.ports.stream()
+                                                        .flatMap((portReply) -> (portReply.getEntries().stream()))
+                                                        .collect(Collectors.toList()));
                 }
             }
 
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
index 61c37df..37022a1 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
@@ -183,7 +183,7 @@
     @Override
     public List<OFPortDesc> getPorts() {
         List<OFPortDesc> portEntries = new ArrayList<>();
-        portEntries.addAll(ports.getEntries());
+        portEntries.addAll(super.getPorts());
         if (wPorts != null) {
             portEntries.addAll(wPorts.getEntries());
         }
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTP.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTP.java
index 4e7f61d..80fc95f 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTP.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTP.java
@@ -34,6 +34,8 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+//TODO: Knock-off this class as we don't need any switch/app specific
+//drivers in the south bound layers.
 public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch {
 
     private OFFactory factory;
@@ -48,8 +50,9 @@
     private static final int TABLE_MPLS = 3;
     private static final int TABLE_ACL = 5;
 
-    /* Set the default values. These variables will get
-     * overwritten based on the switch vendor type
+    /*
+     * Set the default values. These variables will get overwritten based on the
+     * switch vendor type
      */
     protected int vlanTableId = TABLE_VLAN;
     protected int tmacTableId = TABLE_TMAC;
@@ -64,13 +67,13 @@
         setSwitchDescription(desc);
     }
 
-
     @Override
     public String toString() {
-        return "OFSwitchImplSpringOpenTTP [" + ((channel != null)
-                ? channel.getRemoteAddress() : "?")
-                + " DPID[" + ((this.getStringId() != null) ?
-                this.getStringId() : "?") + "]]";
+        return "OFSwitchImplSpringOpenTTP ["
+                + ((channel != null) ? channel.getRemoteAddress() : "?")
+                + " DPID["
+                + ((this.getStringId() != null) ? this.getStringId() : "?")
+                + "]]";
     }
 
     @Override
@@ -78,7 +81,6 @@
         return null;
     }
 
-
     @Override
     public void startDriverHandshake() {
         log.debug("Starting driver handshake for sw {}", getStringId());
@@ -101,8 +103,6 @@
         return driverHandshakeComplete.get();
     }
 
-
-
     @Override
     public void processDriverHandshakeMessage(OFMessage m) {
         if (!startDriverHandshakeCalled) {
@@ -113,15 +113,14 @@
         }
     }
 
-
     @Override
     public void write(OFMessage msg) {
-        this.channel.write(Collections.singletonList(msg));
+        channel.write(Collections.singletonList(msg));
     }
 
     @Override
     public void write(List<OFMessage> msgs) {
-        this.channel.write(msgs);
+        channel.write(msgs);
     }
 
     @Override
@@ -134,10 +133,10 @@
             for (OFInstruction i : instructions) {
                 if (i instanceof OFInstructionGotoTable) {
                     OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
-                    TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
-                    newInstructions.add(
-                            gotoTable.createBuilder()
-                                    .setTableId(getTableId(tid)).build());
+                    TableType tid = TableType.values()[gotoTable.getTableId()
+                            .getValue()];
+                    newInstructions.add(gotoTable.createBuilder()
+                            .setTableId(getTableId(tid)).build());
                 } else {
                     newInstructions.add(i);
                 }
@@ -156,38 +155,39 @@
     @Override
     public TableType getTableType(TableId tid) {
         switch (tid.getValue()) {
-            case TABLE_IPV4_UNICAST:
-                return TableType.IP;
-            case TABLE_MPLS:
-                return TableType.MPLS;
-            case TABLE_ACL:
-                return TableType.ACL;
-            case TABLE_VLAN:
-                return TableType.VLAN;
-            case TABLE_TMAC:
-                return TableType.ETHER;
-            default:
-                log.error("Table type for Table id {} is not supported in the driver", tid);
-                return TableType.NONE;
+        case TABLE_IPV4_UNICAST:
+            return TableType.IP;
+        case TABLE_MPLS:
+            return TableType.MPLS;
+        case TABLE_ACL:
+            return TableType.ACL;
+        case TABLE_VLAN:
+            return TableType.VLAN;
+        case TABLE_TMAC:
+            return TableType.ETHER;
+        default:
+            log.error("Table type for Table id {} is not supported in the driver",
+                      tid);
+            return TableType.NONE;
         }
     }
 
     private TableId getTableId(TableType tableType) {
         switch (tableType) {
-            case IP:
-                return TableId.of(ipv4UnicastTableId);
-            case MPLS:
-                return TableId.of(mplsTableId);
-            case ACL:
-                return TableId.of(aclTableId);
-            case VLAN:
-                return TableId.of(vlanTableId);
-            case ETHER:
-                return TableId.of(tmacTableId);
-            default: {
-                log.error("Table type {} is not supported in the driver", tableType);
-                return TableId.NONE;
-            }
+        case IP:
+            return TableId.of(ipv4UnicastTableId);
+        case MPLS:
+            return TableId.of(mplsTableId);
+        case ACL:
+            return TableId.of(aclTableId);
+        case VLAN:
+            return TableId.of(vlanTableId);
+        case ETHER:
+            return TableId.of(tmacTableId);
+        default: {
+            log.error("Table type {} is not supported in the driver", tableType);
+            return TableId.NONE;
+        }
         }
     }
 
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTPDellOSR.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTPDellOSR.java
new file mode 100644
index 0000000..783a37e
--- /dev/null
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFSwitchImplSpringOpenTTPDellOSR.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow.drivers;
+
+import org.onosproject.openflow.controller.Dpid;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.types.TableId;
+
+/**
+ * OFDescriptionStatistics Vendor (Manufacturer Desc.): Dell Make (Hardware
+ * Desc.) : OpenFlow 1.3 Reference Userspace Switch Model (Datapath Desc.) :
+ * None Software : Serial : None.
+ */
+//TODO: Knock-off this class as we don't need any switch/app specific
+//drivers in the south bound layers.
+public class OFSwitchImplSpringOpenTTPDellOSR extends OFSwitchImplSpringOpenTTP {
+
+    /* Table IDs to be used for Dell Open Segment Routers*/
+    private static final int DELL_TABLE_VLAN = 17;
+    private static final int DELL_TABLE_TMAC = 18;
+    private static final int DELL_TABLE_IPV4_UNICAST = 30;
+    private static final int DELL_TABLE_MPLS = 25;
+    private static final int DELL_TABLE_ACL = 40;
+
+    public OFSwitchImplSpringOpenTTPDellOSR(Dpid dpid, OFDescStatsReply desc) {
+        super(dpid, desc);
+        vlanTableId = DELL_TABLE_VLAN;
+        tmacTableId = DELL_TABLE_TMAC;
+        ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST;
+        mplsTableId = DELL_TABLE_MPLS;
+        aclTableId = DELL_TABLE_ACL;
+    }
+
+    @Override
+    public TableType getTableType(TableId tid) {
+        switch (tid.getValue()) {
+            case DELL_TABLE_IPV4_UNICAST:
+                return TableType.IP;
+            case DELL_TABLE_MPLS:
+                return TableType.MPLS;
+            case DELL_TABLE_ACL:
+                return TableType.ACL;
+            case DELL_TABLE_VLAN:
+                return TableType.VLAN;
+            case DELL_TABLE_TMAC:
+                return TableType.ETHER;
+            default:
+                log.error("Table type for Table id {} is not supported in the driver", tid);
+                return TableType.NONE;
+        }
+    }
+}
\ No newline at end of file