diff options
Diffstat (limited to 'vpp-api/java/jvpp/org/openvpp')
13 files changed, 787 insertions, 0 deletions
diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java new file mode 100644 index 00000000000..72ff62c944b --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppConnection.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp; + +/** + * Representation of a management connection to VPP. + * Connection is initiated when instance is created, closed with close(). + */ +public interface VppConnection extends AutoCloseable { + + /** + * Check if this instance connection is active. + * + * @throws IllegalStateException if this instance was disconnected. + */ + void checkActive(); + + /** + * Closes Vpp connection. + */ + @Override + void close(); +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java new file mode 100644 index 00000000000..9e07cc768c4 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppJNIConnection.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; +import org.openvpp.jvpp.callback.JVppCallback; + +/** + * JNI based representation of a management connection to VPP + */ +public final class VppJNIConnection implements VppConnection { + private final static Logger LOG = Logger.getLogger(VppJNIConnection.class.getName()); + private static final String LIBNAME = "libjvpp.so.0.0.0"; + + static { + try { + loadLibrary(); + } catch (Exception e) { + LOG.severe("Can't find vpp jni library: " + LIBNAME); + throw new ExceptionInInitializerError(e); + } + } + + private static void loadStream(final InputStream is) throws IOException { + final Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---"); + final Path p = Files.createTempFile(LIBNAME, null, PosixFilePermissions.asFileAttribute(perms)); + try { + Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); + + try { + Runtime.getRuntime().load(p.toString()); + } catch (UnsatisfiedLinkError e) { + throw new IOException("Failed to load library " + p, e); + } + } finally { + try { + Files.deleteIfExists(p); + } catch (IOException e) { + } + } + } + + private static void loadLibrary() throws IOException { + try (final InputStream is = VppJNIConnection.class.getResourceAsStream('/' + LIBNAME)) { + if (is == null) { + throw new IOException("Failed to open library resource " + LIBNAME); + } + loadStream(is); + } + } + + private final String clientName; + private volatile boolean disconnected = false; + + private VppJNIConnection(final String clientName) { + if (clientName == null) { + throw new NullPointerException("Null clientName"); + } + this.clientName = clientName; + } + + /** + * Guarded by VppJNIConnection.class + */ + private static final Map<String, VppJNIConnection> connections = new HashMap<>(); + + /** + * Create a new Vpp connection identified by clientName parameter. + * + * Multiple instances are allowed since this class is not a singleton + * (VPP allows multiple management connections). + * + * However only a single connection per clientName is allowed. + * + * @param clientName identifier of vpp connection + * @param callback global callback to receive response calls from vpp + * + * @return new Vpp connection + * @throws IOException in case the connection could not be established, or there already is a connection with the same name + */ + public static VppJNIConnection create(final String clientName, final JVppCallback callback) throws IOException { + synchronized (VppJNIConnection.class) { + if(connections.containsKey(clientName)) { + throw new IOException("Client " + clientName + " already connected"); + } + + final VppJNIConnection vppJNIConnection = new VppJNIConnection(clientName); + final int ret = clientConnect(clientName, callback); + if (ret != 0) { + throw new IOException("Connection returned error " + ret); + } + connections.put(clientName, vppJNIConnection); + return vppJNIConnection; + } + } + + @Override + public final void checkActive() { + if (disconnected) { + throw new IllegalStateException("Disconnected client " + clientName); + } + } + + @Override + public synchronized final void close() { + if (!disconnected) { + disconnected = true; + try { + clientDisconnect(); + } finally { + synchronized (VppJNIConnection.class) { + connections.remove(clientName); + } + } + } + } + + private static native int clientConnect(String clientName, JVppCallback callback); + private static native void clientDisconnect(); +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java new file mode 100644 index 00000000000..c17f2e0aa96 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.callback; + +/** +* Base JVppCallback interface +*/ +public interface JVppCallback { +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java new file mode 100644 index 00000000000..295bbba8525 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppDump.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.dto; + +/** +* Base interface for all dump requests +*/ +public interface JVppDump extends JVppRequest { + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java new file mode 100644 index 00000000000..2f4964c4de0 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReply.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.dto; + +/** +* Base interface for all reply DTOs +*/ +public interface JVppReply<REQ extends JVppRequest> { + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java new file mode 100644 index 00000000000..4aecedc19d4 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppReplyDump.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.dto; + +/** +* Base interface for all dump replies +*/ +public interface JVppReplyDump<REQ extends JVppRequest, RESP extends JVppReply<REQ>> + extends JVppReply<REQ> { + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java new file mode 100644 index 00000000000..8cd1534aa13 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.dto; + +import org.openvpp.jvpp.JVpp; + +/** +* Base interface for all request DTOs +*/ +public interface JVppRequest { + + /** + * Invoke current operation asynchronously on VPP + * + * @return context id of this request. Can be used to track incomming response + */ + int send(JVpp jvpp); + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java new file mode 100644 index 00000000000..d860bc2d483 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVpp.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.future; + + +import java.util.concurrent.CompletionStage; +import org.openvpp.jvpp.dto.JVppReply; +import org.openvpp.jvpp.dto.JVppRequest; + +/** +* Future facade on top of JVpp +*/ +public interface FutureJVpp { + + /** + * Invoke asynchronous operation on VPP + * + * @return CompletionStage with future result of an async VPP call + */ + <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req); + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java new file mode 100644 index 00000000000..5b8222c4565 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppFacade.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.future; + + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.dto.ControlPing; +import org.openvpp.jvpp.dto.JVppDump; +import org.openvpp.jvpp.dto.JVppReply; +import org.openvpp.jvpp.dto.JVppReplyDump; +import org.openvpp.jvpp.dto.JVppRequest; + +/** +* Future facade on top of JVpp +*/ +public final class FutureJVppFacade implements FutureJVpp { + + private final JVpp jvpp; + + /** + * Guarded by self + */ + private final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requests; + + public FutureJVppFacade(final JVpp jvpp, + final Map<Integer, CompletableFuture<? extends JVppReply<?>>> requestMap) { + // TODO use guava's preconditions for nonNull and state checks + // However adding guava as a dependency requires better build system for Java in VPP project + // Currently it's just invocation of javac + if(jvpp == null) { + throw new NullPointerException("Null jvpp"); + } + this.jvpp = jvpp; + if(requestMap == null) { + throw new NullPointerException("Null requestMap"); + } + // Request map represents the shared state between this facade and it's callback + // where facade puts futures in and callback completes + removes them + // TODO what if the call never completes ? + this.requests = requestMap; + } + + // TODO use Optional in Future, java8 + + @Override + @SuppressWarnings("unchecked") + public <REQ extends JVppRequest, REPLY extends JVppReply<REQ>> CompletionStage<REPLY> send(REQ req) { + synchronized(requests) { + final int contextId = jvpp.send(req); + + final CompletableFuture<REPLY> replyCompletableFuture; + if(req instanceof JVppDump) { + replyCompletableFuture = (CompletableFuture<REPLY>) new CompletableDumpFuture<>(contextId); + } else { + replyCompletableFuture = new CompletableFuture<>(); + } + + requests.put(contextId, replyCompletableFuture); + if(req instanceof JVppDump) { + requests.put(jvpp.send(new ControlPing()), replyCompletableFuture); + } + return replyCompletableFuture; + } + } + + static final class CompletableDumpFuture<T extends JVppReplyDump<?, ?>> extends CompletableFuture<T> { + // TODO make this final + // The reason why this is not final is the instantiation of ReplyDump DTOs + // Their instantiation must be generated, so currently the DTOs are created in callback and set when first dump reponses + // is returned. Because in callback we have method per response, but here where requests are invoked there is only + // a single generic send method that does not have enough information to create the DTO + // This can be final as soon as we provide specific send methods here + private T replyDump; + private final long contextId; + + CompletableDumpFuture(final long contextId) { + this.contextId = contextId; + } + + long getContextId() { + return contextId; + } + + T getReplyDump() { + return replyDump; + } + + void setReplyDump(final T replyDump) { + this.replyDump = replyDump; + } + } + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java new file mode 100644 index 00000000000..5ac4b69a52d --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.test; + +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.GetNodeIndexCallback; +import org.openvpp.jvpp.callback.ShowVersionCallback; +import org.openvpp.jvpp.callback.SwInterfaceCallback; +import org.openvpp.jvpp.dto.GetNodeIndex; +import org.openvpp.jvpp.dto.GetNodeIndexReply; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDump; + +public class CallbackApiTest { + + private static class TestCallback implements GetNodeIndexCallback, ShowVersionCallback, SwInterfaceCallback { + + @Override + public void onGetNodeIndexReply(final GetNodeIndexReply msg) { + System.out.printf("Received GetNodeIndexReply: context=%d, retval=%d, nodeIndex=%d\n", + msg.context, msg.retval, msg.nodeIndex); + } + @Override + public void onShowVersionReply(final ShowVersionReply msg) { + System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, version=%s, " + + "buildDate=%s, buildDirectory=%s\n", + msg.context, msg.retval, new String(msg.program), new String(msg.version), + new String(msg.buildDate), new String(msg.buildDirectory)); + } + + @Override + public void onSwInterfaceDetails(final SwInterfaceDetails msg) { + System.out.printf("Received SwInterfaceDetails: interfaceName=%s, l2AddressLength=%d, adminUpDown=%d, " + + "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n", + new String(msg.interfaceName), msg.l2AddressLength, msg.adminUpDown, + msg.linkUpDown, msg.linkSpeed, (int)msg.linkMtu); + } + } + + private static void testCallbackApi() throws Exception { + System.out.println("Testing Java callback API"); + JVpp jvpp = new JVppImpl(VppJNIConnection.create("CallbackApiTest", new TestCallback())); + System.out.println("Successfully connected to VPP"); + + System.out.println("Sending ShowVersion request..."); + jvpp.send(new ShowVersion()); + + System.out.println("Sending GetNodeIndex request..."); + GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); + getNodeIndexRequest.nodeName = "node0".getBytes(); + jvpp.send(getNodeIndexRequest); + + System.out.println("Sending SwInterfaceDump request..."); + SwInterfaceDump swInterfaceDumpRequest = new SwInterfaceDump(); + swInterfaceDumpRequest.nameFilterValid = 0; + swInterfaceDumpRequest.nameFilter = "".getBytes(); + jvpp.send(swInterfaceDumpRequest); + + Thread.sleep(5000); + + System.out.println("Disconnecting..."); + jvpp.close(); + Thread.sleep(1000); + } + + public static void main(String[] args) throws Exception { + testCallbackApi(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java new file mode 100644 index 00000000000..df3b0e7056c --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.test; + +import java.util.HashMap; +import java.util.Map; +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.JVppCallback; +import org.openvpp.jvpp.callback.ShowVersionCallback; +import org.openvpp.jvpp.callfacade.CallbackJVppFacade; +import org.openvpp.jvpp.callfacade.CallbackJVppFacadeCallback; + +/** + * CallbackJVppFacade together with CallbackJVppFacadeCallback allow for setting different callback for each request. + * This is more convenient than the approach shown in CallbackApiTest. + */ +public class CallbackJVppFacadeTest { + + private static ShowVersionCallback showVersionCallback1 = msg -> + System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, retval=%d, program=%s," + + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program), + new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + + private static ShowVersionCallback showVersionCallback2 = msg -> + System.out.printf("ShowVersionCallback2 received ShowVersionReply: context=%d, retval=%d, program=%s," + + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program), + new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + + private static void testCallbackFacade() throws Exception { + System.out.println("Testing CallbackJVppFacade"); + + final Map<Integer, JVppCallback> callbackMap = new HashMap<>(); + JVpp impl = new JVppImpl(VppJNIConnection.create("CallbackApiTest", new CallbackJVppFacadeCallback(callbackMap))); + CallbackJVppFacade jvpp = new CallbackJVppFacade(impl, callbackMap); + System.out.println("Successfully connected to VPP"); + + jvpp.showVersion(showVersionCallback1); + jvpp.showVersion(showVersionCallback2); + + + Thread.sleep(2000); + + System.out.println("Disconnecting..."); + impl.close(); + Thread.sleep(1000); + } + + public static void main(String[] args) throws Exception { + testCallbackFacade(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java new file mode 100644 index 00000000000..f1bd41de86f --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.test; + +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.ControlPingCallback; +import org.openvpp.jvpp.dto.ControlPing; +import org.openvpp.jvpp.dto.ControlPingReply; + +public class ControlPingTest { + + private static void testControlPing() throws Exception { + System.out.println("Testing ControlPing using Java callback API"); + + JVpp jvpp = new JVppImpl(VppJNIConnection.create("ControlPingTest", new ControlPingCallback() { + @Override + public void onControlPingReply(final ControlPingReply reply) { + System.out.printf("Received ControlPingReply: context=%d, retval=%d, clientIndex=%d vpePid=%d\n", + reply.context, reply.retval, reply.clientIndex, reply.vpePid); + } + })); + System.out.println("Successfully connected to VPP"); + Thread.sleep(1000); + + jvpp.send(new ControlPing()); + + Thread.sleep(2000); + + System.out.println("Disconnecting..."); + jvpp.close(); + Thread.sleep(1000); + } + + public static void main(String[] args) throws Exception { + testControlPing(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java new file mode 100644 index 00000000000..b5b36d58015 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016 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 org.openvpp.jvpp.test; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.dto.GetNodeIndex; +import org.openvpp.jvpp.dto.GetNodeIndexReply; +import org.openvpp.jvpp.dto.JVppReply; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceDump; +import org.openvpp.jvpp.future.FutureJVppFacade; +import org.openvpp.jvpp.future.FutureJVppFacadeCallback; + +public class FutureApiTest { + + private static void testShowVersion(final FutureJVppFacade jvpp) { + System.out.println("Sending ShowVersion request..."); + try { + final Future<JVppReply<ShowVersion>> replyFuture = jvpp.send(new ShowVersion()).toCompletableFuture(); + final ShowVersionReply reply = (ShowVersionReply) replyFuture.get(); // TODO can we get rid of that cast? + System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, " + + "version=%s, buildDate=%s, buildDirectory=%s\n", + reply.context, reply.retval, new String(reply.program), new String(reply.version), + new String(reply.buildDate), new String(reply.buildDirectory)); + } catch (Exception e) { + System.err.printf("ShowVersion request failed:\n"); + e.printStackTrace(); + } + } + + /** + * This test will fail with some error code if node 'node0' is not defined. + * TODO: consider adding error messages specific for given api calls + */ + private static void testGetNodeIndex(final FutureJVppFacade jvpp) { + System.out.println("Sending GetNodeIndex request..."); + try { + final GetNodeIndex request = new GetNodeIndex(); + request.nodeName = "node0".getBytes(); + final Future<JVppReply<GetNodeIndex>> replyFuture = jvpp.send(request).toCompletableFuture(); + final GetNodeIndexReply reply = (GetNodeIndexReply) replyFuture.get(); + System.out.printf("Received GetNodeIndexReply: context=%d, retval=%d, nodeIndex=%d\n", + reply.context, reply.retval, reply.nodeIndex); + } catch (Exception e) { + System.err.printf("GetNodeIndex request failed:\n"); + e.printStackTrace(); + } + } + + private static void testSwInterfaceDump(final FutureJVppFacade jvpp) { + System.out.println("Sending SwInterfaceDump request..."); + try { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilterValid = 0; + request.nameFilter = "".getBytes(); + final Future<JVppReply<SwInterfaceDump>> replyFuture = jvpp.send(request).toCompletableFuture(); + final SwInterfaceDetailsReplyDump reply = (SwInterfaceDetailsReplyDump) replyFuture.get(); + + if (reply == null) { + throw new IllegalStateException("SwInterfaceDetailsReplyDump is null!"); + } + if (reply.swInterfaceDetails == null) { + throw new IllegalStateException("SwInterfaceDetailsReplyDump.swInterfaceDetails is null!"); + } + + for (SwInterfaceDetails details : reply.swInterfaceDetails) { + if (details == null) { + throw new IllegalStateException("reply.swInterfaceDetails contains null element!"); + } + + System.out.printf("Received SwInterfaceDetails: interfaceName=%s, l2AddressLength=%d, adminUpDown=%d, " + + "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n", + new String(details.interfaceName), details.l2AddressLength, details.adminUpDown, + details.linkUpDown, details.linkSpeed, (int) details.linkMtu); + } + } catch (Exception e) { + System.err.printf("SwInterfaceDump request failed:\n"); + e.printStackTrace(); + } + } + + private static void testFutureApi() throws Exception { + System.out.println("Testing Java future API"); + + final Map<Integer, CompletableFuture<? extends JVppReply<?>>> map = new HashMap<>(); + final org.openvpp.jvpp.JVppImpl impl = + new org.openvpp.jvpp.JVppImpl(VppJNIConnection.create("FutureApiTest", new FutureJVppFacadeCallback(map))); + final FutureJVppFacade jvpp = new FutureJVppFacade(impl, map); + System.out.println("Successfully connected to VPP"); + + testShowVersion(jvpp); + testGetNodeIndex(jvpp); + testSwInterfaceDump(jvpp); + + System.out.println("Disconnecting..."); + // TODO we should consider adding jvpp.close(); to the facade + impl.close(); + } + + public static void main(String[] args) throws Exception { + testFutureApi(); + } +} |