Acked-by: Andy Zhou <az...@nicira.com>
On Tue, Mar 11, 2014 at 1:56 PM, Ben Pfaff <b...@nicira.com> wrote: > Signed-off-by: Ben Pfaff <b...@nicira.com> > > Conflicts: > lib/ovs-rcu.h > --- > ofproto/connmgr.c | 5 +- > ofproto/ofproto-dpif-xlate.c | 2 - > ofproto/ofproto-dpif.c | 2 - > ofproto/ofproto-provider.h | 19 ++++--- > ofproto/ofproto.c | 119 > ++++++++++++++++++------------------------ > 5 files changed, 63 insertions(+), 84 deletions(-) > > diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c > index 033ab7d..0058309 100644 > --- a/ofproto/connmgr.c > +++ b/ofproto/connmgr.c > @@ -2043,8 +2043,9 @@ ofmonitor_report(struct connmgr *mgr, struct rule > *rule, > ovs_mutex_unlock(&rule->mutex); > > if (flags & NXFMF_ACTIONS) { > - fu.ofpacts = rule->actions->ofpacts; > - fu.ofpacts_len = rule->actions->ofpacts_len; > + struct rule_actions *actions = rule_get_actions(rule); > + fu.ofpacts = actions->ofpacts; > + fu.ofpacts_len = actions->ofpacts_len; > } else { > fu.ofpacts = NULL; > fu.ofpacts_len = 0; > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index eb4931e..5201b93 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -1836,7 +1836,6 @@ xlate_recursively(struct xlate_ctx *ctx, struct > rule_dpif *rule) > ctx->rule = rule; > actions = rule_dpif_get_actions(rule); > do_xlate_actions(actions->ofpacts, actions->ofpacts_len, ctx); > - rule_actions_unref(actions); > ctx->rule = old_rule; > ctx->recurse--; > } > @@ -3171,7 +3170,6 @@ xlate_actions__(struct xlate_in *xin, struct > xlate_out *xout) > } > > out: > - rule_actions_unref(actions); > rule_dpif_unref(rule); > } > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 8c43ee9..1c779ee 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -3587,8 +3587,6 @@ trace_format_rule(struct ds *result, int level, > const struct rule_dpif *rule) > ds_put_cstr(result, "OpenFlow actions="); > ofpacts_format(actions->ofpacts, actions->ofpacts_len, result); > ds_put_char(result, '\n'); > - > - rule_actions_unref(actions); > } > > static void > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h > index 2c72fbc..956e593 100644 > --- a/ofproto/ofproto-provider.h > +++ b/ofproto/ofproto-provider.h > @@ -1,5 +1,5 @@ > /* > - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. > + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -43,6 +43,7 @@ > #include "ofp-util.h" > #include "ofproto/ofproto.h" > #include "ovs-atomic.h" > +#include "ovs-rcu.h" > #include "ovs-thread.h" > #include "shash.h" > #include "simap.h" > @@ -374,7 +375,7 @@ struct rule { > > /* OpenFlow actions. See struct rule_actions for more thread-safety > * notes. */ > - struct rule_actions *actions OVS_GUARDED; > + OVSRCU_TYPE(struct rule_actions *) actions; > > /* In owning meter's 'rules' list. An empty list if there is no > meter. */ > struct list meter_list_node OVS_GUARDED_BY(ofproto_mutex); > @@ -403,10 +404,11 @@ struct rule { > void ofproto_rule_ref(struct rule *); > void ofproto_rule_unref(struct rule *); > > -struct rule_actions *rule_get_actions(const struct rule *rule) > - OVS_EXCLUDED(rule->mutex); > -struct rule_actions *rule_get_actions__(const struct rule *rule) > - OVS_REQUIRES(rule->mutex); > +static inline struct rule_actions * > +rule_get_actions(const struct rule *rule) > +{ > + return ovsrcu_get(struct rule_actions *, &rule->actions); > +} > > /* Returns true if 'rule' is an OpenFlow 1.3 "table-miss" rule, false > * otherwise. > @@ -431,8 +433,6 @@ rule_is_table_miss(const struct rule *rule) > * 'rule' is the rule for which 'rule->actions == actions') or that owns a > * reference to 'actions->ref_count' (or both). */ > struct rule_actions { > - struct ovs_refcount ref_count; > - > /* These members are immutable: they do not change during the struct's > * lifetime. */ > struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */ > @@ -442,8 +442,7 @@ struct rule_actions { > > struct rule_actions *rule_actions_create(const struct ofproto *, > const struct ofpact *, size_t); > -void rule_actions_ref(struct rule_actions *); > -void rule_actions_unref(struct rule_actions *); > +void rule_actions_destroy(struct rule_actions *); > > /* A set of rules to which an OpenFlow operation applies. */ > struct rule_collection { > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index d61e618..d0daea4 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -43,6 +43,7 @@ > #include "ofproto-provider.h" > #include "openflow/nicira-ext.h" > #include "openflow/openflow.h" > +#include "ovs-rcu.h" > #include "packets.h" > #include "pinsched.h" > #include "pktbuf.h" > @@ -1897,11 +1898,9 @@ ofproto_add_flow(struct ofproto *ofproto, const > struct match *match, > rule = rule_from_cls_rule(classifier_find_match_exactly( > &ofproto->tables[0].cls, match, > priority)); > if (rule) { > - ovs_mutex_lock(&rule->mutex); > - must_add = !ofpacts_equal(rule->actions->ofpacts, > - rule->actions->ofpacts_len, > + struct rule_actions *actions = rule_get_actions(rule); > + must_add = !ofpacts_equal(actions->ofpacts, actions->ofpacts_len, > ofpacts, ofpacts_len); > - ovs_mutex_unlock(&rule->mutex); > } else { > must_add = true; > } > @@ -1945,14 +1944,16 @@ ofproto_flow_mod(struct ofproto *ofproto, struct > ofputil_flow_mod *fm) > /* Reading many of the rule fields and writing on 'modified' > * requires the rule->mutex. Also, rule->actions may change > * if rule->mutex is not held. */ > + const struct rule_actions *actions; > + > ovs_mutex_lock(&rule->mutex); > + actions = rule_get_actions(rule); > if (rule->idle_timeout == fm->idle_timeout > && rule->hard_timeout == fm->hard_timeout > && rule->flags == (fm->flags & OFPUTIL_FF_STATE) > && (!fm->modify_cookie || (fm->new_cookie == > rule->flow_cookie)) > && ofpacts_equal(fm->ofpacts, fm->ofpacts_len, > - rule->actions->ofpacts, > - rule->actions->ofpacts_len)) { > + actions->ofpacts, actions->ofpacts_len)) > { > /* Rule already exists and need not change, only update > the > modified timestamp. */ > rule->modified = time_msec(); > @@ -2574,33 +2575,12 @@ ofproto_rule_unref(struct rule *rule) > } > } > > -struct rule_actions * > -rule_get_actions(const struct rule *rule) > - OVS_EXCLUDED(rule->mutex) > -{ > - struct rule_actions *actions; > - > - ovs_mutex_lock(&rule->mutex); > - actions = rule_get_actions__(rule); > - ovs_mutex_unlock(&rule->mutex); > - > - return actions; > -} > - > -struct rule_actions * > -rule_get_actions__(const struct rule *rule) > - OVS_REQUIRES(rule->mutex) > -{ > - rule_actions_ref(rule->actions); > - return rule->actions; > -} > - > static void > ofproto_rule_destroy__(struct rule *rule) > OVS_NO_THREAD_SAFETY_ANALYSIS > { > cls_rule_destroy(CONST_CAST(struct cls_rule *, &rule->cr)); > - rule_actions_unref(rule->actions); > + rule_actions_destroy(rule_get_actions(rule)); > ovs_mutex_destroy(&rule->mutex); > rule->ofproto->ofproto_class->rule_dealloc(rule); > } > @@ -2617,7 +2597,6 @@ rule_actions_create(const struct ofproto *ofproto, > struct rule_actions *actions; > > actions = xmalloc(sizeof *actions); > - ovs_refcount_init(&actions->ref_count); > actions->ofpacts = xmemdup(ofpacts, ofpacts_len); > actions->ofpacts_len = ofpacts_len; > actions->provider_meter_id > @@ -2627,23 +2606,20 @@ rule_actions_create(const struct ofproto *ofproto, > return actions; > } > > -/* Increments 'actions''s ref_count. */ > -void > -rule_actions_ref(struct rule_actions *actions) > +static void > +rule_actions_destroy_cb(struct rule_actions *actions) > { > - if (actions) { > - ovs_refcount_ref(&actions->ref_count); > - } > + free(actions->ofpacts); > + free(actions); > } > > /* Decrements 'actions''s ref_count and frees 'actions' if the ref_count > * reaches 0. */ > void > -rule_actions_unref(struct rule_actions *actions) > +rule_actions_destroy(struct rule_actions *actions) > { > - if (actions && ovs_refcount_unref(&actions->ref_count) == 1) { > - free(actions->ofpacts); > - free(actions); > + if (actions) { > + ovsrcu_postpone(rule_actions_destroy_cb, actions); > } > } > > @@ -2653,9 +2629,13 @@ static bool > ofproto_rule_has_out_port(const struct rule *rule, ofp_port_t port) > OVS_REQUIRES(ofproto_mutex) > { > - return (port == OFPP_ANY > - || ofpacts_output_to_port(rule->actions->ofpacts, > - rule->actions->ofpacts_len, port)); > + if (port == OFPP_ANY) { > + return true; > + } else { > + const struct rule_actions *actions = rule_get_actions(rule); > + return ofpacts_output_to_port(actions->ofpacts, > + actions->ofpacts_len, port); > + } > } > > /* Returns true if 'rule' has group and equals group_id. */ > @@ -2663,9 +2643,13 @@ static bool > ofproto_rule_has_out_group(const struct rule *rule, uint32_t group_id) > OVS_REQUIRES(ofproto_mutex) > { > - return (group_id == OFPG11_ANY > - || ofpacts_output_to_group(rule->actions->ofpacts, > - rule->actions->ofpacts_len, > group_id)); > + if (group_id == OFPG_ANY) { > + return true; > + } else { > + const struct rule_actions *actions = rule_get_actions(rule); > + return ofpacts_output_to_group(actions->ofpacts, > + actions->ofpacts_len, group_id); > + } > } > > /* Returns true if a rule related to 'op' has an OpenFlow OFPAT_OUTPUT or > @@ -3593,7 +3577,7 @@ handle_flow_stats_request(struct ofconn *ofconn, > fs.hard_timeout = rule->hard_timeout; > created = rule->created; > modified = rule->modified; > - actions = rule_get_actions__(rule); > + actions = rule_get_actions(rule); > flags = rule->flags; > ovs_mutex_unlock(&rule->mutex); > > @@ -3611,8 +3595,6 @@ handle_flow_stats_request(struct ofconn *ofconn, > > fs.flags = flags; > ofputil_append_flow_stats_reply(&fs, &replies); > - > - rule_actions_unref(actions); > } > > rule_collection_unref(&rules); > @@ -3634,7 +3616,7 @@ flow_stats_ds(struct rule *rule, struct ds *results) > &byte_count, &used); > > ovs_mutex_lock(&rule->mutex); > - actions = rule_get_actions__(rule); > + actions = rule_get_actions(rule); > created = rule->created; > ovs_mutex_unlock(&rule->mutex); > > @@ -3651,8 +3633,6 @@ flow_stats_ds(struct rule *rule, struct ds *results) > ofpacts_format(actions->ofpacts, actions->ofpacts_len, results); > > ds_put_cstr(results, "\n"); > - > - rule_actions_unref(actions); > } > > /* Adds a pretty-printed description of all flows to 'results', including > @@ -4057,7 +4037,8 @@ add_flow(struct ofproto *ofproto, struct ofconn > *ofconn, > > *CONST_CAST(uint8_t *, &rule->table_id) = table - ofproto->tables; > rule->flags = fm->flags & OFPUTIL_FF_STATE; > - rule->actions = rule_actions_create(ofproto, fm->ofpacts, > fm->ofpacts_len); > + ovsrcu_set(&rule->actions, > + rule_actions_create(ofproto, fm->ofpacts, > fm->ofpacts_len)); > list_init(&rule->meter_list_node); > rule->eviction_group = NULL; > list_init(&rule->expirable); > @@ -4108,6 +4089,7 @@ modify_flows__(struct ofproto *ofproto, struct > ofconn *ofconn, > error = OFPERR_OFPBRC_EPERM; > for (i = 0; i < rules->n; i++) { > struct rule *rule = rules->rules[i]; > + const struct rule_actions *actions; > struct ofoperation *op; > bool actions_changed; > bool reset_counters; > @@ -4121,9 +4103,10 @@ modify_flows__(struct ofproto *ofproto, struct > ofconn *ofconn, > continue; > } > > + actions = rule_get_actions(rule); > actions_changed = !ofpacts_equal(fm->ofpacts, fm->ofpacts_len, > - rule->actions->ofpacts, > - rule->actions->ofpacts_len); > + actions->ofpacts, > + actions->ofpacts_len); > > op = ofoperation_create(group, rule, type, 0); > > @@ -4150,13 +4133,11 @@ modify_flows__(struct ofproto *ofproto, struct > ofconn *ofconn, > if (actions_changed || reset_counters) { > struct rule_actions *new_actions; > > - op->actions = rule->actions; > + op->actions = rule_get_actions(rule); > new_actions = rule_actions_create(ofproto, > fm->ofpacts, > fm->ofpacts_len); > > - ovs_mutex_lock(&rule->mutex); > - rule->actions = new_actions; > - ovs_mutex_unlock(&rule->mutex); > + ovsrcu_set(&rule->actions, new_actions); > > rule->ofproto->ofproto_class->rule_modify_actions(rule, > > reset_counters); > @@ -4737,7 +4718,7 @@ ofproto_compose_flow_refresh_update(const struct > rule *rule, > if (!(flags & NXFMF_ACTIONS)) { > actions = NULL; > } else if (!op) { > - actions = rule->actions; > + actions = rule_get_actions(rule); > } else { > /* An operation is in progress. Use the previous version of the > flow's > * actions, so that when the operation commits we report the > change. */ > @@ -4747,11 +4728,11 @@ ofproto_compose_flow_refresh_update(const struct > rule *rule, > > case OFOPERATION_MODIFY: > case OFOPERATION_REPLACE: > - actions = op->actions ? op->actions : rule->actions; > + actions = op->actions ? op->actions : rule_get_actions(rule); > break; > > case OFOPERATION_DELETE: > - actions = rule->actions; > + actions = rule_get_actions(rule); > break; > > default: > @@ -6241,12 +6222,12 @@ ofopgroup_complete(struct ofopgroup *group) > struct rule_actions *old_actions; > > ovs_mutex_lock(&rule->mutex); > - old_actions = rule->actions; > - rule->actions = op->actions; > + old_actions = rule_get_actions(rule); > + ovsrcu_set(&rule->actions, op->actions); > ovs_mutex_unlock(&rule->mutex); > > op->actions = NULL; > - rule_actions_unref(old_actions); > + rule_actions_destroy(old_actions); > } > rule->flags = op->flags; > } > @@ -6332,7 +6313,7 @@ ofoperation_destroy(struct ofoperation *op) > hmap_remove(&group->ofproto->deletions, &op->hmap_node); > } > list_remove(&op->group_node); > - rule_actions_unref(op->actions); > + rule_actions_destroy(op->actions); > free(op); > } > > @@ -6814,6 +6795,7 @@ oftable_insert_rule(struct rule *rule) > { > struct ofproto *ofproto = rule->ofproto; > struct oftable *table = &ofproto->tables[rule->table_id]; > + struct rule_actions *actions; > bool may_expire; > > ovs_mutex_lock(&rule->mutex); > @@ -6826,9 +6808,10 @@ oftable_insert_rule(struct rule *rule) > > cookies_insert(ofproto, rule); > > - if (rule->actions->provider_meter_id != UINT32_MAX) { > - uint32_t meter_id = ofpacts_get_meter(rule->actions->ofpacts, > - rule->actions->ofpacts_len); > + actions = rule_get_actions(rule); > + if (actions->provider_meter_id != UINT32_MAX) { > + uint32_t meter_id = ofpacts_get_meter(actions->ofpacts, > + actions->ofpacts_len); > struct meter *meter = ofproto->meters[meter_id]; > list_insert(&meter->rules, &rule->meter_list_node); > } > -- > 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