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