summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-04-09 16:22:06 +0200
committerMaros Marsalek <mmarsale@cisco.com>2016-06-10 11:04:21 +0200
commit927bd5f4d9d04b46dbec3b081810a92f8b4572f9 (patch)
tree13f1118c14cebfb7524de049eeb40f30f4948776 /v3po/v3po2vpp
parent8d79904b2036ea3042a13292f075f64ae84e843f (diff)
HONEYCOMB-33: Add notification service to Hc
Implement VPP interface notification translator as part of v3po2vpp plugin Change-Id: I69cfad9668ae9e4d79ed30bb8d54d294faa4c54a Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po/v3po2vpp')
-rw-r--r--v3po/v3po2vpp/pom.xml5
-rw-r--r--v3po/v3po2vpp/src/main/config/default-config.xml37
-rw-r--r--v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducer.java149
-rw-r--r--v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModule.java28
-rw-r--r--v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModuleFactory.java13
-rw-r--r--v3po/v3po2vpp/src/main/yang/v3po2vpp.yang39
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducerTest.java130
7 files changed, 401 insertions, 0 deletions
diff --git a/v3po/v3po2vpp/pom.xml b/v3po/v3po2vpp/pom.xml
index d02807c9d..edff40b3d 100644
--- a/v3po/v3po2vpp/pom.xml
+++ b/v3po/v3po2vpp/pom.xml
@@ -36,6 +36,11 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
+ <artifactId>notification-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
<artifactId>translate-utils</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/v3po/v3po2vpp/src/main/config/default-config.xml b/v3po/v3po2vpp/src/main/config/default-config.xml
index 19226d4fc..1ee177553 100644
--- a/v3po/v3po2vpp/src/main/config/default-config.xml
+++ b/v3po/v3po2vpp/src/main/config/default-config.xml
@@ -26,6 +26,7 @@
<capability>
urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled?module=threadpool-impl-scheduled&amp;revision=2013-12-01
</capability>
+ <capability>urn:honeycomb:params:xml:ns:yang:notification:impl?module=notification-impl&amp;revision=2016-06-01</capability>
</required-capabilities>
<configuration>
@@ -65,6 +66,35 @@
<name>global-netconf-ssh-scheduled-executor</name>
</keepalive-executor>
</module>
+
+ <!-- Interface notification producer-->
+ <module>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:v3po2vpp">prefix:vpp-interface-notification-producer</type>
+ <name>vpp-interface-notification-producer</name>
+ <vpp-jvpp>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:jvpp:cfg">prefix:vpp-jvpp</type>
+ <name>vpp-jvpp</name>
+ </vpp-jvpp>
+ <interface-context>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
+ <name>interface-context</name>
+ </interface-context>
+ <realtime-mapping-context>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:translate:api">prefix:honeycomb-mapping-context</type>
+ <name>realtime-mapping-context</name>
+ </realtime-mapping-context>
+ </module>
+ <!-- Register to HC notification collector-->
+ <module>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:notification:impl">prefix:honeycomb-notification-manager</type>
+ <name>honeycomb-notification-manager</name>
+ <notification-producers>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:notification:api">prefix:honeycomb-notification-producer</type>
+ <name>vpp-interface-notification-producer</name>
+ </notification-producers>
+ </module>
+ <!-- /Interface notification producer -->
+
<module>
<type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:v3po2vpp">prefix:interfaces-state-honeycomb-reader</type>
<name>interfaces-state-honeycomb-reader</name>
@@ -157,6 +187,13 @@
</instance>
</service>
<service>
+ <type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:notification:api">prefix:honeycomb-notification-producer</type>
+ <instance>
+ <name>vpp-interface-notification-producer</name>
+ <provider>/modules/module[type='vpp-interface-notification-producer'][name='vpp-interface-notification-producer']</provider>
+ </instance>
+ </service>
+ <service>
<type xmlns:prefix="urn:honeycomb:params:xml:ns:yang:vpp:util">prefix:naming-context</type>
<instance>
<name>interface-context</name>
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducer.java
new file mode 100644
index 000000000..f3689d7e2
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducer.java
@@ -0,0 +1,149 @@
+/*
+ * 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 io.fd.honeycomb.v3po.translate.v3po.notification;
+
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.v3po.notification.ManagedNotificationProducer;
+import io.fd.honeycomb.v3po.notification.NotificationCollector;
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.CompletionStage;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceDeleted;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceDeletedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceNameOrIndex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceStateChange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceStateChangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceStatus;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.openvpp.jvpp.VppBaseCallException;
+import org.openvpp.jvpp.VppInvocationException;
+import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification;
+import org.openvpp.jvpp.dto.WantInterfaceEvents;
+import org.openvpp.jvpp.dto.WantInterfaceEventsReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Notification producer for interface events. It starts interface notification stream and for every
+ * received notification, it transforms it into its BA equivalent and pushes into HC's notification collector.
+ */
+@NotThreadSafe
+public final class InterfaceChangeNotificationProducer implements ManagedNotificationProducer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceChangeNotificationProducer.class);
+
+ private final FutureJVpp jvpp;
+ private final NamingContext interfaceContext;
+ private final MappingContext mappingContext;
+ @Nullable
+ private AutoCloseable notificationListenerReg;
+
+ public InterfaceChangeNotificationProducer(@Nonnull final FutureJVpp jvpp,
+ @Nonnull final NamingContext interfaceContext,
+ @Nonnull final MappingContext mappingContext) {
+ this.jvpp = jvpp;
+ this.interfaceContext = interfaceContext;
+ this.mappingContext = mappingContext;
+ }
+
+ @Override
+ public void start(final NotificationCollector collector) {
+ LOG.trace("Starting interface notifications");
+ enableDisableIfcNotifications(1);
+ LOG.debug("Interface notifications started successfully");
+ notificationListenerReg = jvpp.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(
+ swInterfaceSetFlagsNotification -> {
+ LOG.trace("Interface notification received: {}", swInterfaceSetFlagsNotification);
+ collector.onNotification(transformNotification(swInterfaceSetFlagsNotification));
+ }
+ );
+ }
+
+ private Notification transformNotification(final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification) {
+ if(swInterfaceSetFlagsNotification.deleted == 1) {
+ return new InterfaceDeletedBuilder().setName(getIfcName(swInterfaceSetFlagsNotification)).build();
+ } else {
+ return new InterfaceStateChangeBuilder()
+ .setName(getIfcName(swInterfaceSetFlagsNotification))
+ .setAdminStatus(swInterfaceSetFlagsNotification.adminUpDown == 1 ? InterfaceStatus.Up : InterfaceStatus.Down)
+ .setOperStatus(swInterfaceSetFlagsNotification.linkUpDown == 1 ? InterfaceStatus.Up : InterfaceStatus.Down)
+ .build();
+ }
+ }
+
+ /**
+ * Get mapped name for the interface. Best effort only! The mapping might not yet be stored in context
+ * data tree (write transaction is still in progress and context changes have not been committed yet, or
+ * VPP sends the notification before it returns create request(that would store mapping)).
+ *
+ * In case mapping is not available, index is used as name. TODO inconsistent behavior, maybe just use indices ?
+ */
+ private InterfaceNameOrIndex getIfcName(final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification) {
+ return interfaceContext.containsName(swInterfaceSetFlagsNotification.swIfIndex, mappingContext)
+ ? new InterfaceNameOrIndex(interfaceContext.getName(swInterfaceSetFlagsNotification.swIfIndex, mappingContext))
+ : new InterfaceNameOrIndex((long) swInterfaceSetFlagsNotification.swIfIndex);
+ }
+
+ @Override
+ public void stop() {
+ LOG.trace("Stopping interface notifications");
+ enableDisableIfcNotifications(0);
+ LOG.debug("Interface notifications stopped successfully");
+ try {
+ if (notificationListenerReg != null) {
+ notificationListenerReg.close();
+ }
+ } catch (Exception e) {
+ LOG.warn("Unable to properly close notification registration: {}", notificationListenerReg, e);
+ }
+ }
+
+ private void enableDisableIfcNotifications(int enableDisable) {
+ final WantInterfaceEvents wantInterfaceEvents = new WantInterfaceEvents();
+ wantInterfaceEvents.pid = 1;
+ wantInterfaceEvents.enableDisable = enableDisable;
+ final CompletionStage<WantInterfaceEventsReply> wantInterfaceEventsReplyCompletionStage;
+ try {
+ wantInterfaceEventsReplyCompletionStage = jvpp.wantInterfaceEvents(wantInterfaceEvents);
+ TranslateUtils.getReply(wantInterfaceEventsReplyCompletionStage.toCompletableFuture());
+ } catch (VppBaseCallException e) {
+ LOG.warn("Unable to {} interface notifications", enableDisable == 1 ? "enable" : "disable", e);
+ throw new IllegalStateException("Unable to control interface notifications", e);
+ }
+
+ }
+
+ @Override
+ public Collection<Class<? extends Notification>> getNotificationTypes() {
+ final ArrayList<Class<? extends Notification>> classes = Lists.newArrayList();
+ classes.add(InterfaceStateChange.class);
+ classes.add(InterfaceDeleted.class);
+ return classes;
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.trace("Closing interface notifications producer");
+ stop();
+ }
+}
diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModule.java
new file mode 100644
index 000000000..4251fdab2
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModule.java
@@ -0,0 +1,28 @@
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406;
+
+import io.fd.honeycomb.v3po.translate.v3po.notification.InterfaceChangeNotificationProducer;
+
+public class VppInterfaceNotificationProducerModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractVppInterfaceNotificationProducerModule {
+
+ public VppInterfaceNotificationProducerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public VppInterfaceNotificationProducerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.VppInterfaceNotificationProducerModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ return new InterfaceChangeNotificationProducer(
+ getVppJvppDependency(),
+ getInterfaceContextDependency(),
+ getRealtimeMappingContextDependency());
+ }
+
+}
diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModuleFactory.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModuleFactory.java
new file mode 100644
index 000000000..c80a0d364
--- /dev/null
+++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppInterfaceNotificationProducerModuleFactory.java
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: v3po2vpp yang module local name: vpp-interface-notification-producer
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Jun 01 17:12:36 CEST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406;
+public class VppInterfaceNotificationProducerModuleFactory extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractVppInterfaceNotificationProducerModuleFactory {
+
+}
diff --git a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang
index 5ccac8e94..cf89cbd51 100644
--- a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang
+++ b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang
@@ -10,6 +10,7 @@ module v3po2vpp {
import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
import vpp-util { prefix vpp-u; revision-date 2016-04-06; }
import threadpool {prefix th;}
+ import notification-api { prefix hc-notif-a; revision-date 2016-06-01; }
description
"This module contains reads and writers for v3po yang model";
@@ -68,6 +69,44 @@ module v3po2vpp {
}
}
+ identity vpp-interface-notification-producer {
+ base config:module-type;
+ config:provided-service hc-notif-a:honeycomb-notification-producer;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case vpp-interface-notification-producer {
+ when "/config:modules/config:module/config:type = 'vpp-interface-notification-producer'";
+
+ container vpp-jvpp {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity vjvppc:vpp-jvpp;
+ }
+ }
+ }
+
+ container interface-context {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity vpp-u:naming-context;
+ }
+ }
+ }
+
+ container realtime-mapping-context {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity tapi:honeycomb-mapping-context;
+ }
+ }
+ }
+ }
+ }
+
identity interfaces-state-honeycomb-reader {
base config:module-type;
config:provided-service tapi:honeycomb-reader;
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducerTest.java
new file mode 100644
index 000000000..dd5a22d61
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/notification/InterfaceChangeNotificationProducerTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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 io.fd.honeycomb.v3po.translate.v3po.notification;
+
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMapping;
+import static io.fd.honeycomb.v3po.translate.v3po.test.ContextTestUtils.getMappingIid;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.v3po.notification.NotificationCollector;
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceStateChange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceStatus;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.openvpp.jvpp.callback.SwInterfaceSetFlagsNotificationCallback;
+import org.openvpp.jvpp.dto.SwInterfaceSetFlagsNotification;
+import org.openvpp.jvpp.dto.WantInterfaceEvents;
+import org.openvpp.jvpp.dto.WantInterfaceEventsReply;
+import org.openvpp.jvpp.future.FutureJVpp;
+import org.openvpp.jvpp.notification.NotificationRegistry;
+
+public class InterfaceChangeNotificationProducerTest {
+
+ @Mock
+ private FutureJVpp jVpp;
+ private NamingContext namingContext = new NamingContext("test", "test-instance");
+ @Mock
+ private MappingContext mappingContext;
+ @Mock
+ private NotificationCollector collector;
+ @Mock
+ private NotificationRegistry notificationRegistry;
+ @Mock
+ private AutoCloseable notificationListenerReg;
+
+ private ArgumentCaptor<SwInterfaceSetFlagsNotificationCallback> callbackArgumentCaptor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn(notificationRegistry).when(jVpp).getNotificationRegistry();
+ callbackArgumentCaptor = ArgumentCaptor.forClass(SwInterfaceSetFlagsNotificationCallback.class);
+ doReturn(notificationListenerReg).when(notificationRegistry).registerSwInterfaceSetFlagsNotificationCallback(
+ callbackArgumentCaptor.capture());
+
+ final KeyedInstanceIdentifier<Mapping, MappingKey> eth0Id = getMappingIid("eth0", "test-instance");
+ final Optional<Mapping> eth0 = getMapping("eth0", 0);
+
+ final List<Mapping> allMappings = Lists.newArrayList(getMapping("eth0", 0).get());
+ final Mappings allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build();
+ doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(eth0Id.firstIdentifierOf(Mappings.class));
+
+ doReturn(eth0).when(mappingContext).read(eth0Id);
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ final CompletableFuture<WantInterfaceEventsReply> response = new CompletableFuture<>();
+ response.complete(new WantInterfaceEventsReply());
+ doReturn(response).when(jVpp).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ final InterfaceChangeNotificationProducer interfaceChangeNotificationProducer =
+ new InterfaceChangeNotificationProducer(jVpp, namingContext, mappingContext);
+
+ interfaceChangeNotificationProducer.start(collector);
+ verify(jVpp).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ verify(jVpp).getNotificationRegistry();
+ verify(notificationRegistry).registerSwInterfaceSetFlagsNotificationCallback(any(
+ SwInterfaceSetFlagsNotificationCallback.class));
+
+ interfaceChangeNotificationProducer.stop();
+ verify(jVpp, times(2)).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ verify(notificationListenerReg).close();
+ }
+
+ @Test
+ public void testNotification() throws Exception {
+ final CompletableFuture<WantInterfaceEventsReply> response = new CompletableFuture<>();
+ response.complete(new WantInterfaceEventsReply());
+ doReturn(response).when(jVpp).wantInterfaceEvents(any(WantInterfaceEvents.class));
+ final InterfaceChangeNotificationProducer interfaceChangeNotificationProducer =
+ new InterfaceChangeNotificationProducer(jVpp, namingContext, mappingContext);
+
+ interfaceChangeNotificationProducer.start(collector);
+
+ final SwInterfaceSetFlagsNotification swInterfaceSetFlagsNotification = new SwInterfaceSetFlagsNotification();
+ swInterfaceSetFlagsNotification.deleted = 0;
+ swInterfaceSetFlagsNotification.swIfIndex = 0;
+ swInterfaceSetFlagsNotification.adminUpDown = 1;
+ swInterfaceSetFlagsNotification.linkUpDown = 1;
+
+ callbackArgumentCaptor.getValue().onSwInterfaceSetFlagsNotification(swInterfaceSetFlagsNotification);
+ final ArgumentCaptor<InterfaceStateChange> notificationCaptor =
+ ArgumentCaptor.forClass(InterfaceStateChange.class);
+ verify(collector).onNotification(notificationCaptor.capture());
+
+ assertEquals("eth0", notificationCaptor.getValue().getName().getString());
+ assertEquals(InterfaceStatus.Up, notificationCaptor.getValue().getAdminStatus());
+ assertEquals(InterfaceStatus.Up, notificationCaptor.getValue().getOperStatus());
+ }
+} \ No newline at end of file