api: make vpp api handlers endian independent 19/27119/6
authorOle Troan <ot@cisco.com>
Mon, 18 May 2020 09:14:05 +0000 (11:14 +0200)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Wed, 27 May 2020 08:30:38 +0000 (08:30 +0000)
Add a new boolean to signal that the API infrastructure should performan any required
endian conversions for the API handler.

  am->is_autoendian[mm->msg_id_base + VL_API_MAP_ADD_DOMAIN] = 1;

Similarly add new REPLY_ macros that perform endian conversion.

These changes do not change the on-the-wire encoding of the API messages, and therefore the API CRC is not changed.

Type: feature
Signed-off-by: Ole Troan <ot@cisco.com>
Change-Id: I7588f8ccb38b2d1e8d85ea17be99bac43f756267
Signed-off-by: Ole Troan <ot@cisco.com>
src/plugins/map/map_api.c
src/tools/vppapigen/vppapigen_c.py
src/vlibapi/api_common.h
src/vlibapi/api_helper_macros.h
src/vlibapi/api_shared.c

index 13f0552..94d2458 100644 (file)
@@ -48,14 +48,14 @@ vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
                       mp->ip6_prefix.len,
                       (ip6_address_t *) & mp->ip6_src.address,
                       mp->ip6_src.len, mp->ea_bits_len, mp->psid_offset,
-                      mp->psid_length, &index, ntohs (mp->mtu), flags,
-                      mp->tag);
+                      mp->psid_length, &index, mp->mtu, flags, mp->tag);
 
   /* *INDENT-OFF* */
-  REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
+  REPLY_MACRO2_END(VL_API_MAP_ADD_DOMAIN_REPLY,
   ({
-    rmp->index = ntohl(index);
+    rmp->index = index;
   }));
+
   /* *INDENT-ON* */
 }
 
@@ -556,6 +556,9 @@ map_plugin_api_hookup (vlib_main_t * vm)
   map_main_t *mm = &map_main;
 
   mm->msg_id_base = setup_message_id_table ();
+
+  api_main_t *am = vlibapi_get_main ();
+  am->is_autoendian[mm->msg_id_base + VL_API_MAP_ADD_DOMAIN] = 1;
   return 0;
 }
 
index 46f60de..b7a62dc 100644 (file)
@@ -394,6 +394,7 @@ def endianfun_array(o):
                                name=o.fieldname))
     return output
 
+no_endian_conversion = {'client_index': None}
 
 def endianfun_obj(o):
     output = ''
@@ -403,6 +404,9 @@ def endianfun_obj(o):
         output += ('    s = format(s, "\\n{} {} {} (print not implemented");\n'
                    .format(o.type, o.fieldtype, o.fieldname))
         return output
+    if o.fieldname in no_endian_conversion:
+        output += '    /* a->{n} = a->{n} (no-op) */\n'.format(n=o.fieldname)
+        return output
     if o.fieldtype in endian_strings:
         output += ('    a->{name} = {format}(a->{name});\n'
                    .format(name=o.fieldname,
@@ -594,6 +598,7 @@ def generate_include_types(s, module, stream):
 
 def generate_c_boilerplate(services, defines, file_crc, module, stream):
     write = stream.write
+    define_hash = {d.name:d for d in defines}
 
     hdr = '''\
 #define vl_endianfun           /* define message structures */
@@ -612,6 +617,7 @@ def generate_c_boilerplate(services, defines, file_crc, module, stream):
     write('static u16\n')
     write('setup_message_id_table (void) {\n')
     write('   api_main_t *am = my_api_main;\n')
+    write('   vl_msg_api_msg_config_t c;\n')
     write('   u16 msg_id_base = vl_msg_api_get_msg_ids ("{}_{crc:08x}", VL_MSG_FIRST_AVAILABLE);\n'
           .format(module, crc=file_crc))
 
@@ -621,11 +627,16 @@ def generate_c_boilerplate(services, defines, file_crc, module, stream):
               '                                VL_API_{ID} + msg_id_base);\n'
               .format(n=d.name, ID=d.name.upper(), crc=d.crc))
     for s in services:
-        write('   vl_msg_api_set_handlers(VL_API_{ID} + msg_id_base, "{n}",\n'
-              '                           vl_api_{n}_t_handler, vl_noop_handler,\n'
-              '                           vl_api_{n}_t_endian, vl_api_{n}_t_print,\n'
-              '                           sizeof(vl_api_{n}_t), 1);\n'
+        d = define_hash[s.caller]
+        write('   c = (vl_msg_api_msg_config_t) {{.id = VL_API_{ID} + msg_id_base,\n'
+              '                                  .name = "{n}",\n'
+              '                                  .handler = vl_api_{n}_t_handler,\n'
+              '                                  .cleanup = vl_noop_handler,\n'
+              '                                  .endian = vl_api_{n}_t_endian,\n'
+              '                                  .print = vl_api_{n}_t_print,\n'
+              '                                  .is_autoendian = 0}};\n'
               .format(n=s.caller, ID=s.caller.upper()))
+        write('   vl_msg_api_config (&c);\n')
 
     write('   return msg_id_base;\n')
     write('}\n')
index 0ea0943..86b1c5a 100644 (file)
@@ -132,6 +132,7 @@ typedef struct
   int replay;                  /**< is this message to be replayed?  */
   int message_bounce;          /**< do not free message after processing */
   int is_mp_safe;              /**< worker thread barrier required?  */
+  int is_autoendian;           /**< endian conversion required?  */
 } vl_msg_api_msg_config_t;
 
 /** Message header structure */
@@ -248,6 +249,9 @@ typedef struct
   /** Message is mp safe vector */
   u8 *is_mp_safe;
 
+  /** Message requires us to do endian conversion */
+  u8 *is_autoendian;
+
   /** Allocator ring vectors (in shared memory) */
   struct ring_alloc_ *arings;
 
index 5750257..c7348cf 100644 (file)
@@ -59,6 +59,26 @@ do {                                                                    \
     vl_api_send_msg (rp, (u8 *)rmp);                                    \
 } while(0);
 
+#define REPLY_MACRO2_END(t, body)                                       \
+do {                                                                    \
+    vl_api_registration_t *rp;                                          \
+    rv = vl_msg_api_pd_handler (mp, rv);                                \
+    rp = vl_api_client_index_to_registration (mp->client_index);        \
+    if (rp == 0)                                                        \
+      return;                                                           \
+                                                                        \
+    rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
+    rmp->_vl_msg_id = t+(REPLY_MSG_ID_BASE);                            \
+    rmp->context = mp->context;                                         \
+    rmp->retval = rv;                                                   \
+    do {body;} while (0);                                               \
+    api_main_t *am = vlibapi_get_main ();                              \
+    void (*endian_fp) (void *);                                                \
+    endian_fp = am->msg_endian_handlers[t];                            \
+    (*endian_fp) (rmp);                                                        \
+    vl_api_send_msg (rp, (u8 *)rmp);                                    \
+} while(0);
+
 #define REPLY_MACRO2_ZERO(t, body)                                      \
 do {                                                                    \
     vl_api_registration_t *rp;                                          \
index fbaa9c9..c818668 100644 (file)
@@ -485,6 +485,14 @@ msg_handler_internal (api_main_t * am,
              vl_msg_api_barrier_trace_context (am->msg_names[id]);
              vl_msg_api_barrier_sync ();
            }
+
+         if (am->is_autoendian[id])
+           {
+             void (*endian_fp) (void *);
+             endian_fp = am->msg_endian_handlers[id];
+             (*endian_fp) (the_msg);
+           }
+
          (*am->msg_handlers[id]) (the_msg);
          if (!am->is_mp_safe[id])
            vl_msg_api_barrier_release ();
@@ -606,6 +614,13 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp,
       if (PREDICT_FALSE (vl_msg_api_fuzz_hook != 0))
        (*vl_msg_api_fuzz_hook) (id, the_msg);
 
+      if (am->is_autoendian[id])
+       {
+         void (*endian_fp) (void *);
+         endian_fp = am->msg_endian_handlers[id];
+         (*endian_fp) (the_msg);
+       }
+
       (*handler) (the_msg, vm, node);
       if (is_private)
        {
@@ -772,7 +787,8 @@ _(msg_endian_handlers)                          \
 _(msg_print_handlers)                           \
 _(api_trace_cfg)                               \
 _(message_bounce)                              \
-_(is_mp_safe)
+_(is_mp_safe)                                  \
+_(is_autoendian)
 
 void
 vl_msg_api_config (vl_msg_api_msg_config_t * c)
@@ -813,6 +829,7 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
   am->msg_print_handlers[c->id] = c->print;
   am->message_bounce[c->id] = c->message_bounce;
   am->is_mp_safe[c->id] = c->is_mp_safe;
+  am->is_autoendian[c->id] = c->is_autoendian;
 
   am->api_trace_cfg[c->id].size = c->size;
   am->api_trace_cfg[c->id].trace_enable = c->traced;
@@ -842,6 +859,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
   c->replay = 1;
   c->message_bounce = 0;
   c->is_mp_safe = 0;
+  c->is_autoendian = 0;
   vl_msg_api_config (c);
 }