From 7becd08c4b641886ad08dedb90be156f305140ee Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 31 May 2016 17:45:16 +0200 Subject: VPP-119: JVpp notifications - add notification DTOs to JVpp - add notification callbacks - add notification registry - provide/implement notification registry from future and callback facades Change-Id: I1060ef2ec8ba1eb2e8cff279c93b73aa7c9f9aee Signed-off-by: Maros Marsalek --- .../jvpp/callback/JVppNotificationCallback.java | 24 ++++++ .../org/openvpp/jvpp/dto/JVppNotification.java | 23 ++++++ .../org/openvpp/jvpp/future/FutureJVppInvoker.java | 3 +- .../jvpp/future/FutureJVppInvokerFacade.java | 5 +- .../notification/NotificationRegistryProvider.java | 12 +++ .../NotificationRegistryProviderContext.java | 20 +++++ .../test/CallbackJVppFacadeNotificationTest.java | 87 ++++++++++++++++++++ .../jvpp/test/CallbackNotificationApiTest.java | 93 ++++++++++++++++++++++ .../jvpp/test/FutureApiNotificationTest.java | 60 ++++++++++++++ .../org/openvpp/jvpp/test/NotificationUtils.java | 38 +++++++++ vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt | 3 + 11 files changed, 365 insertions(+), 3 deletions(-) create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java (limited to 'vpp-api/java/jvpp/org') diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.java new file mode 100644 index 00000000..72a75c83 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppNotificationCallback.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.callback; + +/** +* Notification callback +*/ +public interface JVppNotificationCallback { + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.java new file mode 100644 index 00000000..7d0fecb7 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppNotification.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.dto; + +/** +* Base interface for all notification DTOs +*/ +public interface JVppNotification { +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java index 9219e353..1683bd75 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java @@ -21,11 +21,12 @@ import org.openvpp.jvpp.dto.JVppReply; import org.openvpp.jvpp.dto.JVppRequest; import java.util.concurrent.CompletionStage; +import org.openvpp.jvpp.notification.NotificationRegistryProvider; /** * Future facade on top of JVpp */ -public interface FutureJVppInvoker extends AutoCloseable { +public interface FutureJVppInvoker extends NotificationRegistryProvider, AutoCloseable { /** * Invoke asynchronous operation on VPP diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java index 69967a1d..a60e1b28 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java @@ -25,11 +25,12 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import org.openvpp.jvpp.notification.NotificationRegistryProviderContext; /** * Future facade on top of JVpp */ -public class FutureJVppInvokerFacade implements FutureJVppInvoker { +public class FutureJVppInvokerFacade extends NotificationRegistryProviderContext implements FutureJVppInvoker { private final JVpp jvpp; @@ -39,7 +40,7 @@ public class FutureJVppInvokerFacade implements FutureJVppInvoker { private final Map>> requests; public FutureJVppInvokerFacade(final JVpp jvpp, - final Map>> requestMap) { + final Map>> requestMap) { this.jvpp = Objects.requireNonNull(jvpp, "Null jvpp"); // Request map represents the shared state between this facade and it's callback // where facade puts futures in and callback completes + removes them diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java new file mode 100644 index 00000000..50b72be5 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProvider.java @@ -0,0 +1,12 @@ +package org.openvpp.jvpp.notification; + +/** + * Provides notification registry + */ +public interface NotificationRegistryProvider { + + /** + * Get current notification registry instance + */ + NotificationRegistry getNotificationRegistry(); +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java new file mode 100644 index 00000000..8e703812 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/notification/NotificationRegistryProviderContext.java @@ -0,0 +1,20 @@ +package org.openvpp.jvpp.notification; + +/** + * Base class for notification aware JVpp facades + */ +public abstract class NotificationRegistryProviderContext implements NotificationRegistryProvider { + + private final NotificationRegistryImpl notificationRegistry = new NotificationRegistryImpl(); + + public final NotificationRegistry getNotificationRegistry() { + return notificationRegistry; + } + + /** + * Get instance of notification callback. Can be used to propagate notifications from JVpp facade + */ + protected final GlobalNotificationCallback getNotificationCallback() { + return notificationRegistry; + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.java new file mode 100644 index 00000000..430ce881 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeNotificationTest.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.VppCallbackException; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.WantInterfaceEventsCallback; +import org.openvpp.jvpp.callfacade.CallbackJVppFacade; +import org.openvpp.jvpp.dto.WantInterfaceEventsReply; + +public class CallbackJVppFacadeNotificationTest { + + private static void testCallbackFacade() throws Exception { + System.out.println("Testing CallbackJVppFacade for notifications"); + + JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); + + CallbackJVppFacade jvppCallbackFacade = new CallbackJVppFacade(jvpp); + System.out.println("Successfully connected to VPP"); + + final AutoCloseable notificationListenerReg = + jvppCallbackFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback( + NotificationUtils::printNotification + ); + + jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getEnableInterfaceNotificationsReq(), + new WantInterfaceEventsCallback() { + @Override + public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) { + System.out.println("Interface events started"); + } + + @Override + public void onError(final VppCallbackException ex) { + System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", + ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); + } + }); + + System.out.println("Changing interface configuration"); + NotificationUtils.getChangeInterfaceState().send(jvpp); + + Thread.sleep(1000); + + jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getDisableInterfaceNotificationsReq(), + new WantInterfaceEventsCallback() { + @Override + public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) { + System.out.println("Interface events stopped"); + } + + @Override + public void onError(final VppCallbackException ex) { + System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", + ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); + } + }); + + notificationListenerReg.close(); + + Thread.sleep(2000); + + System.out.println("Disconnecting..."); + jvpp.close(); + Thread.sleep(1000); + } + + public static void main(String[] args) throws Exception { + testCallbackFacade(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java new file mode 100644 index 00000000..5bf2b212 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackNotificationApiTest.java @@ -0,0 +1,93 @@ +/* + * 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 static org.openvpp.jvpp.test.NotificationUtils.getChangeInterfaceState; +import static org.openvpp.jvpp.test.NotificationUtils.getDisableInterfaceNotificationsReq; +import static org.openvpp.jvpp.test.NotificationUtils.getEnableInterfaceNotificationsReq; +import static org.openvpp.jvpp.test.NotificationUtils.printNotification; + +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppCallbackException; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.SwInterfaceSetFlagsCallback; +import org.openvpp.jvpp.callback.SwInterfaceSetFlagsNotificationCallback; +import org.openvpp.jvpp.callback.WantInterfaceEventsCallback; +import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification; +import org.openvpp.jvpp.dto.SwInterfaceSetFlagsReply; +import org.openvpp.jvpp.dto.WantInterfaceEventsReply; + +public class CallbackNotificationApiTest { + + private static class TestCallback implements SwInterfaceSetFlagsNotificationCallback, + WantInterfaceEventsCallback, SwInterfaceSetFlagsCallback { + + @Override + public void onSwInterfaceSetFlagsNotification( + final SwInterfaceSetFlagsNotification msg) { + printNotification(msg); + } + + @Override + public void onWantInterfaceEventsReply(final WantInterfaceEventsReply wantInterfaceEventsReply) { + System.out.println("Interface notification stream updated"); + } + + @Override + public void onSwInterfaceSetFlagsReply(final SwInterfaceSetFlagsReply swInterfaceSetFlagsReply) { + System.out.println("Interface flags set successfully"); + } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n", + ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); + + } + } + + private static void testCallbackApi() throws Exception { + System.out.println("Testing Java callback API for notifications"); + JVpp jvpp = new JVppImpl( new VppJNIConnection("CallbackApiTest")); + jvpp.connect( new TestCallback()); + System.out.println("Successfully connected to VPP"); + + getEnableInterfaceNotificationsReq().send(jvpp); + System.out.println("Interface notifications started"); + // TODO test ifc dump which also triggers interface flags send + + System.out.println("Changing interface configuration"); + getChangeInterfaceState().send(jvpp); + + // Notification is received + Thread.sleep(500); + + getDisableInterfaceNotificationsReq().send(jvpp); + System.out.println("Interface events stopped"); + + Thread.sleep(2000); + + 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/FutureApiNotificationTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java new file mode 100644 index 00000000..c48f86d4 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiNotificationTest.java @@ -0,0 +1,60 @@ +/* + * 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 static org.openvpp.jvpp.test.NotificationUtils.getChangeInterfaceState; +import static org.openvpp.jvpp.test.NotificationUtils.getDisableInterfaceNotificationsReq; +import static org.openvpp.jvpp.test.NotificationUtils.getEnableInterfaceNotificationsReq; + +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.future.FutureJVppFacade; + +public class FutureApiNotificationTest { + + private static void testFutureApi() throws Exception { + System.out.println("Testing Java future API for notifications"); + + final org.openvpp.jvpp.JVppImpl impl = + new org.openvpp.jvpp.JVppImpl(new VppJNIConnection("FutureApiTest")); + final FutureJVppFacade jvppFacade = new FutureJVppFacade(impl); + System.out.println("Successfully connected to VPP"); + + final AutoCloseable notificationListenerReg = + jvppFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(NotificationUtils::printNotification); + + jvppFacade.wantInterfaceEvents(getEnableInterfaceNotificationsReq()).toCompletableFuture().get(); + System.out.println("Interface events started"); + + System.out.println("Changing interface configuration"); + jvppFacade.swInterfaceSetFlags(getChangeInterfaceState()).toCompletableFuture().get(); + + Thread.sleep(1000); + + jvppFacade.wantInterfaceEvents(getDisableInterfaceNotificationsReq()).toCompletableFuture().get(); + System.out.println("Interface events stopped"); + + notificationListenerReg.close(); + + 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(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java new file mode 100644 index 00000000..9c24d572 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/NotificationUtils.java @@ -0,0 +1,38 @@ +package org.openvpp.jvpp.test; + +import java.io.PrintStream; +import org.openvpp.jvpp.dto.SwInterfaceSetFlags; +import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification; +import org.openvpp.jvpp.dto.WantInterfaceEvents; + +final class NotificationUtils { + + private NotificationUtils() {} + + static PrintStream printNotification(final SwInterfaceSetFlagsNotification msg) { + return System.out.printf("Received interface notification: ifc: %d, admin: %d, link: %d, deleted: %d\n", + msg.swIfIndex, msg.adminUpDown, msg.linkUpDown, msg.deleted); + } + + static SwInterfaceSetFlags getChangeInterfaceState() { + final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags(); + swInterfaceSetFlags.swIfIndex = 0; + swInterfaceSetFlags.adminUpDown = 1; + swInterfaceSetFlags.deleted = 0; + return swInterfaceSetFlags; + } + + static WantInterfaceEvents getEnableInterfaceNotificationsReq() { + WantInterfaceEvents wantInterfaceEvents = new WantInterfaceEvents(); + wantInterfaceEvents.pid = 1; + wantInterfaceEvents.enableDisable = 1; + return wantInterfaceEvents; + } + + static WantInterfaceEvents getDisableInterfaceNotificationsReq() { + WantInterfaceEvents wantInterfaceEvents = new WantInterfaceEvents(); + wantInterfaceEvents.pid = 1; + wantInterfaceEvents.enableDisable = 0; + return wantInterfaceEvents; + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt b/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt index f9c67ddb..e0aa4f4d 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt @@ -7,8 +7,11 @@ This package contains basic tests for jvpp. To run the tests: Available tests: ControlPingTest - Simple test executing a single control ping using low level JVpp APIs CallbackApiTest - Similar to ControlPingTest, invokes more complex calls (e.g. interface dump) using low level JVpp APIs +CallbackNotificationApiTest - Tests interface notifications using low level JVpp APIs FutureApiTest - Execution of more complex calls using Future based JVpp facade +FutureApiNotificationTest - Tests interface notifications using Future based JVpp facade CallbackJVppFacadeTest - Execution of more complex calls using Callback based JVpp facade +CallbackJVppFacadeNotificationTest - Tests interface notifications using Callback based JVpp facade L2AclTest - Tests L2 ACL creation CreateSubInterfaceTest - Tests sub-interface creation OnErrorCallbackTest - simple test failing with onError -- cgit 1.2.3-korg