From 4746a5d75ebb080d15d5d743dca3a85d0265176f Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 27 Jan 2017 08:57:40 +0100 Subject: jvpp: utilize per-message CRCs (VPP-544) Since messages ids are no longer statically referenced, fixes also VPP-611. Change-Id: Ic8e6ee2b7f1142c185595347984d69350be25ac3 Signed-off-by: Marek Gradzki --- src/vpp-api/java/jvpp-acl/jvpp_acl.c | 8 +++- src/vpp-api/java/jvpp-common/jvpp_common.c | 16 +++++++ src/vpp-api/java/jvpp-common/jvpp_common.h | 7 +++ src/vpp-api/java/jvpp-core/jvpp_core.c | 8 +++- .../java/jvpp-ioamexport/jvpp_ioam_export.c | 8 +++- src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c | 8 +++- src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c | 8 +++- src/vpp-api/java/jvpp-registry/jvpp_registry.c | 54 ++++++++++++++++++++-- src/vpp-api/java/jvpp-snat/jvpp_snat.c | 8 +++- src/vpp-api/java/jvpp/gen/jvpp_gen.py | 2 +- src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py | 31 +++++++++++-- 11 files changed, 143 insertions(+), 15 deletions(-) diff --git a/src/vpp-api/java/jvpp-acl/jvpp_acl.c b/src/vpp-api/java/jvpp-acl/jvpp_acl.c index d56abe3d..9150ce6b 100644 --- a/src/vpp-api/java/jvpp-acl/jvpp_acl.c +++ b/src/vpp-api/java/jvpp-acl/jvpp_acl.c @@ -74,8 +74,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_acl_JVppAclImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); \ + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N + plugin_main->msg_id_base, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ diff --git a/src/vpp-api/java/jvpp-common/jvpp_common.c b/src/vpp-api/java/jvpp-common/jvpp_common.c index a161c09c..b88c0ea2 100644 --- a/src/vpp-api/java/jvpp-common/jvpp_common.c +++ b/src/vpp-api/java/jvpp-common/jvpp_common.c @@ -63,3 +63,19 @@ void call_on_error(const char* callName, int contextId, int retval, (*env)->CallVoidMethod(env, callbackObject, callbackExcMethod, excObject); DEBUG_LOG("CallOnError : Response sent\n"); } + +u32 get_message_id(JNIEnv *env, const char *key) { + uword *p = hash_get(jvpp_main.messages_hash, key); + if (!p) { + jclass exClass = (*env)->FindClass(env, "java/lang/IllegalStateException"); + char *msgBuf = clib_mem_alloc(strlen(key) + 40); + strcpy(msgBuf, "API mismatch detected: "); + strcat(msgBuf, key); + strcat(msgBuf, " is missing"); + DEBUG_LOG("get_message_id : %s\n", msgBuf); + (*env)->ThrowNew(env, exClass, msgBuf); + clib_mem_free(msgBuf); + return 0; + } + return (u32) p[0]; +} diff --git a/src/vpp-api/java/jvpp-common/jvpp_common.h b/src/vpp-api/java/jvpp-common/jvpp_common.h index bbb203ed..34502d04 100644 --- a/src/vpp-api/java/jvpp-common/jvpp_common.h +++ b/src/vpp-api/java/jvpp-common/jvpp_common.h @@ -37,6 +37,7 @@ typedef struct { /* Convenience */ unix_shared_memory_queue_t * vl_input_queue; u32 my_client_index; + uword *messages_hash; } jvpp_main_t; extern jvpp_main_t jvpp_main __attribute__((aligned (64))); @@ -64,4 +65,10 @@ void call_on_error(const char* callName, int contextId, int retval, jclass callbackClass, jobject callbackObject, jclass callbackExceptionClass); +/** + * Retrieves message id based on message name and crc (key format: name_crc). + * Throws java/lang/IllegalStateException on failure. + */ +u32 get_message_id(JNIEnv *env, const char* key); + #endif /* __included_jvpp_common_h__ */ diff --git a/src/vpp-api/java/jvpp-core/jvpp_core.c b/src/vpp-api/java/jvpp-core/jvpp_core.c index ef4cb8e3..c04666b2 100644 --- a/src/vpp-api/java/jvpp-core/jvpp_core.c +++ b/src/vpp-api/java/jvpp-core/jvpp_core.c @@ -67,8 +67,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_core_JVppCoreImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); \ + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_noop_handler, \ diff --git a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c index 5cda89d1..068d2ec3 100644 --- a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c +++ b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c @@ -74,8 +74,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioamexport_JVppIoamexportImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); \ + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N + plugin_main->msg_id_base, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ diff --git a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c index 9291dbba..51b6a075 100644 --- a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c +++ b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c @@ -74,8 +74,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioampot_JVppIoampotImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); \ + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N + plugin_main->msg_id_base, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ diff --git a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c index 0bf17889..2f74b5ad 100644 --- a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c +++ b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c @@ -74,8 +74,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioamtrace_JVppIoamtraceImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); \ + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N + plugin_main->msg_id_base, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ diff --git a/src/vpp-api/java/jvpp-registry/jvpp_registry.c b/src/vpp-api/java/jvpp-registry/jvpp_registry.c index cbd5e0ab..add872db 100644 --- a/src/vpp-api/java/jvpp-registry/jvpp_registry.c +++ b/src/vpp-api/java/jvpp-registry/jvpp_registry.c @@ -52,16 +52,21 @@ void __stack_chk_guard(void) __attribute__((weak)); void __stack_chk_guard(void) { } +#define CONTROL_PING_MESSAGE "control_ping" +#define CONTROL_PING_REPLY_MESSAGE "control_ping_reply" + typedef struct { /* UThread attachment */ volatile u32 control_ping_result_ready; volatile i32 control_ping_retval; - /* Control poing callback */ + /* Control ping callback */ jobject registryObject; jclass registryClass; jclass controlPingReplyClass; jclass callbackExceptionClass; + int control_ping_msg_id; + int control_ping_reply_msg_id; /* Thread cleanup */ pthread_key_t cleanup_rx_thread_key; @@ -168,6 +173,41 @@ static void vl_api_control_ping_reply_t_handler( out: rm->control_ping_result_ready = 1; } +static int find_ping_id() { + int rv = 0; + jvpp_main_t * jm = &jvpp_main; + jvpp_registry_main_t * rm = &jvpp_registry_main; + api_main_t *am = &api_main; + hash_pair_t *hp; + jm->messages_hash = am->msg_index_by_name_and_crc; + + rm->control_ping_msg_id = -1; + rm->control_ping_reply_msg_id = -1; + + hash_foreach_pair (hp, jm->messages_hash, + ({ + char *key = (char *)hp->key; // key format: name_crc + int msg_name_len = strlen(key) - 9; // ignore crc + if (strlen(CONTROL_PING_MESSAGE) == msg_name_len && + strncmp(CONTROL_PING_MESSAGE, (char *)hp->key, msg_name_len) == 0) { + rm->control_ping_msg_id = (u32)hp->value[0]; + } + if (strlen(CONTROL_PING_REPLY_MESSAGE) == msg_name_len && + strncmp(CONTROL_PING_REPLY_MESSAGE, (char *)hp->key, msg_name_len) == 0) { + rm->control_ping_reply_msg_id = (u32)hp->value[0]; + } + })); + if (rm->control_ping_msg_id == -1) { + clib_warning("failed to find id for %s", CONTROL_PING_MESSAGE); + rv = -1; + } + if (rm->control_ping_reply_msg_id == -1) { + clib_warning("failed to find id for %s", CONTROL_PING_REPLY_MESSAGE); + rv = -1; + } + return rv; +} + static int send_initial_control_ping() { f64 timeout; clib_time_t clib_time; @@ -180,7 +220,7 @@ static int send_initial_control_ping() { rm->control_ping_result_ready = 0; mp = vl_msg_api_alloc(sizeof(*mp)); memset(mp, 0, sizeof(*mp)); - mp->_vl_msg_id = ntohs(VL_API_CONTROL_PING); + mp->_vl_msg_id = ntohs(rm->control_ping_msg_id); mp->client_index = jm->my_client_index; // send message: @@ -197,7 +237,7 @@ static int send_initial_control_ping() { } if (rv != 0) { - clib_warning("common: first control ping failed: %d", rv); + clib_warning("first control ping failed: %d", rv); } return rv; @@ -206,6 +246,7 @@ static int send_initial_control_ping() { static int connect_to_vpe(char *name) { jvpp_main_t * jm = &jvpp_main; api_main_t * am = &api_main; + jvpp_registry_main_t * rm = &jvpp_registry_main; if (vl_client_connect_to_vlib("/vpe-api", name, 32) < 0) return -1; @@ -214,7 +255,10 @@ static int connect_to_vpe(char *name) { jm->vl_input_queue = am->shmem_hdr->vl_input_queue; - vl_msg_api_set_handlers(VL_API_CONTROL_PING_REPLY, "control_ping_reply", + if (find_ping_id() < 0) + return -1; + + vl_msg_api_set_handlers(rm->control_ping_reply_msg_id, CONTROL_PING_REPLY_MESSAGE, vl_api_control_ping_reply_t_handler, vl_noop_handler, vl_api_control_ping_reply_t_endian, vl_api_control_ping_reply_t_print, @@ -286,7 +330,7 @@ JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_JVppRegistryImpl_controlPing0( mp = vl_msg_api_alloc(sizeof(*mp)); memset(mp, 0, sizeof(*mp)); - mp->_vl_msg_id = ntohs(VL_API_CONTROL_PING); + mp->_vl_msg_id = ntohs(rm->control_ping_msg_id); mp->client_index = jm->my_client_index; mp->context = clib_host_to_net_u32(my_context_id); diff --git a/src/vpp-api/java/jvpp-snat/jvpp_snat.c b/src/vpp-api/java/jvpp-snat/jvpp_snat.c index 1095b6eb..c4d1afe8 100644 --- a/src/vpp-api/java/jvpp-snat/jvpp_snat.c +++ b/src/vpp-api/java/jvpp-snat/jvpp_snat.c @@ -74,8 +74,14 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_snat_JVppSnatImpl_init0 plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); + // verify API has not changed since jar generation + #define _(N) \ + get_message_id(env, #N); + foreach_supported_api_message; + #undef _ + #define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N + plugin_main->msg_id_base, #n, \ + vl_msg_api_set_handlers(get_message_id(env, #N), #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ diff --git a/src/vpp-api/java/jvpp/gen/jvpp_gen.py b/src/vpp-api/java/jvpp/gen/jvpp_gen.py index f51b11d0..2a5ada98 100755 --- a/src/vpp-api/java/jvpp/gen/jvpp_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvpp_gen.py @@ -6,7 +6,7 @@ # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 -# l +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py index 611171c4..5b0fbc95 100644 --- a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py @@ -130,7 +130,7 @@ JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name // create message: mp = vl_msg_api_alloc(sizeof(*mp)); memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_${c_name_uppercase} + plugin_main->msg_id_base); + 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); @@ -181,6 +181,7 @@ def generate_jni_impl(func_list, plugin_name, inputfile): field_name=camel_case_function_name, c_name_uppercase=f_name_uppercase, c_name=f_name, + crc=f['crc'], plugin_name=plugin_name, java_plugin_name=plugin_name.title(), request_class=request_class, @@ -282,7 +283,7 @@ def generate_msg_handlers(func_list, plugin_name, inputfile): return "\n".join(handlers) -handler_registration_template = Template("""_(${upercase_name}, ${name}) \\ +handler_registration_template = Template("""_(${name}_${crc}, ${name}) \\ """) @@ -298,11 +299,30 @@ def generate_handler_registration(func_list): handler_registration.append(handler_registration_template.substitute( name=name, - upercase_name=name.upper())) + crc=f['crc'])) return "".join(handler_registration) +api_verification_template = Template("""_(${name}_${crc}) \\ +""") + + +def generate_api_verification(func_list): + api_verification = ["#define foreach_supported_api_message \\\n"] + for f in func_list: + name = f['name'] + + if util.is_ignored(name): + continue + + api_verification.append(api_verification_template.substitute( + name=name, + crc=f['crc'])) + + return "".join(api_verification) + + jvpp_c_template = Template("""/** * This file contains JNI bindings for jvpp Java API. * It was generated by jvpp_c_gen.py based on $inputfile @@ -312,6 +332,9 @@ jvpp_c_template = Template("""/** // JAVA class reference cache $class_cache +// List of supported API messages used for verification +$api_verification + // JNI bindings $jni_implementations @@ -330,11 +353,13 @@ def generate_jvpp(func_list, plugin_name, inputfile, path): jni_impl = generate_jni_impl(func_list, plugin_name, inputfile) msg_handlers = generate_msg_handlers(func_list, plugin_name, inputfile) handler_registration = generate_handler_registration(func_list) + api_verification = generate_api_verification(func_list) jvpp_c_file = open("%s/jvpp_%s_gen.h" % (path, plugin_name), 'w') jvpp_c_file.write(jvpp_c_template.substitute( inputfile=inputfile, class_cache=class_cache, + api_verification=api_verification, jni_implementations=jni_impl, msg_handlers=msg_handlers, handler_registration=handler_registration)) -- cgit 1.2.3-korg