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