[ovs-dev] [PATCH ovn] logical-fields: fix memory leak while initializing ovnfield_by_name

Damijan Skvarc damjan.skvarc at gmail.com
Wed Aug 7 10:49:37 UTC 2019


ovnfield_by_name is a hash table, intended to quicky find ovn_field by
name from a list of supported ovn_fields. This hash table is initialized
in ovn_init_symtab() function based on ovn_fields const array. In case
ovn_init_symtab() function is called multiple times then hash table is
reinitialized multiple times without deallocating previously allocated
memory. This is actually what happens in ovn_controller by initializing
lflow.symtab and ofctrl.symtab tables.

Since ovnfield_by_name is initialized twice with same values I have
introduced a flag indicating ovnfield_by_name is already initialized
or not and based on this flag hash table is prevented to be initialized
multiple times.

Note that currently ovn_fields array is constituted from one single
entry and thus searching a list of one entry by using helper hash table
is somehow useless. Memory leak could be solved by simply removing
ovnfield_by_name table and do a linear search through a list of single
entry. However I want to keep previous functionality in case ovn_fields
array will be extended somewhen in the future.

Signed-off-by: Damijan Skvarc <damjan.skvarc at gmail.com>
---
 lib/logical-fields.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/lib/logical-fields.c b/lib/logical-fields.c
index 4ad5bf4..62b9a71 100644
--- a/lib/logical-fields.c
+++ b/lib/logical-fields.c
@@ -57,6 +57,23 @@ add_ct_bit(const char *name, int index, struct shash *symtab)
     free(expansion);
 }
 
+
+static void
+init_ovnfield_by_name()
+{
+    static bool initialized = 0;
+
+    if (0 == initialized) {
+        shash_init(&ovnfield_by_name);
+        for (int i = 0; i < OVN_FIELD_N_IDS; i++) {
+            const struct ovn_field *of = &ovn_fields[i];
+            ovs_assert(of->id == i); /* Fields must be in the enum order. */
+            shash_add_once(&ovnfield_by_name, of->name, of);
+        }
+        initialized=1;
+    }
+}
+
 void
 ovn_init_symtab(struct shash *symtab)
 {
@@ -218,12 +235,8 @@ ovn_init_symtab(struct shash *symtab)
     expr_symtab_add_field(symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false);
     expr_symtab_add_field(symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
 
-    shash_init(&ovnfield_by_name);
-    for (int i = 0; i < OVN_FIELD_N_IDS; i++) {
-        const struct ovn_field *of = &ovn_fields[i];
-        ovs_assert(of->id == i); /* Fields must be in the enum order. */
-        shash_add_once(&ovnfield_by_name, of->name, of);
-    }
+    init_ovnfield_by_name();
+
     expr_symtab_add_ovn_field(symtab, "icmp4.frag_mtu", OVN_ICMP4_FRAG_MTU);
 }
 
-- 
2.7.4



More information about the dev mailing list