u16 last_msg_id;
} vl_api_msg_range_t;
+typedef clib_error_t *(vl_msg_api_init_function_t) (u32 client_index);
+
+typedef struct _vl_msg_api_init_function_list_elt
+{
+ struct _vl_msg_api_init_function_list_elt *next_init_function;
+ vl_msg_api_init_function_t *f;
+} _vl_msg_api_function_list_elt_t;
+
typedef struct
{
void (**msg_handlers) (void *);
/* Replay in progress? */
int replay_in_progress;
+
+ /* List of API client reaper functions */
+ _vl_msg_api_function_list_elt_t *reaper_function_registrations;
+
} api_main_t;
extern api_main_t api_main;
})
+#define _VL_MSG_API_FUNCTION_SYMBOL(x, type) \
+ _vl_msg_api_##type##_function_##x
+
+#define VL_MSG_API_FUNCTION_SYMBOL(x) \
+ _VL_MSG_API_FUNCTION_SYMBOL(x, reaper)
+
+#define VLIB_DECLARE_REAPER_FUNCTION(x, tag) \
+vl_msg_api_init_function_t * _VL_MSG_API_FUNCTION_SYMBOL (x, tag) = x; \
+static void __vl_msg_api_add_##tag##_function_##x (void) \
+ __attribute__((__constructor__)) ; \
+ \
+static void __vl_msg_api_add_##tag##_function_##x (void) \
+{ \
+ api_main_t * am = &api_main; \
+ static _vl_msg_api_function_list_elt_t _vl_msg_api_function; \
+ _vl_msg_api_function.next_init_function \
+ = am->tag##_function_registrations; \
+ am->tag##_function_registrations = &_vl_msg_api_function; \
+ _vl_msg_api_function.f = &x; \
+}
+
+#define VL_MSG_API_REAPER_FUNCTION(x) VLIB_DECLARE_REAPER_FUNCTION(x,reaper)
+
+/* Call reaper function with client index */
+#define vl_msg_api_call_reaper_function(ci) \
+ ({ \
+ extern vlib_init_function_t * VLIB_INIT_FUNCTION_SYMBOL (reaper); \
+ vlib_init_function_t * _f = VLIB_INIT_FUNCTION_SYMBOL (reaper); \
+ clib_error_t * _error = 0; \
+ _error = _f (ci); \
+ })
+
#endif /* included_api_h */
/*
vl_msg_api_send_shmem (q, (u8 *) & rp);
}
-/* Application callback to clean up leftover registrations from this client */
-int vl_api_memclnt_delete_callback (u32 client_index) __attribute__ ((weak));
-
-int
-vl_api_memclnt_delete_callback (u32 client_index)
+static int
+call_reaper_functions (u32 client_index)
{
+ clib_error_t *error = 0;
+ _vl_msg_api_function_list_elt_t *i;
+
+ i = api_main.reaper_function_registrations;
+ while (i)
+ {
+ error = i->f (client_index);
+ if (error)
+ clib_error_report (error);
+ i = i->next_init_function;
+ }
return 0;
}
handle = mp->index;
- if (vl_api_memclnt_delete_callback (handle))
+ if (call_reaper_functions (handle))
return;
epoch = vl_msg_api_handle_get_epoch (handle);
handle = vl_msg_api_handle_from_index_and_epoch
(dead_indices[i], shm->application_restarts);
- (void) vl_api_memclnt_delete_callback (handle);
+ (void) call_reaper_functions (handle);
}
}
static int nd_change_delete_callback (u32 pool_index, u8 * notused);
/* Clean up all registrations belonging to the indicated client */
-int
-vl_api_memclnt_delete_callback (u32 client_index)
+static clib_error_t *
+memclnt_delete_callback (u32 client_index)
{
vpe_api_main_t *vam = &vpe_api_main;
vpe_client_registration_t *rp;
return 0;
}
+VL_MSG_API_REAPER_FUNCTION (memclnt_delete_callback);
+
pub_sub_handler (oam_events, OAM_EVENTS);
#define RESOLUTION_EVENT 1