api: improve REPLY_MACRO safety
Improve vppapigen to generate per-message #define indicating whether
said message is dynamically sized (due to VLA or string) or not. Use
these #defines in REPLY_MACROs to prevent improper usage. Fix existing
improper REPLY_MACRO* usage.
Type: improvement
Change-Id: Ia77aaf9f6cf3ed68ea21075a4cc8deda78a68651
Signed-off-by: Klement Sekera <ksekera@cisco.com>
diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py
index d0f63fb..1e18a83 100644
--- a/src/tools/vppapigen/vppapigen_c.py
+++ b/src/tools/vppapigen/vppapigen_c.py
@@ -24,6 +24,7 @@
'''
import datetime
+import itertools
import os
import time
import sys
@@ -1256,7 +1257,7 @@
filename = i.filename.replace('plugins/', '')
write('#include <{}_types.h>\n'.format(filename))
- for o in s['types'] + s['Define']:
+ for o in itertools.chain(s['types'], s['Define']):
tname = o.__class__.__name__
if tname == 'Using':
if 'length' in o.alias:
@@ -1315,6 +1316,7 @@
.format(b, o.name))
write('} vl_api_%s_t;\n' % o.name)
+ write(f'#define VL_API_{o.name.upper()}_IS_CONSTANT_SIZE ({0 if o.vla else 1})\n\n')
for t in s['Define']:
write('#define VL_API_{ID}_CRC "{n}_{crc:08x}"\n'
diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h
index 5c4dd9a..6b5b37a 100644
--- a/src/vlibapi/api_helper_macros.h
+++ b/src/vlibapi/api_helper_macros.h
@@ -33,20 +33,26 @@
endian_fp = am->msg_endian_handlers[t + (REPLY_MSG_ID_BASE)]; \
(*endian_fp) (rmp);
-#define REPLY_MACRO(t) \
-do { \
- vl_api_registration_t *rp; \
- 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 = htons((t)+(REPLY_MSG_ID_BASE)); \
- rmp->context = mp->context; \
- rmp->retval = ntohl(rv); \
- \
- vl_api_send_msg (rp, (u8 *)rmp); \
-} while(0);
+#define REPLY_MACRO(msg) \
+ do \
+ { \
+ STATIC_ASSERT ( \
+ msg##_IS_CONSTANT_SIZE, \
+ "REPLY_MACRO can only be used with constant size messages, " \
+ "use REPLY_MACRO[3|4]* instead"); \
+ vl_api_registration_t *rp; \
+ 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 = htons (msg + (REPLY_MSG_ID_BASE)); \
+ rmp->context = mp->context; \
+ rmp->retval = ntohl (rv); \
+ \
+ vl_api_send_msg (rp, (u8 *) rmp); \
+ } \
+ while (0);
#define REPLY_MACRO_END(t) \
do \
@@ -65,20 +71,30 @@
} \
while (0);
-#define REPLY_MACRO2(t, body) \
-do { \
- vl_api_registration_t *rp; \
- 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 = htons((t)+(REPLY_MSG_ID_BASE)); \
- rmp->context = mp->context; \
- rmp->retval = ntohl(rv); \
- do {body;} while (0); \
- vl_api_send_msg (rp, (u8 *)rmp); \
-} while(0);
+#define REPLY_MACRO2(t, body) \
+ do \
+ { \
+ STATIC_ASSERT ( \
+ t##_IS_CONSTANT_SIZE, \
+ "REPLY_MACRO2 can only be used with constant size messages, " \
+ "use REPLY_MACRO[3|4]* instead"); \
+ vl_api_registration_t *rp; \
+ 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 = htons ((t) + (REPLY_MSG_ID_BASE)); \
+ rmp->context = mp->context; \
+ rmp->retval = ntohl (rv); \
+ do \
+ { \
+ body; \
+ } \
+ while (0); \
+ vl_api_send_msg (rp, (u8 *) rmp); \
+ } \
+ while (0);
#define REPLY_MACRO2_END(t, body) \
do \
@@ -230,20 +246,26 @@
} \
while (0);
-#define REPLY_MACRO3(t, n, body) \
-do { \
- vl_api_registration_t *rp; \
- rp = vl_api_client_index_to_registration (mp->client_index); \
- if (rp == 0) \
- return; \
- \
- rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \
- rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
- rmp->context = mp->context; \
- rmp->retval = ntohl(rv); \
- do {body;} while (0); \
- vl_api_send_msg (rp, (u8 *)rmp); \
-} while(0);
+#define REPLY_MACRO3(t, n, body) \
+ do \
+ { \
+ vl_api_registration_t *rp; \
+ rp = vl_api_client_index_to_registration (mp->client_index); \
+ if (rp == 0) \
+ return; \
+ \
+ rmp = vl_msg_api_alloc (sizeof (*rmp) + (n)); \
+ rmp->_vl_msg_id = htons ((t) + (REPLY_MSG_ID_BASE)); \
+ rmp->context = mp->context; \
+ rmp->retval = ntohl (rv); \
+ do \
+ { \
+ body; \
+ } \
+ while (0); \
+ vl_api_send_msg (rp, (u8 *) rmp); \
+ } \
+ while (0);
#define REPLY_MACRO3_END(t, n, body) \
do \
@@ -619,62 +641,65 @@
; \
} while (0);
-#define pub_sub_handler(lca,UCA) \
-static void vl_api_want_##lca##_t_handler ( \
- vl_api_want_##lca##_t *mp) \
-{ \
- vpe_api_main_t *vam = &vpe_api_main; \
- vpe_client_registration_t *rp; \
- vl_api_want_##lca##_reply_t *rmp; \
- uword *p; \
- i32 rv = 0; \
- \
- p = hash_get (vam->lca##_registration_hash, mp->client_index); \
- if (p) { \
- if (mp->enable_disable) { \
- clib_warning ("pid %d: already enabled...", ntohl(mp->pid)); \
- rv = VNET_API_ERROR_INVALID_REGISTRATION; \
- goto reply; \
- } else { \
- rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
- pool_put (vam->lca##_registrations, rp); \
- hash_unset (vam->lca##_registration_hash, \
- mp->client_index); \
- goto reply; \
- } \
- } \
- if (mp->enable_disable == 0) { \
- clib_warning ("pid %d: already disabled...", mp->pid); \
- rv = VNET_API_ERROR_INVALID_REGISTRATION; \
- goto reply; \
- } \
- pool_get (vam->lca##_registrations, rp); \
- rp->client_index = mp->client_index; \
- rp->client_pid = mp->pid; \
- hash_set (vam->lca##_registration_hash, rp->client_index, \
- rp - vam->lca##_registrations); \
- \
-reply: \
- REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \
-} \
- \
-static clib_error_t * vl_api_want_##lca##_t_reaper (u32 client_index) \
-{ \
- vpe_api_main_t *vam = &vpe_api_main; \
- vpe_client_registration_t *rp; \
- uword *p; \
- \
- p = hash_get (vam->lca##_registration_hash, client_index); \
- if (p) \
- { \
- rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
- pool_put (vam->lca##_registrations, rp); \
- hash_unset (vam->lca##_registration_hash, client_index); \
- } \
- return (NULL); \
-} \
- \
-VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper); \
+#define pub_sub_handler(lca, UCA) \
+ static void vl_api_want_##lca##_t_handler (vl_api_want_##lca##_t *mp) \
+ { \
+ vpe_api_main_t *vam = &vpe_api_main; \
+ vpe_client_registration_t *rp; \
+ vl_api_want_##lca##_reply_t *rmp; \
+ uword *p; \
+ i32 rv = 0; \
+ \
+ p = hash_get (vam->lca##_registration_hash, mp->client_index); \
+ if (p) \
+ { \
+ if (mp->enable_disable) \
+ { \
+ clib_warning ("pid %d: already enabled...", ntohl (mp->pid)); \
+ rv = VNET_API_ERROR_INVALID_REGISTRATION; \
+ goto reply; \
+ } \
+ else \
+ { \
+ rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
+ pool_put (vam->lca##_registrations, rp); \
+ hash_unset (vam->lca##_registration_hash, mp->client_index); \
+ goto reply; \
+ } \
+ } \
+ if (mp->enable_disable == 0) \
+ { \
+ clib_warning ("pid %d: already disabled...", mp->pid); \
+ rv = VNET_API_ERROR_INVALID_REGISTRATION; \
+ goto reply; \
+ } \
+ pool_get (vam->lca##_registrations, rp); \
+ rp->client_index = mp->client_index; \
+ rp->client_pid = mp->pid; \
+ hash_set (vam->lca##_registration_hash, rp->client_index, \
+ rp - vam->lca##_registrations); \
+ \
+ reply: \
+ REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \
+ } \
+ \
+ static clib_error_t *vl_api_want_##lca##_t_reaper (u32 client_index) \
+ { \
+ vpe_api_main_t *vam = &vpe_api_main; \
+ vpe_client_registration_t *rp; \
+ uword *p; \
+ \
+ p = hash_get (vam->lca##_registration_hash, client_index); \
+ if (p) \
+ { \
+ rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
+ pool_put (vam->lca##_registrations, rp); \
+ hash_unset (vam->lca##_registration_hash, client_index); \
+ } \
+ return (NULL); \
+ } \
+ \
+ VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper);
#define foreach_registration_hash \
_(interface_events) \
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index 2121d20..767a24a 100644
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -696,25 +696,28 @@
done:
/* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_APP_ATTACH_REPLY, ({
- if (!rv)
- {
- ctrl_thread = n_workers ? 1 : 0;
- segp = (fifo_segment_t *) a->segment;
- rmp->app_index = clib_host_to_net_u32 (a->app_index);
- rmp->app_mq = fifo_segment_msg_q_offset (segp, 0);
- rmp->vpp_ctrl_mq = fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
- rmp->vpp_ctrl_mq_thread = ctrl_thread;
- rmp->n_fds = n_fds;
- rmp->fd_flags = fd_flags;
- if (vec_len (segp->ssvm.name))
- {
- vl_api_vec_to_api_string (segp->ssvm.name, &rmp->segment_name);
- }
- rmp->segment_size = segp->ssvm.ssvm_size;
- rmp->segment_handle = clib_host_to_net_u64 (a->segment_handle);
- }
- }));
+ REPLY_MACRO3 (
+ VL_API_APP_ATTACH_REPLY,
+ ((!rv) ? vec_len (((fifo_segment_t *) a->segment)->ssvm.name) : 0), ({
+ if (!rv)
+ {
+ ctrl_thread = n_workers ? 1 : 0;
+ segp = (fifo_segment_t *) a->segment;
+ rmp->app_index = clib_host_to_net_u32 (a->app_index);
+ rmp->app_mq = fifo_segment_msg_q_offset (segp, 0);
+ rmp->vpp_ctrl_mq =
+ fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
+ rmp->vpp_ctrl_mq_thread = ctrl_thread;
+ rmp->n_fds = n_fds;
+ rmp->fd_flags = fd_flags;
+ if (vec_len (segp->ssvm.name))
+ {
+ vl_api_vec_to_api_string (segp->ssvm.name, &rmp->segment_name);
+ }
+ rmp->segment_size = segp->ssvm.ssvm_size;
+ rmp->segment_handle = clib_host_to_net_u64 (a->segment_handle);
+ }
+ }));
/* *INDENT-ON* */
if (n_fds)
@@ -780,22 +783,25 @@
/* *INDENT-OFF* */
done:
- REPLY_MACRO2 (VL_API_APP_WORKER_ADD_DEL_REPLY, ({
- rmp->is_add = mp->is_add;
- rmp->wrk_index = clib_host_to_net_u32 (args.wrk_map_index);
- rmp->segment_handle = clib_host_to_net_u64 (args.segment_handle);
- if (!rv && mp->is_add)
- {
- rmp->app_event_queue_address =
- fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
- rmp->n_fds = n_fds;
- rmp->fd_flags = fd_flags;
- if (vec_len (args.segment->name))
- {
- vl_api_vec_to_api_string (args.segment->name, &rmp->segment_name);
- }
- }
- }));
+ REPLY_MACRO3 (
+ VL_API_APP_WORKER_ADD_DEL_REPLY,
+ ((!rv && mp->is_add) ? vec_len (args.segment->name) : 0), ({
+ rmp->is_add = mp->is_add;
+ rmp->wrk_index = clib_host_to_net_u32 (args.wrk_map_index);
+ rmp->segment_handle = clib_host_to_net_u64 (args.segment_handle);
+ if (!rv && mp->is_add)
+ {
+ rmp->app_event_queue_address =
+ fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
+ rmp->n_fds = n_fds;
+ rmp->fd_flags = fd_flags;
+ if (vec_len (args.segment->name))
+ {
+ vl_api_vec_to_api_string (args.segment->name,
+ &rmp->segment_name);
+ }
+ }
+ }));
/* *INDENT-ON* */
if (n_fds)