summaryrefslogtreecommitdiffstats
path: root/java/jvpp-stats/jvpp_interface_stats.h
diff options
context:
space:
mode:
authorMichal Cmarada <mcmarada@cisco.com>2019-05-03 11:29:04 +0200
committerMichal Cmarada <mcmarada@cisco.com>2019-05-03 11:29:04 +0200
commit9c6ac1db63e54e753ebdc2aa3fc73c68ef2a2247 (patch)
tree84247ce2d242d50ee59de7581f13bf1f10b2c732 /java/jvpp-stats/jvpp_interface_stats.h
parentfd32c70dc39fb304d1be7ea155410386414d677d (diff)
Implement callbacks and registry for stats
Change-Id: I9e562482195fcd5f54634cfff29df4358b78ed28 Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
Diffstat (limited to 'java/jvpp-stats/jvpp_interface_stats.h')
-rw-r--r--java/jvpp-stats/jvpp_interface_stats.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/java/jvpp-stats/jvpp_interface_stats.h b/java/jvpp-stats/jvpp_interface_stats.h
new file mode 100644
index 0000000..01b8cdb
--- /dev/null
+++ b/java/jvpp-stats/jvpp_interface_stats.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This file contains JNI bindings for jvpp Java API.
+ */
+#include <jvpp-common/jvpp_common.h>
+#include <vpp-api/client/stat_client.h>
+
+// JAVA class reference cache
+jclass interfaceStatisticsDumpClass;
+jclass interfaceStatisticsClass;
+jclass interfaceStatisticsDetailsClass;
+jclass callbackExceptionClass;
+
+typedef struct interface_statistics {
+ int context;
+ int sw_if_index;
+ int rx_errors;
+ int rx_bytes;
+ int rx_unicast_pkts;
+ int rx_broadcast_pkts;
+ int rx_multicast_pkts;
+ int tx_errors;
+ int tx_bytes;
+ int tx_unicast_pkts;
+ int tx_broadcast_pkts;
+ int tx_multicast_pkts;
+
+} vl_api_interface_statistics_details_t;
+
+static int cache_class_references(JNIEnv *env) {
+
+ interfaceStatisticsDumpClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env,
+ "io/fd/jvpp/stats/dto/InterfaceStatisticsDump"));
+ if ((*env)->ExceptionCheck(env)) {
+ (*env)->ExceptionDescribe(env);
+ return JNI_ERR;
+ }
+ interfaceStatisticsDetailsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env,
+ "io/fd/jvpp/stats/dto/InterfaceStatisticsDetails"));
+ if ((*env)->ExceptionCheck(env)) {
+ (*env)->ExceptionDescribe(env);
+ return JNI_ERR;
+ }
+ interfaceStatisticsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env,
+ "io/fd/jvpp/stats/dto/InterfaceStatistics"));
+ if ((*env)->ExceptionCheck(env)) {
+ (*env)->ExceptionDescribe(env);
+ return JNI_ERR;
+ }
+ callbackExceptionClass = (jclass) (*env)->NewGlobalRef(env,
+ (*env)->FindClass(env, "io/fd/jvpp/VppCallbackException"));
+ if ((*env)->ExceptionCheck(env)) {
+ (*env)->ExceptionDescribe(env);
+ return JNI_ERR;
+ }
+ return 0;
+}
+
+static void delete_class_references(JNIEnv *env) {
+
+ if (interfaceStatisticsDumpClass) {
+ (*env)->DeleteGlobalRef(env, interfaceStatisticsDumpClass);
+ }
+ if (interfaceStatisticsDetailsClass) {
+ (*env)->DeleteGlobalRef(env, interfaceStatisticsDetailsClass);
+ }
+ if (interfaceStatisticsClass) {
+ (*env)->DeleteGlobalRef(env, interfaceStatisticsClass);
+ }
+ if (callbackExceptionClass) {
+ (*env)->DeleteGlobalRef(env, callbackExceptionClass);
+ }
+}
+
+/**
+ * Handler for interface_statistics_details message.
+ */
+static void
+interface_statistics_details_handler(JNIEnv *env, vl_api_interface_statistics_details_t *ifc_stats, int ifc_count) {
+ stats_main_t *plugin_main = &stats_main;
+ jthrowable exc;
+ if (CLIB_DEBUG > 1)
+ clib_warning ("Received interface_statistics_details event message");
+
+ jmethodID constructor = (*env)->GetMethodID(env, interfaceStatisticsDetailsClass, "<init>", "(II)V");
+
+ // User does not have to provide callbacks for all VPP messages.
+ // We are ignoring messages that are not supported by user.
+ (*env)->ExceptionClear(env); // just in case exception occurred in different place and was not properly cleared
+ jmethodID callbackMethod = (*env)->GetMethodID(env, plugin_main->callbackClass, "onInterfaceStatisticsDetails",
+ "(Lio/fd/jvpp/stats/dto/InterfaceStatisticsDetails;)V");
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ clib_warning(
+ "Unable to extract onInterfaceStatisticsDetails method reference from stats plugin's callbackClass. Ignoring message.\n");
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ return;
+ }
+ jobject dto = (*env)->NewObject(env, interfaceStatisticsDetailsClass, constructor, ifc_count, ifc_stats->context);
+ jfieldID interfaceStatisticsId = (*env)->GetFieldID(env, interfaceStatisticsDetailsClass, "interfaceStatistics",
+ "[Lio/fd/jvpp/stats/dto/InterfaceStatistics;");
+ jobject stats_array = (*env)->GetObjectField(env, dto, interfaceStatisticsId);
+
+ jmethodID ifc_stats_constructor = (*env)->GetMethodID(env, interfaceStatisticsClass, "<init>", "(IIIIIIIIIII)V");
+ for (int i = 0; i < ifc_count; i++) {
+
+ jobject element = (*env)->NewObject(env, interfaceStatisticsClass, ifc_stats_constructor,
+ ifc_stats[i].sw_if_index,
+ ifc_stats[i].tx_errors,
+ ifc_stats[i].tx_multicast_pkts,
+ ifc_stats[i].tx_unicast_pkts,
+ ifc_stats[i].tx_broadcast_pkts,
+ ifc_stats[i].tx_bytes,
+ ifc_stats[i].rx_errors,
+ ifc_stats[i].rx_multicast_pkts,
+ ifc_stats[i].rx_unicast_pkts,
+ ifc_stats[i].rx_broadcast_pkts,
+ ifc_stats[i].rx_bytes);
+
+ (*env)->SetObjectArrayElement(env, stats_array, i, element);
+ if ((*env)->ExceptionOccurred(env)) {
+ break;
+ }
+ (*env)->DeleteLocalRef(env, element);
+ }
+ (*env)->CallVoidMethod(env, plugin_main->callbackObject, callbackMethod, dto);
+ if ((*env)->ExceptionOccurred(env)) {
+ clib_warning("Unable to call callback for stats plugin's callbackClass.\n");
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ return;
+ }
+ (*env)->DeleteLocalRef(env, stats_array);
+ (*env)->DeleteLocalRef(env, dto);
+}
+
+static void
+set_field(vl_api_interface_statistics_details_t *stats, int index, const char *field_name, int packets, int bytes) {
+ if (strcmp(field_name, "/if/rx-error") == 0) {
+ stats[index].rx_errors = packets;
+ } else if (strcmp(field_name, "/if/tx-error") == 0) {
+ stats[index].tx_errors = packets;
+ } else if (strcmp(field_name, "/if/tx") == 0) {
+ stats[index].tx_bytes = bytes;
+ } else if (strcmp(field_name, "/if/tx-multicast") == 0) {
+ stats[index].tx_multicast_pkts = packets;
+ } else if (strcmp(field_name, "/if/tx-unicast") == 0) {
+ stats[index].tx_unicast_pkts = packets;
+ } else if (strcmp(field_name, "/if/tx-broadcast") == 0) {
+ stats[index].tx_broadcast_pkts = packets;
+ } else if (strcmp(field_name, "/if/rx") == 0) {
+ stats[index].rx_bytes = bytes;
+ } else if (strcmp(field_name, "/if/rx-multicast") == 0) {
+ stats[index].rx_multicast_pkts = packets;
+ } else if (strcmp(field_name, "/if/rx-unicast") == 0) {
+ stats[index].rx_unicast_pkts = packets;
+ } else if (strcmp(field_name, "/if/rx-broadcast") == 0) {
+ stats[index].rx_broadcast_pkts = packets;
+ }
+ stats[index].sw_if_index = index;
+}
+
+static stat_segment_data_t *get_ifc_statistics_dump() {
+ u8 **patterns = 0;
+ u32 *dir;
+ vec_add1(patterns, (u8 *) "/if/rx");
+ vec_add1(patterns, (u8 *) "/if/tx");
+ dir = stat_segment_ls(patterns);
+ return stat_segment_dump(dir);
+}
+
+static jint getInterfaceStatisticsDump(JNIEnv *env) {
+ stat_segment_data_t *res;
+ int i, j, k, interface_count = 0;
+ u32 my_context_id = vppjni_get_context_id(&jvpp_main);
+ res = get_ifc_statistics_dump();
+ if (res == NULL) {
+ clib_warning("Interface Statistics dump failed.\n");
+ return -1;
+ }
+
+ if (vec_len (res) > 0) {
+ if ((res[0].simple_counter_vec != 0) && (vec_len (res[0].simple_counter_vec) > 0)) {
+ interface_count = vec_len (res[0].simple_counter_vec[0]);
+ } else if ((res[0].combined_counter_vec != 0) && (vec_len (res[0].combined_counter_vec) > 0)) {
+ interface_count = vec_len (res[0].combined_counter_vec[0]);
+ }
+ }
+ vl_api_interface_statistics_details_t ifc_stats[interface_count];
+ memset(ifc_stats, 0, interface_count * sizeof(vl_api_interface_statistics_details_t));
+ ifc_stats->context = my_context_id;
+
+ for (i = 0; i < vec_len (res); i++) {
+ switch (res[i].type) {
+ case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
+ if (res[i].simple_counter_vec == 0)
+ continue;
+ for (k = 0; k < vec_len (res[i].simple_counter_vec); k++)
+ for (j = 0; j < vec_len (res[i].simple_counter_vec[k]); j++) {
+ set_field(ifc_stats, j, res[i].name, res[i].simple_counter_vec[k][j], 0);
+ }
+ break;
+
+ case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
+ if (res[i].combined_counter_vec == 0)
+ continue;
+ for (k = 0; k < vec_len (res[i].combined_counter_vec); k++)
+ for (j = 0; j < vec_len (res[i].combined_counter_vec[k]); j++) {
+ set_field(ifc_stats, j, res[i].name, res[i].combined_counter_vec[k][j].packets,
+ res[i].combined_counter_vec[k][j].bytes);
+ }
+ break;
+
+ default:;
+ }
+ }
+ stat_segment_data_free(res);
+ interface_statistics_details_handler(env, ifc_stats, interface_count);
+ return ifc_stats->context;
+} \ No newline at end of file