[ovs-dev] [PATCH 1/5] ofproto: Fix double-unref of temporary rule when learning.

Ben Pfaff blp at ovn.org
Thu Jan 25 23:39:45 UTC 2018


When ofproto_flow_mod_init() accepts a rule, it takes ownership of it and
either unrefs it on error or transfers ownership to the struct it
initializes on success, but ofproto_flow_mod_init_for_learn() was unref-ing
it a second time if it reported an error.

Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 ofproto/ofproto-provider.h |  5 ++++-
 ofproto/ofproto.c          | 16 ++++++----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 9dc73c482119..ae4af4525705 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -1874,7 +1874,10 @@ struct rule_criteria {
 /* flow_mod with execution context. */
 struct ofproto_flow_mod {
     /* Allocated by 'init' phase, may be freed after 'start' phase, as these
-     * are not needed for 'revert' nor 'finish'. */
+     * are not needed for 'revert' nor 'finish'.
+     *
+     * This structure owns a reference to 'temp_rule' (if it is nonnull) that
+     * must be eventually be released with ofproto_rule_unref().  */
     struct rule *temp_rule;
     struct rule_criteria criteria;
     struct cls_conjunction *conjs;
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index d42acd747acc..76d96a6f93f3 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4948,15 +4948,14 @@ ofproto_rule_create(struct ofproto *ofproto, struct cls_rule *cr,
 
 /* Initialize 'ofm' for a learn action.  If the rule already existed, reference
  * to that rule is taken, otherwise a new rule is created.  'ofm' keeps the
- * rule reference in both.  This does not take the global 'ofproto_mutex'. */
+ * rule reference in both.  This does not take the global 'ofproto_mutex'.
+ */
 enum ofperr
 ofproto_flow_mod_init_for_learn(struct ofproto *ofproto,
                                 const struct ofputil_flow_mod *fm,
                                 struct ofproto_flow_mod *ofm)
     OVS_EXCLUDED(ofproto_mutex)
 {
-    enum ofperr error;
-
     /* Reject flow mods that do not look like they were generated by a learn
      * action. */
     if (fm->command != OFPFC_MODIFY_STRICT || fm->table_id == OFPTT_ALL
@@ -4997,13 +4996,7 @@ ofproto_flow_mod_init_for_learn(struct ofproto *ofproto,
         }
     }
 
-    /* Initialize ofproto_flow_mod for future use. */
-    error = ofproto_flow_mod_init(ofproto, ofm, fm, rule);
-    if (error) {
-        ofproto_rule_unref(rule);
-        return error;
-    }
-    return 0;
+    return ofproto_flow_mod_init(ofproto, ofm, fm, rule);
 }
 
 enum ofperr
@@ -7558,6 +7551,9 @@ ofproto_flow_mod_uninit(struct ofproto_flow_mod *ofm)
     }
 }
 
+/* Initializes 'ofm' with 'ofproto', 'fm', and 'rule'.  'rule' may be null, but
+ * if it is nonnull then the caller must own a reference to it, which on
+ * success is transferred to 'ofm' and on failure is unreffed. */
 static enum ofperr
 ofproto_flow_mod_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
                       const struct ofputil_flow_mod *fm, struct rule *rule)
-- 
2.10.2



More information about the dev mailing list