diff options
16 files changed, 556 insertions, 3 deletions
diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java index c4f22dc..39ae750 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/JVppStats.java @@ -28,4 +28,6 @@ public interface JVppStats extends io.fd.jvpp.JVpp { int send(io.fd.jvpp.dto.JVppRequest request) throws io.fd.jvpp.VppInvocationException; int interfaceStatisticsDump() throws io.fd.jvpp.VppInvocationException; + + int interfaceNamesDump() throws io.fd.jvpp.VppInvocationException; } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java index fdee289..2b30182 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/JVppStatsImpl.java @@ -82,6 +82,8 @@ public class JVppStatsImpl implements io.fd.jvpp.stats.JVppStats { private static native int interfaceStatisticsDump0() throws io.fd.jvpp.VppInvocationException; + private static native int interfaceNamesDump0() throws io.fd.jvpp.VppInvocationException; + private static native void close0(); @Override @@ -115,6 +117,17 @@ public class JVppStatsImpl implements io.fd.jvpp.stats.JVppStats { } @Override + public int interfaceNamesDump() throws VppInvocationException { + connection.checkActive(); + LOG.fine("Sending interfaceNamesDump event message"); + int result = interfaceNamesDump0(); + if (result < 0) { + throw new io.fd.jvpp.VppInvocationException("interfaceNamesDump", result); + } + return result; + } + + @Override public void close() { close0(); } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceNamesDetailsCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceNamesDetailsCallback.java new file mode 100644 index 0000000..56fd0f5 --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/callback/InterfaceNamesDetailsCallback.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.callback; + +/** + * <p>Represents callback for plugin's api message. + */ +public interface InterfaceNamesDetailsCallback extends io.fd.jvpp.callback.JVppCallback { + + void onInterfaceNamesDetails(io.fd.jvpp.stats.dto.InterfaceNamesDetails reply); +} diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java index 794a645..9562dab 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/callback/JVppStatsGlobalCallback.java @@ -19,5 +19,6 @@ package io.fd.jvpp.stats.callback; /** * Global aggregated callback interface. */ -public interface JVppStatsGlobalCallback extends io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback { +public interface JVppStatsGlobalCallback extends io.fd.jvpp.stats.callback.InterfaceStatisticsDetailsCallback, + io.fd.jvpp.stats.callback.InterfaceNamesDetailsCallback { } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java index ec1feb2..b1f8d54 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/callfacade/CallbackJVppStatsFacadeCallback.java @@ -64,4 +64,21 @@ public final class CallbackJVppStatsFacadeCallback implements io.fd.jvpp.stats.c callback.onInterfaceStatisticsDetails(reply); } } + + @Override + public void onInterfaceNamesDetails(final io.fd.jvpp.stats.dto.InterfaceNamesDetails reply) { + + io.fd.jvpp.stats.callback.InterfaceNamesDetailsCallback callback; + final int replyId = reply.context; + if (LOG.isLoggable(java.util.logging.Level.FINE)) { + LOG.fine(String.format("Received InterfaceNamesDetails event message: %s", reply)); + } + synchronized (requests) { + callback = (io.fd.jvpp.stats.callback.InterfaceNamesDetailsCallback) requests.remove(replyId); + } + + if (callback != null) { + callback.onInterfaceNamesDetails(reply); + } + } } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceName.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceName.java new file mode 100644 index 0000000..a50471b --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceName.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.dto; + +import java.util.Objects; + +public class InterfaceName { + + public int swIfIndex; + public String name; + + public InterfaceName(final int swIfIndex, final String name) { + this.swIfIndex = swIfIndex; + this.name = name; + } + + @Override + public boolean equals(final Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + final InterfaceName otherIfc = (InterfaceName) other; + return swIfIndex == otherIfc.swIfIndex && name.equals(otherIfc.name); + } + + @Override + public int hashCode() { + return Objects.hash(swIfIndex, name); + } + + @Override + public String toString() { + return "InterfaceName{" + + "swIfIndex=" + swIfIndex + + ", name=" + name + + '}'; + } +} diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetails.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetails.java new file mode 100644 index 0000000..c437faf --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetails.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.dto; + +/** + * <p>This class represents reply DTO for InterfaceNamesDetails. + */ +public final class InterfaceNamesDetails implements io.fd.jvpp.dto.JVppReply<InterfaceNamesDump> { + public int context; + public InterfaceName[] interfaceNames; + public int length; + + public InterfaceNamesDetails(int length, int context) { + this.context = context; + this.length = length; + this.interfaceNames = new InterfaceName[length]; + } + + @Override + @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") + public int hashCode() { + return java.util.Objects.hash(context, interfaceNames, length); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final InterfaceNamesDetails other = (InterfaceNamesDetails) o; + + if (!java.util.Objects.equals(this.context, other.context)) { + return false; + } + if (!java.util.Arrays.equals(this.interfaceNames, other.interfaceNames)) { + return false; + } + if (!java.util.Objects.equals(this.length, other.length)) { + return false; + } else { + return true; + } + } + + @Override + public String toString() { + return "InterfaceNamesDetails{" + + "context=" + context + + ", interfaceNames=" + java.util.Arrays.toString(interfaceNames) + + ", length=" + length + + '}'; + } +} diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetailsReplyDump.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetailsReplyDump.java new file mode 100644 index 0000000..c1e1b1b --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDetailsReplyDump.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.dto; + +/** + * <p>This class represents dump reply wrapper for InterfaceNamesDetails. + */ +public final class InterfaceNamesDetailsReplyDump + implements io.fd.jvpp.dto.JVppReplyDump<InterfaceNamesDump, InterfaceNamesDetails> { + + public InterfaceNamesDetails interfaceNamesDetails; + + @Override + @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") + public int hashCode() { + return java.util.Objects.hash(interfaceNamesDetails); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final InterfaceNamesDetailsReplyDump + other = (InterfaceNamesDetailsReplyDump) o; + + return java.util.Objects.equals(this.interfaceNamesDetails, other.interfaceNamesDetails); + } + + @Override + public String toString() { + return "InterfaceNamesDetailsReplyDump{" + + "interfaceNamesDetails=" + interfaceNamesDetails + + '}'; + } +} diff --git a/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDump.java b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDump.java new file mode 100644 index 0000000..79125aa --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/dto/InterfaceNamesDump.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.dto; + +/** + * <p>This class represents request DTO. + */ +public final class InterfaceNamesDump implements io.fd.jvpp.dto.JVppDump { + + @Override + @io.fd.jvpp.coverity.SuppressFBWarnings("UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD") + public int hashCode() { + return java.util.Objects.hash(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + return true; + } + + @Override + public String toString() { + return "InterfaceNamesDump{}"; + } + + @Override + public int send(final io.fd.jvpp.JVpp jvpp) throws io.fd.jvpp.VppInvocationException { + return ((io.fd.jvpp.stats.JVppStats) jvpp).interfaceNamesDump(); + } +} diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java index 288b556..9e0db46 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStats.java @@ -16,6 +16,7 @@ package io.fd.jvpp.stats.future; +import io.fd.jvpp.stats.dto.InterfaceNamesDetailsReplyDump; import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump; /** @@ -25,4 +26,7 @@ public interface FutureJVppStats extends io.fd.jvpp.stats.future.FutureJVppInvok java.util.concurrent.CompletionStage<InterfaceStatisticsDetailsReplyDump> interfaceStatisticsDump( io.fd.jvpp.stats.dto.InterfaceStatisticsDump request); + + java.util.concurrent.CompletionStage<InterfaceNamesDetailsReplyDump> interfaceNamesDump( + io.fd.jvpp.stats.dto.InterfaceNamesDump request); } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java index 470a2fd..8e5e118 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacade.java @@ -17,7 +17,10 @@ package io.fd.jvpp.stats.future; import io.fd.jvpp.notification.EventRegistry; +import io.fd.jvpp.stats.dto.InterfaceNamesDetailsReplyDump; +import io.fd.jvpp.stats.dto.InterfaceNamesDump; import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump; +import java.util.concurrent.CompletionStage; /** * <p>Implementation of FutureJVpp based on AbstractFutureJVppInvoker @@ -47,6 +50,11 @@ public class FutureJVppStatsFacade extends io.fd.jvpp.stats.future.AbstractFutur } @Override + public CompletionStage<InterfaceNamesDetailsReplyDump> interfaceNamesDump(final InterfaceNamesDump request) { + return send(request, new InterfaceNamesDetailsReplyDump()); + } + + @Override public EventRegistry getEventRegistry() { return null; } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java index a215b89..1c9dfb5 100644 --- a/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java +++ b/java/jvpp-stats/io/fd/jvpp/stats/future/FutureJVppStatsFacadeCallback.java @@ -16,6 +16,7 @@ package io.fd.jvpp.stats.future; +import io.fd.jvpp.stats.dto.InterfaceNamesDetailsReplyDump; import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump; /** @@ -78,4 +79,31 @@ public final class FutureJVppStatsFacadeCallback implements io.fd.jvpp.stats.cal completableFuture.getReplyDump().interfaceStatisticsDetails = reply; } } + + @Override + @SuppressWarnings("unchecked") + public void onInterfaceNamesDetails(final io.fd.jvpp.stats.dto.InterfaceNamesDetails reply) { + io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<InterfaceNamesDetailsReplyDump> + completableFuture; + final int replyId = reply.context; + if (LOG.isLoggable(java.util.logging.Level.FINE)) { + LOG.fine(String.format("Received InterfaceNamesDetails event message: %s", reply)); + } + synchronized (requests) { + completableFuture = + (io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<InterfaceNamesDetailsReplyDump>) requests + .get(replyId); + + if (completableFuture == null) { + // reply received before writer created future, + // create new future, and put into map to notify sender that reply is already received, + // following details replies will add information to this future + completableFuture = + new io.fd.jvpp.stats.future.AbstractFutureJVppInvoker.CompletableDumpFuture<>(replyId, + new InterfaceNamesDetailsReplyDump()); + requests.put(replyId, completableFuture); + } + completableFuture.getReplyDump().interfaceNamesDetails = reply; + } + } } diff --git a/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiNamesTest.java b/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiNamesTest.java new file mode 100644 index 0000000..49c48d7 --- /dev/null +++ b/java/jvpp-stats/io/fd/jvpp/stats/test/FutureApiNamesTest.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package io.fd.jvpp.stats.test; + + +import io.fd.jvpp.JVppRegistry; +import io.fd.jvpp.stats.JVppStatsImpl; +import io.fd.jvpp.stats.JVppStatsRegistryImpl; +import io.fd.jvpp.stats.dto.InterfaceNamesDetailsReplyDump; +import io.fd.jvpp.stats.dto.InterfaceNamesDump; +import io.fd.jvpp.stats.future.FutureJVppStatsFacade; +import java.util.concurrent.Future; +import java.util.logging.Logger; + +public class FutureApiNamesTest { + + private static final Logger LOG = Logger.getLogger(FutureApiNamesTest.class.getName()); + + public static void main(String[] args) throws Exception { + testCallbackApi(args); + } + + private static void testCallbackApi(String[] args) throws Exception { + LOG.info("Testing Java callback API for stats plugin"); + try (final JVppRegistry registry = new JVppStatsRegistryImpl("FutureApiTest"); + final FutureJVppStatsFacade jvpp = new FutureJVppStatsFacade(registry, new JVppStatsImpl())) { + LOG.info("Successfully connected to VPP"); + testinterfaceNamesDump(jvpp); + + LOG.info("Disconnecting..."); + } + } + + private static void testinterfaceNamesDump(FutureJVppStatsFacade jvpp) throws Exception { + LOG.info("Sending InterfaceNamesDump request..."); + final InterfaceNamesDump request = new InterfaceNamesDump(); + + final Future<InterfaceNamesDetailsReplyDump> replyFuture = + jvpp.interfaceNamesDump(request).toCompletableFuture(); + final InterfaceNamesDetailsReplyDump reply = replyFuture.get(); + + if (reply == null || reply.interfaceNamesDetails == null) { + throw new IllegalStateException("Received null response for empty dump: " + reply); + } else { + LOG.info(String.format("Received interface names reply: %s \n", reply.interfaceNamesDetails)); + } + } +} diff --git a/java/jvpp-stats/jvpp_interface_stats.h b/java/jvpp-stats/jvpp_interface_stats.h index 01b8cdb..0cc592e 100644 --- a/java/jvpp-stats/jvpp_interface_stats.h +++ b/java/jvpp-stats/jvpp_interface_stats.h @@ -24,6 +24,9 @@ jclass interfaceStatisticsDumpClass; jclass interfaceStatisticsClass; jclass interfaceStatisticsDetailsClass; +jclass interfaceNamesDumpClass; +jclass interfaceNameClass; +jclass interfaceNamesDetailsClass; jclass callbackExceptionClass; typedef struct interface_statistics { @@ -42,6 +45,12 @@ typedef struct interface_statistics { } vl_api_interface_statistics_details_t; +typedef struct interface_names { + int context; + int sw_if_index; + char *name; +} vl_api_interface_names_details_t; + static int cache_class_references(JNIEnv *env) { interfaceStatisticsDumpClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env, @@ -62,6 +71,26 @@ static int cache_class_references(JNIEnv *env) { (*env)->ExceptionDescribe(env); return JNI_ERR; } + + interfaceNamesDumpClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env, + "io/fd/jvpp/stats/dto/InterfaceNamesDump")); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + return JNI_ERR; + } + interfaceNamesDetailsClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env, + "io/fd/jvpp/stats/dto/InterfaceNamesDetails")); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + return JNI_ERR; + } + interfaceNameClass = (jclass) (*env)->NewGlobalRef(env, (*env)->FindClass(env, + "io/fd/jvpp/stats/dto/InterfaceName")); + 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)) { @@ -82,6 +111,15 @@ static void delete_class_references(JNIEnv *env) { if (interfaceStatisticsClass) { (*env)->DeleteGlobalRef(env, interfaceStatisticsClass); } + if (interfaceNamesDumpClass) { + (*env)->DeleteGlobalRef(env, interfaceNamesDumpClass); + } + if (interfaceNamesDetailsClass) { + (*env)->DeleteGlobalRef(env, interfaceNamesDetailsClass); + } + if (interfaceNameClass) { + (*env)->DeleteGlobalRef(env, interfaceNameClass); + } if (callbackExceptionClass) { (*env)->DeleteGlobalRef(env, callbackExceptionClass); } @@ -150,6 +188,60 @@ interface_statistics_details_handler(JNIEnv *env, vl_api_interface_statistics_de (*env)->DeleteLocalRef(env, dto); } +/** + * Handler for interface_names_details message. + */ +static void +interface_names_details_handler(JNIEnv *env, vl_api_interface_names_details_t *ifc_names, int ifc_count) { + stats_main_t *plugin_main = &stats_main; + jthrowable exc; + if (CLIB_DEBUG > 1) + clib_warning ("Received interface_names_details event message"); + + jmethodID constructor = (*env)->GetMethodID(env, interfaceNamesDetailsClass, "<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, "onInterfaceNamesDetails", + "(Lio/fd/jvpp/stats/dto/InterfaceNamesDetails;)V"); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + clib_warning( + "Unable to extract onInterfaceNamesDetails method reference from stats plugin's callbackClass. Ignoring message.\n"); + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + return; + } + jobject dto = (*env)->NewObject(env, interfaceNamesDetailsClass, constructor, ifc_count, ifc_names->context); + jfieldID interfaceNamesId = (*env)->GetFieldID(env, interfaceNamesDetailsClass, "interfaceNames", + "[Lio/fd/jvpp/stats/dto/InterfaceName;"); + jobject names_array = (*env)->GetObjectField(env, dto, interfaceNamesId); + + jmethodID ifc_names_constructor = (*env)->GetMethodID(env, interfaceNameClass, "<init>", "(ILjava/lang/String;)V"); + for (int i = 0; i < ifc_count; i++) { + jstring name = (*env)->NewStringUTF(env, (char *) ifc_names[i].name); + jobject element = (*env)->NewObject(env, interfaceNameClass, ifc_names_constructor, + ifc_names[i].sw_if_index, + name); + + (*env)->SetObjectArrayElement(env, names_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, names_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) { @@ -176,6 +268,14 @@ set_field(vl_api_interface_statistics_details_t *stats, int index, const char *f stats[index].sw_if_index = index; } +static void +set_names_field(vl_api_interface_names_details_t *ifc_names, int index, const char *field_name, char *name) { + if (strcmp(field_name, "/if/names") == 0) { + ifc_names[index].name = name; + } + ifc_names[index].sw_if_index = index; +} + static stat_segment_data_t *get_ifc_statistics_dump() { u8 **patterns = 0; u32 *dir; @@ -233,4 +333,62 @@ static jint getInterfaceStatisticsDump(JNIEnv *env) { stat_segment_data_free(res); interface_statistics_details_handler(env, ifc_stats, interface_count); return ifc_stats->context; +} + +static stat_segment_data_t *get_ifc_names_dump() { + u8 **patterns = 0; + u32 *dir; + vec_add1(patterns, (u8 *) "/if/names"); + dir = stat_segment_ls(patterns); + return stat_segment_dump(dir); +} + +static jint getInterfaceNamesDump(JNIEnv *env) { + stat_segment_data_t *res; + int i, k, interface_count = 0; + u32 my_context_id = vppjni_get_context_id(&jvpp_main); + res = get_ifc_names_dump(); + if (res == NULL) { + clib_warning("Interface Names dump failed.\n"); + return -1; + } + + if (vec_len (res) > 0) { + if ((res[0].name_vector != 0) && (vec_len (res[0].name_vector) > 0)) { + interface_count = vec_len (res[0].name_vector); + } + } + vl_api_interface_names_details_t ifc_names[interface_count]; + memset(ifc_names, 0, interface_count * sizeof(vl_api_interface_names_details_t)); + int length = 0; + for (i = 0; i < vec_len (res); i++) { + switch (res[i].type) { + case STAT_DIR_TYPE_NAME_VECTOR: + if (res[i].name_vector == 0) + continue; + for (k = 0; k < interface_count; k++) + if (res[i].name_vector[k]) { + set_names_field(ifc_names, k, res[i].name, (char *) res[i].name_vector[k]); + length ++; + } + break; + + default:; + } + } + vl_api_interface_names_details_t ifc_names_reduced[length]; + memset(ifc_names_reduced, 0, length * sizeof(vl_api_interface_names_details_t)); + ifc_names_reduced->context = my_context_id; + // skip null entries + int index = 0; + for (int j = 0; j < interface_count; ++j) { + if (ifc_names[j].name != NULL) { + ifc_names_reduced[index].sw_if_index = ifc_names[j].sw_if_index; + ifc_names_reduced[index].name = ifc_names[j].name; + index ++; + } + } + stat_segment_data_free(res); + interface_names_details_handler(env, ifc_names_reduced, length); + return ifc_names_reduced->context; }
\ No newline at end of file diff --git a/java/jvpp-stats/jvpp_stats.c b/java/jvpp-stats/jvpp_stats.c index d3a0b18..f70877f 100644 --- a/java/jvpp-stats/jvpp_stats.c +++ b/java/jvpp-stats/jvpp_stats.c @@ -36,8 +36,6 @@ JNIEXPORT void JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_init0 (JNIEnv *env, jclass clazz, jobject callback, jlong queue_address, jint my_client_index) { stats_main_t *plugin_main = &stats_main; - clib_warning ("Java_io_fd_jvpp_stats_JVppStatsImpl_init0"); - plugin_main->my_client_index = my_client_index; plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); @@ -68,6 +66,10 @@ JNIEXPORT jint JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_interfaceStatisticsDu return getInterfaceStatisticsDump(env); } +JNIEXPORT jint JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_interfaceNamesDump0(JNIEnv *env, jclass jclazz) { + return getInterfaceNamesDump(env); +} + /* Attach thread to JVM and cache class references when initiating JVPP Stats */ jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; diff --git a/java/jvpp-stats/jvpp_stats.h b/java/jvpp-stats/jvpp_stats.h index d38414b..2cc6abd 100644 --- a/java/jvpp-stats/jvpp_stats.h +++ b/java/jvpp-stats/jvpp_stats.h @@ -45,4 +45,6 @@ JNIEXPORT void JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_close0(JNIEnv *, jcla JNIEXPORT jint JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_interfaceStatisticsDump0(JNIEnv *, jclass); +JNIEXPORT jint JNICALL Java_io_fd_jvpp_stats_JVppStatsImpl_interfaceNamesDump0(JNIEnv *, jclass); + #endif //PROJECT_JVPP_STATS_H |