We do call heap_rebuild in ofproto_run, but we do not update rule's
priority with latest hard_timeout and idle_timeout before heap_rebuild.

This patch ensures that rule's priority has been updated before
heap_rebuild, and adds two test cases to check eviction with modified
hard_timeout and idle_timwout.

Signed-off-by: kmindg <kmi...@gmail.com>
---
 lib/heap.h        |  1 -
 ofproto/ofproto.c | 18 ++++++++------
 tests/ofproto.at  | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/lib/heap.h b/lib/heap.h
index 870f582..8829f11 100644
--- a/lib/heap.h
+++ b/lib/heap.h
@@ -55,7 +55,6 @@ static inline struct heap_node *heap_max(const struct heap *);
  * call them, heap_max() will not necessarily return the right value until you
  * subsequently call heap_rebuild(). */
 void heap_raw_insert(struct heap *, struct heap_node *, uint64_t priority);
-static inline void heap_raw_change(struct heap_node *, uint64_t priority);
 void heap_raw_remove(struct heap *, struct heap_node *);
 void heap_rebuild(struct heap *);
 
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index e691bb9..45621e9 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1451,19 +1451,23 @@ ofproto_run(struct ofproto *p)
             }
 
             ovs_mutex_lock(&ofproto_mutex);
-            HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) {
-                heap_rebuild(&evg->rules);
-            }
-
             fat_rwlock_rdlock(&table->cls.rwlock);
             cls_cursor_init(&cursor, &table->cls, NULL);
             CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
-                if (!rule->eviction_group
-                    && (rule->idle_timeout || rule->hard_timeout)) {
-                    eviction_group_add_rule(rule);
+                if (rule->idle_timeout || rule->hard_timeout) {
+                    if (!rule->eviction_group) {
+                        eviction_group_add_rule(rule);
+                    } else {
+                        heap_raw_change(&rule->evg_node,
+                                        rule_eviction_priority(p, rule));
+                    }
                 }
             }
             fat_rwlock_unlock(&table->cls.rwlock);
+
+            HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) {
+                heap_rebuild(&evg->rules);
+            }
             ovs_mutex_unlock(&ofproto_mutex);
         }
     }
diff --git a/tests/ofproto.at b/tests/ofproto.at
index f6a62cd..eb1680c 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -1365,6 +1365,80 @@ OFPST_FLOW reply (OF1.2):
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto - eviction upon table overflow, with modified hard timeout])
+OVS_VSWITCHD_START
+# Configure a maximum of 4 flows.
+AT_CHECK(
+  [ovs-vsctl \
+     -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
+     -- set bridge br0 flow_tables:0=@t0 \
+   | ${PERL} $srcdir/uuidfilt.pl],
+  [0], [<0>
+])
+# Add 4 flows.
+for in_port in 4 3 2 1; do
+    ovs-ofctl add-flow br0 
hard_timeout=1${in_port},in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ hard_timeout=11, in_port=1 actions=drop
+ hard_timeout=12, in_port=2 actions=drop
+ hard_timeout=13, in_port=3 actions=drop
+ hard_timeout=14, in_port=4 actions=drop
+NXST_FLOW reply:
+])
+# Sleep and modify the one that expires soonest
+sleep 2
+AT_CHECK([ovs-ofctl mod-flows br0 in_port=1,actions=drop])
+sleep 2
+# Adding another flow will cause the one that expires soonest to be evicted.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=5,actions=drop])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ hard_timeout=11, in_port=1 actions=drop
+ hard_timeout=13, in_port=3 actions=drop
+ hard_timeout=14, in_port=4 actions=drop
+ in_port=5 actions=drop
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - eviction upon table overflow, with modified idle timeout])
+OVS_VSWITCHD_START([add-port br0 p1 -- set interface p1 type=dummy 
ofport_request=1])
+# Configure a maximum of 4 flows.
+AT_CHECK(
+  [ovs-vsctl \
+     -- --id=@t0 create Flow_Table flow-limit=4 overflow-policy=evict \
+     -- set bridge br0 flow_tables:0=@t0 \
+   | ${PERL} $srcdir/uuidfilt.pl],
+  [0], [<0>
+])
+# Add 4 flows.
+for in_port in 4 3 2 1; do
+    ovs-ofctl add-flow br0 
idle_timeout=1${in_port},in_port=$in_port,actions=drop
+done
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=11, in_port=1 actions=drop
+ idle_timeout=12, in_port=2 actions=drop
+ idle_timeout=13, in_port=3 actions=drop
+ idle_timeout=14, in_port=4 actions=drop
+NXST_FLOW reply:
+])
+# Sleep and receive on the flow that expires soonest
+sleep 2
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1)'])
+sleep 2
+# Adding another flow will cause the one that expires soonest to be evicted.
+AT_CHECK([ovs-ofctl add-flow br0 in_port=5,actions=drop])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ idle_timeout=13, in_port=3 actions=drop
+ idle_timeout=14, in_port=4 actions=drop
+ in_port=5 actions=drop
+ n_packets=1, n_bytes=60, idle_timeout=11, in_port=1 actions=drop
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto - asynchronous message control (OpenFlow 1.0)])
 OVS_VSWITCHD_START
 AT_CHECK([ovs-ofctl -P openflow10 monitor br0 --detach --no-chdir --pidfile])
-- 
1.9.0

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to