Allowed flows to be permanent

Change-Id: I61952fe4cbad98be53094c7ec4a474868384b616
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
index 905469f..cf448cb 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowEntry.java
@@ -27,7 +27,7 @@
             TrafficTreatment treatment, int priority, FlowEntryState state,
             long life, long packets, long bytes, long flowId,
             int timeout) {
-        super(deviceId, selector, treatment, priority, flowId, timeout);
+        super(deviceId, selector, treatment, priority, flowId, timeout, false);
         this.state = state;
         this.life = life;
         this.packets = packets;
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
index 6ecbbbc..a6593a8 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
@@ -24,16 +24,18 @@
     private final short appId;
 
     private final int timeout;
+    private final boolean permanent;
 
 
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
             TrafficTreatment treatment, int priority, long flowId,
-            int timeout) {
+            int timeout, boolean permanent) {
         this.deviceId = deviceId;
         this.priority = priority;
         this.selector = selector;
         this.treatment = treatment;
         this.timeout = timeout;
+        this.permanent = permanent;
         this.created = System.currentTimeMillis();
 
         this.appId = (short) (flowId >>> 48);
@@ -42,7 +44,7 @@
 
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
             TrafficTreatment treatement, int priority, ApplicationId appId,
-            int timeout) {
+            int timeout, boolean permanent) {
 
         if (priority < FlowRule.MIN_PRIORITY) {
             throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
@@ -54,6 +56,7 @@
         this.treatment = treatement;
         this.appId = appId.id();
         this.timeout = timeout;
+        this.permanent = permanent;
         this.created = System.currentTimeMillis();
 
         this.id = FlowId.valueOf((((long) this.appId) << 48) | (this.hash() & 0x0000ffffffffL));
@@ -67,6 +70,7 @@
         this.appId = rule.appId();
         this.id = rule.id();
         this.timeout = rule.timeout();
+        this.permanent = rule.isPermanent();
         this.created = System.currentTimeMillis();
 
     }
@@ -157,4 +161,9 @@
         return timeout;
     }
 
+    @Override
+    public boolean isPermanent() {
+        return permanent;
+    }
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
index c63f247..3ac277d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
@@ -59,8 +59,16 @@
 
     /**
      * Returns the timeout for this flow requested by an application.
+     *
      * @return integer value of the timeout
      */
     int timeout();
 
+    /**
+     * Returns whether the flow is permanent i.e. does not time out.
+     *
+     * @return true if the flow is permanent, otherwise false
+     */
+    boolean isPermanent();
+
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 525946e..67e0867 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -327,6 +327,10 @@
             if (storedRule == null) {
                 return false;
             }
+            if (storedRule.isPermanent()) {
+                return true;
+            }
+
             final long timeout = storedRule.timeout() * 1000;
             final long currentTime = System.currentTimeMillis();
             if (storedRule.packets() != swRule.packets()) {
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java
index 2deb837..b3eb0f5 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java
@@ -117,7 +117,7 @@
         TrafficTreatment treatment = builder().setOutput(outPort).build();
 
         FlowRule rule = new DefaultFlowRule(deviceId,
-                selector, treatment, 123, appId, 600);
+                selector, treatment, 123, appId, 0, true);
 
         return new FlowRuleBatchEntry(operation, rule);
     }
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
index 0baea5a..a7381b7 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
@@ -73,7 +73,7 @@
 
             FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
                     builder.build(), treatment,
-                    123, appId, 15);
+                    123, appId, 0, true);
             rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
             prev = link.dst();
         }
@@ -95,7 +95,7 @@
                     .setOutput(link.src().port()).build();
             FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
                     builder.build(), treatment,
-                    123, appId, 600);
+                    123, appId, 0, true);
             rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
             prev = link.dst();
         }
diff --git a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
index dff740a..ca7cc07 100644
--- a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
@@ -1,7 +1,11 @@
 package org.onlab.onos.net.flow.impl;
 
 import static java.util.Collections.EMPTY_LIST;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
@@ -115,7 +119,7 @@
     private FlowRule flowRule(int tsval, int trval) {
         TestSelector ts = new TestSelector(tsval);
         TestTreatment tr = new TestTreatment(trval);
-        return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT);
+        return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
     }