jvpp: fix memory allocation for variable lenght messages (VPP-841) 09/6709/4
authorMarek Gradzki <mgradzki@cisco.com>
Fri, 12 May 2017 16:24:34 +0000 (18:24 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Mon, 15 May 2017 17:27:01 +0000 (17:27 +0000)
Change-Id: I9a46125e3cf9815c08cf8cca17713ec6e9121eae
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
(cherry picked from commit 307cfd8eb14ff7df04316ffa56f2c2481d650d7e)

src/vpp-api/java/jvpp/gen/jvpp_gen.py
src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py
src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py
src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py

index 2a5ada9..7932741 100755 (executable)
@@ -96,14 +96,16 @@ def is_response_field(field_name):
 
 
 def get_args(t, filter):
-    arg_list = []
+    arg_names = []
+    arg_types = []
     for i in t:
         if is_crc(i):
             continue
         if not filter(i[1]):
             continue
-        arg_list.append(i[1])
-    return arg_list
+        arg_types.append(i[0])
+        arg_names.append(i[1])
+    return arg_types, arg_names
 
 
 def get_types(t, filter):
@@ -143,16 +145,18 @@ def get_definitions(defs):
         # For replies include all the arguments except message_id
         if util.is_reply(java_name):
             types, lengths, crc = get_types(a[1:], is_response_field)
+            args = get_args(a[1:], is_response_field)
             func_name[a[0]] = dict(
                 [('name', a[0]), ('java_name', java_name),
-                 ('args', get_args(a[1:], is_response_field)), ('full_args', get_args(a[1:], lambda x: True)),
+                 ('args', args[1]), ('arg_types', args[0]),
                  ('types', types), ('lengths', lengths), crc])
         # For requests skip message_id, client_id and context
         else:
             types, lengths, crc = get_types(a[1:], is_request_field)
+            args = get_args(a[1:], is_request_field)
             func_name[a[0]] = dict(
                 [('name', a[0]), ('java_name', java_name),
-                 ('args', get_args(a[1:], is_request_field)), ('full_args', get_args(a[1:], lambda x: True)),
+                 ('args', args[1]), ('arg_types', args[0]),
                  ('types', types), ('lengths', lengths), crc])
 
         # Indexed by name
index 328cc8d..cb0d66e 100644 (file)
@@ -248,16 +248,13 @@ struct_setter_templates = {'u8': u8_struct_setter_template,
                            }
 
 
-def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length,
-                                 is_variable_len_array, object_name="request"):
+def jni_request_identifiers_for_type(field_type, field_reference_name, field_name, object_name="request"):
     """
-    Generates jni code that initializes C structure that corresponds to a field of java object
+    Generates jni code that defines C variable corresponding to field of java object
     (dto or custom type). To be used in request message handlers.
     :param field_type: type of the field to be initialized (as defined in vpe.api)
-    :param c_name: name of the message struct member to be initialized
     :param field_reference_name: name of the field reference in generated code
     :param field_name: name of the field (camelcase)
-    :param field_length: integer or name of variable that stores field length
     :param object_name: name of the object to be initialized
     """
     # field identifiers
@@ -266,7 +263,7 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field
     jni_getter = util.jni_field_accessors[field_type]
 
     # field identifier
-    msg_initialization = request_field_identifier_template.substitute(
+    return request_field_identifier_template.substitute(
             jni_type=jni_type,
             field_reference_name=field_reference_name,
             field_name=field_name,
@@ -274,6 +271,17 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field
             jni_getter=jni_getter,
             object_name=object_name)
 
+
+def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_length, is_variable_len_array):
+    """
+    Generates jni code that initializes C structure that corresponds to a field of java object
+    (dto or custom type). To be used in request message handlers.
+    :param field_type: type of the field to be initialized (as defined in vpe.api)
+    :param c_name: name of the message struct member to be initialized
+    :param field_reference_name: name of the field reference in generated code
+    :param field_length: integer or name of variable that stores field length
+    """
+
     # field setter
     field_length_check = ""
 
@@ -287,7 +295,7 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field
 
     struct_setter_template = struct_setter_templates[field_type]
 
-    msg_initialization += struct_setter_template.substitute(
+    msg_initialization = struct_setter_template.substitute(
             c_name=c_name,
             field_reference_name=field_reference_name,
             field_length_check=field_length_check)
index 5b0fbc9..1425cdb 100644 (file)
@@ -113,6 +113,7 @@ request_field_identifier_template = Template("""
     ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId);
     """)
 
+jni_msg_size_template = Template(""" + ${array_length}*sizeof(${element_type})""")
 
 jni_impl_template = Template("""
 /**
@@ -127,9 +128,11 @@ JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name
     u32 my_context_id = vppjni_get_context_id (&jvpp_main);
     $request_class
 
+    $jni_identifiers
+
     // create message:
-    mp = vl_msg_api_alloc(sizeof(*mp));
-    memset (mp, 0, sizeof (*mp));
+    mp = vl_msg_api_alloc(${msg_size});
+    memset (mp, 0, ${msg_size});
     mp->_vl_msg_id = ntohs (get_message_id(env, "${c_name}_${crc}"));
     mp->client_index = plugin_main->my_client_index;
     mp->context = clib_host_to_net_u32 (my_context_id);
@@ -155,8 +158,10 @@ def generate_jni_impl(func_list, plugin_name, inputfile):
 
         arguments = ''
         request_class = ''
+        jni_identifiers = ''
         msg_initialization = ''
         f_name_uppercase = f_name.upper()
+        msg_size = 'sizeof(*mp)'
 
         if f['args']:
             arguments = ', jobject request'
@@ -166,13 +171,19 @@ def generate_jni_impl(func_list, plugin_name, inputfile):
                     java_name_upper=camel_case_function_name_upper,
                     plugin_name=plugin_name)
 
-            for t in zip(f['types'], f['args'], f['lengths']):
+            for t in zip(f['types'], f['args'], f['lengths'], f['arg_types']):
                 field_name = util.underscore_to_camelcase(t[1])
+                is_variable_len_array = t[2][1]
+                if is_variable_len_array:
+                    msg_size += jni_msg_size_template.substitute(array_length=util.underscore_to_camelcase(t[2][0]),
+                                                                 element_type=t[3])
+                jni_identifiers += jni_gen.jni_request_identifiers_for_type(field_type=t[0],
+                                                                            field_reference_name=field_name,
+                                                                            field_name=field_name)
                 msg_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=t[1],
                                                                            field_reference_name=field_name,
-                                                                           field_name=field_name,
                                                                            field_length=t[2][0],
-                                                                           is_variable_len_array=t[2][1])
+                                                                           is_variable_len_array=is_variable_len_array)
 
         jni_impl.append(jni_impl_template.substitute(
                 inputfile=inputfile,
@@ -185,6 +196,8 @@ def generate_jni_impl(func_list, plugin_name, inputfile):
                 plugin_name=plugin_name,
                 java_plugin_name=plugin_name.title(),
                 request_class=request_class,
+                jni_identifiers=jni_identifiers,
+                msg_size=msg_size,
                 msg_initialization=msg_initialization,
                 args=arguments))
 
index 7a5eec3..93883ba 100644 (file)
@@ -108,12 +108,14 @@ def generate_struct_initialization(type_def, c_name_prefix, object_name, indent)
     for t in zip(type_def['types'], type_def['args'], type_def['lengths']):
         field_reference_name = "${c_name}" + util.underscore_to_camelcase_upper(t[1])
         field_name = util.underscore_to_camelcase(t[1])
+        struct_initialization += jni_gen.jni_request_identifiers_for_type(field_type=t[0],
+                                                                          field_reference_name=field_reference_name,
+                                                                          field_name=field_name,
+                                                                          object_name=object_name)
         struct_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=c_name_prefix + t[1],
-                                                                     field_reference_name=field_reference_name,
-                                                                     field_name=field_name,
-                                                                     field_length=t[2][0],
-                                                                     is_variable_len_array=t[2][1],
-                                                                     object_name=object_name)
+                                                                      field_reference_name=field_reference_name,
+                                                                      field_length=t[2][0],
+                                                                      is_variable_len_array=t[2][1])
     return indent + struct_initialization.replace('\n', '\n' + indent)