Nothing freed 'reply'.  This fixes the problem.

Most of this patch is moving coding around.  The essential change is that
breaking the code that works with 'reply' out into a separate function
makes it possible to catch all paths out of the function so that 'reply'
can be freed in one place.

Reported-by: Ryan Moats <rmo...@us.ibm.com>
Signed-off-by: Ben Pfaff <b...@ovn.org>
---
 ovn/controller/ofctrl.c | 124 ++++++++++++++++++++++++++----------------------
 1 file changed, 66 insertions(+), 58 deletions(-)

diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c
index d8e111d..584e260 100644
--- a/ovn/controller/ofctrl.c
+++ b/ovn/controller/ofctrl.c
@@ -199,83 +199,91 @@ run_S_TLV_TABLE_REQUESTED(void)
 {
 }
 
+static bool
+process_tlv_table_reply(const struct ofputil_tlv_table_reply *reply)
+{
+    const struct ofputil_tlv_map *map;
+    uint64_t md_free = UINT64_MAX;
+    BUILD_ASSERT(TUN_METADATA_NUM_OPTS == 64);
+
+    LIST_FOR_EACH (map, list_node, &reply->mappings) {
+        if (map->option_class == OVN_GENEVE_CLASS
+            && map->option_type == OVN_GENEVE_TYPE
+            && map->option_len == OVN_GENEVE_LEN) {
+            if (map->index >= TUN_METADATA_NUM_OPTS) {
+                VLOG_ERR("desired Geneve tunnel option 0x%"PRIx16","
+                         "%"PRIu8",%"PRIu8" already in use with "
+                         "unsupported index %"PRIu16,
+                         map->option_class, map->option_type,
+                         map->option_len, map->index);
+                return false;
+            } else {
+                mff_ovn_geneve = MFF_TUN_METADATA0 + map->index;
+                state = S_CLEAR_FLOWS;
+                return false;
+            }
+        }
+
+        if (map->index < TUN_METADATA_NUM_OPTS) {
+            md_free &= ~(UINT64_C(1) << map->index);
+        }
+    }
+
+    VLOG_DBG("OVN Geneve option not found");
+    if (!md_free) {
+        VLOG_ERR("no Geneve options free for use by OVN");
+        return false;
+    }
+
+    unsigned int index = rightmost_1bit_idx(md_free);
+    mff_ovn_geneve = MFF_TUN_METADATA0 + index;
+    struct ofputil_tlv_map tm;
+    tm.option_class = OVN_GENEVE_CLASS;
+    tm.option_type = OVN_GENEVE_TYPE;
+    tm.option_len = OVN_GENEVE_LEN;
+    tm.index = index;
+
+    struct ofputil_tlv_table_mod ttm;
+    ttm.command = NXTTMC_ADD;
+    ovs_list_init(&ttm.mappings);
+    ovs_list_push_back(&ttm.mappings, &tm.list_node);
+
+    xid = queue_msg(ofputil_encode_tlv_table_mod(OFP13_VERSION, &ttm));
+    xid2 = queue_msg(ofputil_encode_barrier_request(OFP13_VERSION));
+    state = S_TLV_TABLE_MOD_SENT;
+
+    return true;
+}
+
 static void
 recv_S_TLV_TABLE_REQUESTED(const struct ofp_header *oh, enum ofptype type)
 {
     if (oh->xid != xid) {
         ofctrl_recv(oh, type);
+        return;
     } else if (type == OFPTYPE_NXT_TLV_TABLE_REPLY) {
         struct ofputil_tlv_table_reply reply;
         enum ofperr error = ofputil_decode_tlv_table_reply(oh, &reply);
-        if (error) {
+        if (!error) {
+            bool ok = process_tlv_table_reply(&reply);
+            ofputil_uninit_tlv_table(&reply.mappings);
+            if (ok) {
+                return;
+            }
+        } else {
             VLOG_ERR("failed to decode TLV table request (%s)",
                      ofperr_to_string(error));
-            goto error;
-        }
-
-        const struct ofputil_tlv_map *map;
-        uint64_t md_free = UINT64_MAX;
-        BUILD_ASSERT(TUN_METADATA_NUM_OPTS == 64);
-
-        LIST_FOR_EACH (map, list_node, &reply.mappings) {
-            if (map->option_class == OVN_GENEVE_CLASS
-                && map->option_type == OVN_GENEVE_TYPE
-                && map->option_len == OVN_GENEVE_LEN) {
-                if (map->index >= TUN_METADATA_NUM_OPTS) {
-                    VLOG_ERR("desired Geneve tunnel option 0x%"PRIx16","
-                             "%"PRIu8",%"PRIu8" already in use with "
-                             "unsupported index %"PRIu16,
-                             map->option_class, map->option_type,
-                             map->option_len, map->index);
-                    goto error;
-                } else {
-                    mff_ovn_geneve = MFF_TUN_METADATA0 + map->index;
-                    state = S_CLEAR_FLOWS;
-                    return;
-                }
-            }
-
-            if (map->index < TUN_METADATA_NUM_OPTS) {
-                md_free &= ~(UINT64_C(1) << map->index);
-            }
-        }
-
-        VLOG_DBG("OVN Geneve option not found");
-        if (!md_free) {
-            VLOG_ERR("no Geneve options free for use by OVN");
-            goto error;
         }
-
-        unsigned int index = rightmost_1bit_idx(md_free);
-        mff_ovn_geneve = MFF_TUN_METADATA0 + index;
-        struct ofputil_tlv_map tm;
-        tm.option_class = OVN_GENEVE_CLASS;
-        tm.option_type = OVN_GENEVE_TYPE;
-        tm.option_len = OVN_GENEVE_LEN;
-        tm.index = index;
-
-        struct ofputil_tlv_table_mod ttm;
-        ttm.command = NXTTMC_ADD;
-        ovs_list_init(&ttm.mappings);
-        ovs_list_push_back(&ttm.mappings, &tm.list_node);
-
-        xid = queue_msg(ofputil_encode_tlv_table_mod(OFP13_VERSION, &ttm));
-        xid2 = queue_msg(ofputil_encode_barrier_request(OFP13_VERSION));
-        state = S_TLV_TABLE_MOD_SENT;
     } else if (type == OFPTYPE_ERROR) {
         VLOG_ERR("switch refused to allocate Geneve option (%s)",
                  ofperr_to_string(ofperr_decode_msg(oh, NULL)));
-        goto error;
     } else {
         char *s = ofp_to_string(oh, ntohs(oh->length), 1);
-        VLOG_ERR("unexpected reply to TLV table request (%s)",
-                 s);
+        VLOG_ERR("unexpected reply to TLV table request (%s)", s);
         free(s);
-        goto error;
     }
-    return;
 
-error:
+    /* Error path. */
     mff_ovn_geneve = 0;
     state = S_CLEAR_FLOWS;
 }
-- 
2.1.3

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

Reply via email to