[ovs-dev] [PATCH] ovn-controller: Fix memory leak in recv_S_TLV_TABLE_REQUESTED().
Flavio Fernandes
flavio at flaviof.com
Thu Sep 1 18:27:55 UTC 2016
> On Sep 1, 2016, at 1:02 PM, Ben Pfaff <blp at ovn.org> wrote:
>
> 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.
>
+1 for moving it into a function and calling "ofputil_uninit_tlv_table(&reply.mappings);"
in a single place!
> Reported-by: Ryan Moats <rmoats at us.ibm.com>
> Signed-off-by: Ben Pfaff <blp at ovn.org>
Acked-by: Flavio Fernandes <flavio at flaviof.com>
> ---
> 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 at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
More information about the dev
mailing list