Acked-by: Ethan Jackson <et...@nicira.com>
On Mon, Aug 26, 2013 at 5:10 PM, Ben Pfaff <b...@nicira.com> wrote: > In an Open vSwitch flow table that has a configured maximum number of > flows, flows that have an idle or hard timeout, or both, are expirable, > and flows with neither are permanent. The fin_timeout action can change > a flow that has no idle or hard timeout into one that has either one or > both, which should make a permanent flow into an expirable one, but the > implementation was buggy and did not actually make the flow expirable. > This commit fixes the problem. > > This commit also moves most of the implementation of fin_timeout from > ofproto-dpif-xlate into ofproto, because this seems to better respect the > layering. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > ofproto/ofproto-dpif-xlate.c | 24 ++---------------------- > ofproto/ofproto-provider.h | 3 +++ > ofproto/ofproto.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 46 insertions(+), 22 deletions(-) > > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index 54fabfe..eeccbc5 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -2111,33 +2111,13 @@ xlate_learn_action(struct xlate_ctx *ctx, > ofproto_dpif_flow_mod(ctx->xbridge->ofproto, fm); > } > > -/* Reduces '*timeout' to no more than 'max'. A value of zero in either case > - * means "infinite". */ > -static void > -reduce_timeout(uint16_t max, uint16_t *timeout) > -{ > - if (max && (!*timeout || *timeout > max)) { > - *timeout = max; > - } > -} > - > static void > xlate_fin_timeout(struct xlate_ctx *ctx, > const struct ofpact_fin_timeout *oft) > { > if (ctx->xin->tcp_flags & (TCP_FIN | TCP_RST) && ctx->rule) { > - struct rule_dpif *rule = ctx->rule; > - > - ovs_mutex_lock(&rule->up.ofproto->expirable_mutex); > - if (list_is_empty(&rule->up.expirable)) { > - list_insert(&rule->up.ofproto->expirable, &rule->up.expirable); > - } > - ovs_mutex_unlock(&rule->up.ofproto->expirable_mutex); > - > - ovs_mutex_lock(&rule->up.timeout_mutex); > - reduce_timeout(oft->fin_idle_timeout, &rule->up.idle_timeout); > - reduce_timeout(oft->fin_hard_timeout, &rule->up.hard_timeout); > - ovs_mutex_unlock(&rule->up.timeout_mutex); > + ofproto_rule_reduce_timeouts(&ctx->rule->up, oft->fin_idle_timeout, > + oft->fin_hard_timeout); > } > } > > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h > index d8b6a79..72ba3be 100644 > --- a/ofproto/ofproto-provider.h > +++ b/ofproto/ofproto-provider.h > @@ -281,6 +281,9 @@ void ofproto_rule_expire(struct rule *rule, uint8_t > reason) > OVS_RELEASES(rule->evict); > void ofproto_rule_destroy(struct ofproto *, struct classifier *cls, > struct rule *) OVS_REQ_WRLOCK(cls->rwlock); > +void ofproto_rule_reduce_timeouts(struct rule *rule, uint16_t idle_timeout, > + uint16_t hard_timeout) > + OVS_EXCLUDED(rule->ofproto->expirable_mutex, rule->timeout_mutex); > > bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t out_port); > > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index 709fd07..4e3efbe 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -186,6 +186,7 @@ static bool choose_rule_to_evict(struct oftable *table, > struct rule **rulep) > OVS_TRY_WRLOCK(true, (*rulep)->evict); > static void ofproto_evict(struct ofproto *); > static uint32_t rule_eviction_priority(struct rule *); > +static void eviction_group_add_rule(struct rule *rule); > > /* ofport. */ > static void ofport_destroy__(struct ofport *); > @@ -3785,6 +3786,46 @@ ofproto_rule_expire(struct rule *rule, uint8_t reason) > ofproto->ofproto_class->rule_destruct(rule); > ofopgroup_submit(group); > } > + > +/* Reduces '*timeout' to no more than 'max'. A value of zero in either case > + * means "infinite". */ > +static void > +reduce_timeout(uint16_t max, uint16_t *timeout) > +{ > + if (max && (!*timeout || *timeout > max)) { > + *timeout = max; > + } > +} > + > +/* If 'idle_timeout' is nonzero, and 'rule' has no idle timeout or an idle > + * timeout greater than 'idle_timeout', lowers 'rule''s idle timeout to > + * 'idle_timeout' seconds. Similarly for 'hard_timeout'. > + * > + * Suitable for implementing OFPACT_FIN_TIMEOUT. */ > +void > +ofproto_rule_reduce_timeouts(struct rule *rule, > + uint16_t idle_timeout, uint16_t hard_timeout) > + OVS_EXCLUDED(rule->ofproto->expirable_mutex, rule->timeout_mutex) > +{ > + if (!idle_timeout && !hard_timeout) { > + return; > + } > + > + ovs_mutex_lock(&rule->ofproto->expirable_mutex); > + if (list_is_empty(&rule->expirable)) { > + list_insert(&rule->ofproto->expirable, &rule->expirable); > + } > + ovs_mutex_unlock(&rule->ofproto->expirable_mutex); > + > + ovs_mutex_lock(&rule->timeout_mutex); > + reduce_timeout(idle_timeout, &rule->idle_timeout); > + reduce_timeout(hard_timeout, &rule->hard_timeout); > + ovs_mutex_unlock(&rule->timeout_mutex); > + > + if (!rule->eviction_group) { > + eviction_group_add_rule(rule); > + } > +} > > static enum ofperr > handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) > -- > 1.7.10.4 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev