Fixing a couple of bugs in default entries for corsa pipeline.
Also fixing flowRule table-awareness with changes reflected in flow identification (hashing)
and the karaf CLI.

Change-Id: I2fac83db8e0b54b802fb765ef9d82033f7478b99
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
index cceceef..b24c7ac 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
@@ -285,7 +285,7 @@
             processTableZero(install);
             processTableOne(install);
             processTableTwo(install);
-            processTableThree(install);
+            processTableFour(install);
             processTableFive(install);
             processTableSix(install);
             processTableNine(install);
@@ -305,7 +305,7 @@
             FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
                                                 treatment.build(),
                                                 CONTROLLER_PRIORITY, appId, 0,
-                                                true);
+                                                true, FlowRule.Type.FIRST);
 
             FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
 
@@ -319,7 +319,7 @@
 
             rule = new DefaultFlowRule(deviceId, selector.build(),
                                        treatment.build(), DROP_PRIORITY, appId,
-                                       0, true, FlowRule.Type.VLAN_MPLS);
+                                       0, true, FlowRule.Type.FIRST);
 
             ops = install ? ops.add(rule) : ops.remove(rule);
 
@@ -433,7 +433,7 @@
             }));
         }
 
-        private void processTableThree(boolean install) {
+        private void processTableFour(boolean install) {
             TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
             TrafficTreatment.Builder treatment = DefaultTrafficTreatment
                     .builder();
@@ -469,7 +469,7 @@
 
             rule = new DefaultFlowRule(deviceId, selector.build(),
                                        treatment.build(), DROP_PRIORITY, appId,
-                                       0, true, FlowRule.Type.VLAN_MPLS);
+                                       0, true, FlowRule.Type.ETHER);
 
             ops = install ? ops.add(rule) : ops.remove(rule);
 
diff --git a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
index e0b98ed..77a7719 100644
--- a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
@@ -52,7 +52,7 @@
     public static final String ANY = "any";
 
     private static final String FMT =
-            "   id=%s, state=%s, bytes=%s, packets=%s, duration=%s, priority=%s, appId=%s";
+            "   id=%s, state=%s, bytes=%s, packets=%s, duration=%s, priority=%s, tableId=%s appId=%s";
     private static final String TFMT = "      treatment=%s";
     private static final String SFMT = "      selector=%s";
 
@@ -131,6 +131,7 @@
                 .put("bytes", flow.bytes())
                 .put("packets", flow.packets())
                 .put("life", flow.life())
+                .put("tableId", flow.type().toString())
                 .put("appId", coreService.getAppId(flow.appId()).name());
         result.set("selector", crit);
         result.set("treatment", instr);
@@ -185,7 +186,7 @@
         if (!empty) {
             for (FlowEntry f : flows) {
                 print(FMT, Long.toHexString(f.id().value()), f.state(),
-                      f.bytes(), f.packets(), f.life(), f.priority(),
+                      f.bytes(), f.packets(), f.life(), f.priority(), f.type(),
                       coreService.getAppId(f.appId()).name());
                 print(SFMT, f.selector().criteria());
                 print(TFMT, f.treatment().instructions());
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
index 441f9a0..c8105c9 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
@@ -180,11 +180,11 @@
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public int hashCode() {
-        return Objects.hash(deviceId, selector, priority);
+        return Objects.hash(deviceId, selector, priority, type);
     }
 
     public int hash() {
-        return Objects.hash(deviceId, selector, treatment);
+        return Objects.hash(deviceId, selector, treatment, type);
     }
 
     @Override
@@ -202,7 +202,8 @@
             DefaultFlowRule that = (DefaultFlowRule) obj;
             return Objects.equals(deviceId, that.deviceId) &&
                     Objects.equals(priority, that.priority) &&
-                    Objects.equals(selector, that.selector);
+                    Objects.equals(selector, that.selector) &&
+                    Objects.equals(type, that.type);
 
         }
         return false;
@@ -216,6 +217,7 @@
                 .add("priority", priority)
                 .add("selector", selector.criteria())
                 .add("treatment", treatment == null ? "N/A" : treatment.instructions())
+                .add("table type", type)
                 .add("created", created)
                 .toString();
     }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
index 462875a..53aff49 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -33,7 +33,8 @@
      * For single table switch, Default is used.
      */
     public static enum Type {
-        /* Default type - used in flow rule for single table switch */
+        /* Default type - used in flow rule for single table switch
+         * NOTE: this setting should not be used as Table 0 in a multi-table pipeline*/
         DEFAULT,
         /* Used in flow entry for IP table */
         IP,
@@ -48,11 +49,14 @@
         /* VLAN table */
         VLAN,
 
-        /* L2 table */
+        /* Ethtype table */
         ETHER,
 
         /* Class of Service table */
         COS,
+
+        /* Table 0 in a multi-table pipeline */
+        FIRST,
     }
 
     //TODO: build cookie value
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
index fde80ed..6009420 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
@@ -63,7 +63,7 @@
         if (msg.getType() == OFType.FLOW_MOD) {
             OFFlowMod flowMod = (OFFlowMod) msg;
             OFFlowMod.Builder builder = flowMod.createBuilder();
-            List<OFInstruction> instructions = builder.getInstructions();
+            List<OFInstruction> instructions = flowMod.getInstructions();
             List<OFInstruction> newInstructions = Lists.newArrayList();
             for (OFInstruction i : instructions) {
                 if (i instanceof OFInstructionGotoTable) {
@@ -106,9 +106,11 @@
                                             .setTableId(TableId.of(LOCAL_TABLE)).build());
                             break;
                         case NONE:
-                            newInstructions.add(
+                            log.error("Should never have to go to Table 0");
+                            /*newInstructions.add(
                                     gotoTable.createBuilder()
                                             .setTableId(TableId.of(0)).build());
+                            */
                             break;
                         default:
                             log.warn("Unknown table type: {}", tid);
@@ -147,8 +149,10 @@
                     log.warn("Unknown table type: {}", type);
             }
             builder.setInstructions(newInstructions);
-            this.write(builder.build());
-            log.info("Installed {}", builder.build());
+            OFMessage msgnew = builder.build();
+            this.write(msgnew);
+            log.debug("Installed {}", msgnew);
+
         } else {
             this.write(msg);
         }
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index b1848f2..00bb197 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -97,19 +97,20 @@
         Match match = buildMatch();
         List<OFAction> actions = buildActions();
         List<OFInstruction> instructions = buildInstructions();
+
         // FIXME had to revert back to using apply-actions instead of
         // write-actions because LINC-OE apparently doesn't support
         // write-actions. I would prefer to change this back in the future
         // because apply-actions is an optional instruction in OF 1.3.
 
-        OFInstruction applyActions =
-                factory().instructions().applyActions(actions);
-
-        instructions.add(applyActions);
+        if (actions != null) {
+            OFInstruction applyActions =
+                    factory().instructions().applyActions(actions);
+            instructions.add(applyActions);
+        }
 
         long cookie = flowRule().id().value();
 
-
         OFFlowAdd fm = factory().buildFlowAdd()
                 .setXid(xid)
                 .setCookie(U64.of(cookie))
@@ -129,14 +130,15 @@
         Match match = buildMatch();
         List<OFAction> actions = buildActions();
         List<OFInstruction> instructions = buildInstructions();
-        OFInstruction applyActions =
-                factory().instructions().applyActions(actions);
 
-        instructions.add(applyActions);
+        if (actions != null) {
+            OFInstruction applyActions =
+                    factory().instructions().applyActions(actions);
+            instructions.add(applyActions);
+        }
 
         long cookie = flowRule().id().value();
 
-
         OFFlowMod fm = factory().buildFlowModify()
                 .setXid(xid)
                 .setCookie(U64.of(cookie))
@@ -189,6 +191,7 @@
 
     private List<OFAction> buildActions() {
         List<OFAction> actions = new LinkedList<>();
+        boolean tableFound = false;
         if (treatment == null) {
             return actions;
         }
@@ -223,12 +226,17 @@
                     break;
                 case TABLE:
                     //FIXME: should not occur here.
+                    tableFound = true;
                     break;
                 default:
                     log.warn("Instruction type {} not yet implemented.", i.type());
             }
         }
-
+        if (tableFound && actions.isEmpty()) {
+            // handles the case where there are no actions, but there is
+            // a goto instruction for the next table
+            return null;
+        }
         return actions;
     }