From: Jozef Gloncak Date: Thu, 18 Jun 2015 12:10:52 +0000 (+0200) Subject: BUG 3548 - LLDP speaker doesn't start send LLDP packet on port up. X-Git-Tag: release/beryllium~179 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=cf1418573783bea32224b7321882c97598005a93;p=openflowplugin.git BUG 3548 - LLDP speaker doesn't start send LLDP packet on port up. Listener on changes on changes on State subtree was added. If instance of FlowCapableNodeConnector with port down is received in NodeConnectorInventoryEventTranslator then it is stored to local map. When event port up event is received then stored instance is looked up in map, state part is replaced (with port up information) and it is sent to LLDP. Change-Id: Ic989a88c06b2e266c63375bd19e3ed2c2b4d4c2d Signed-off-by: Jozef Gloncak (cherry picked from commit 5865c58f43808e730fdb9dc310741663c304112d) --- diff --git a/applications/lldp-speaker/src/main/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslator.java b/applications/lldp-speaker/src/main/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslator.java index ed3028463b..71b3b3e6ce 100644 --- a/applications/lldp-speaker/src/main/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslator.java +++ b/applications/lldp-speaker/src/main/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslator.java @@ -8,6 +8,11 @@ package org.opendaylight.openflowplugin.applications.lldpspeaker; +import com.google.common.collect.Iterables; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State; +import java.util.HashMap; import com.google.common.collect.ImmutableSet; import java.util.Map; import java.util.Set; @@ -34,26 +39,47 @@ import org.slf4j.LoggerFactory; * and update LLDPSpeaker and topology. */ public class NodeConnectorInventoryEventTranslator implements DataChangeListener, AutoCloseable { + /** + * + */ + private static final InstanceIdentifier II_TO_STATE + = InstanceIdentifier.builder(Nodes.class) + .child(Node.class) + .child(NodeConnector.class) + .augmentation(FlowCapableNodeConnector.class) + .child(State.class) + .build(); + + private static final InstanceIdentifier II_TO_FLOW_CAPABLE_NODE_CONNECTOR + = InstanceIdentifier.builder(Nodes.class) + .child(Node.class) + .child(NodeConnector.class) + .augmentation(FlowCapableNodeConnector.class) + .build(); + private static final Logger LOG = LoggerFactory.getLogger(NodeConnectorInventoryEventTranslator.class); private final ListenerRegistration dataChangeListenerRegistration; + private final ListenerRegistration listenerOnPortStateRegistration; private final Set observers; + private final Map,FlowCapableNodeConnector> iiToDownFlowCapableNodeConnectors = new HashMap<>(); public NodeConnectorInventoryEventTranslator(DataBroker dataBroker, NodeConnectorEventsObserver... observers) { this.observers = ImmutableSet.copyOf(observers); dataChangeListenerRegistration = dataBroker.registerDataChangeListener( LogicalDatastoreType.OPERATIONAL, - InstanceIdentifier.builder(Nodes.class) - .child(Node.class) - .child(NodeConnector.class) - .augmentation(FlowCapableNodeConnector.class) - .build(), + II_TO_FLOW_CAPABLE_NODE_CONNECTOR, this, AsyncDataBroker.DataChangeScope.BASE); + listenerOnPortStateRegistration = dataBroker.registerDataChangeListener( + LogicalDatastoreType.OPERATIONAL, + II_TO_STATE, + this, AsyncDataBroker.DataChangeScope.SUBTREE); } @Override public void close() { dataChangeListenerRegistration.close(); + listenerOnPortStateRegistration.close(); } @Override @@ -65,10 +91,13 @@ public class NodeConnectorInventoryEventTranslator implements DataChangeListener for (Map.Entry, DataObject> entry : change.getCreatedData().entrySet()) { InstanceIdentifier nodeConnectorInstanceId = entry.getKey().firstIdentifierOf(NodeConnector.class); - - FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue(); - if (!isPortDown(flowConnector)) { - notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector); + if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) { + FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue(); + if (!isPortDown(flowConnector)) { + notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector); + } else { + iiToDownFlowCapableNodeConnectors.put(nodeConnectorInstanceId, flowConnector); + } } } @@ -76,21 +105,46 @@ public class NodeConnectorInventoryEventTranslator implements DataChangeListener for (Map.Entry, DataObject> entry : change.getUpdatedData().entrySet()) { InstanceIdentifier nodeConnectorInstanceId = entry.getKey().firstIdentifierOf(NodeConnector.class); - FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue(); - if (isPortDown(flowConnector)) { - notifyNodeConnectorDisappeared(nodeConnectorInstanceId); - } else { - notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector); + if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) { + FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue(); + if (isPortDown(flowConnector)) { + notifyNodeConnectorDisappeared(nodeConnectorInstanceId); + } else { + notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector); + } + } else if (compareIITail(entry.getKey(),II_TO_STATE)) { + FlowCapableNodeConnector flowNodeConnector = iiToDownFlowCapableNodeConnectors.get(nodeConnectorInstanceId); + if (flowNodeConnector != null) { + State state = (State)entry.getValue(); + if (!state.isLinkDown()) { + FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder(flowNodeConnector); + flowCapableNodeConnectorBuilder.setState(state); + notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowCapableNodeConnectorBuilder.build()); + iiToDownFlowCapableNodeConnectors.remove(nodeConnectorInstanceId); + } + } } } // Iterate over removed node connectors for (InstanceIdentifier removed : change.getRemovedPaths()) { - InstanceIdentifier nodeConnectorInstanceId = removed.firstIdentifierOf(NodeConnector.class); - notifyNodeConnectorDisappeared(nodeConnectorInstanceId); + if (compareIITail(removed,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) { + InstanceIdentifier nodeConnectorInstanceId = removed.firstIdentifierOf(NodeConnector.class); + notifyNodeConnectorDisappeared(nodeConnectorInstanceId); + } } } + /** + * @param key + * @param iiToFlowCapableNodeConnector + * @return + */ + private boolean compareIITail(InstanceIdentifier ii1, + InstanceIdentifier ii2) { + return Iterables.getLast(ii1.getPathArguments()).equals(Iterables.getLast(ii2.getPathArguments())); + } + private static boolean isPortDown(FlowCapableNodeConnector flowCapableNodeConnector) { PortState portState = flowCapableNodeConnector.getState(); PortConfig portConfig = flowCapableNodeConnector.getConfiguration(); diff --git a/applications/lldp-speaker/src/test/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslatorTest.java b/applications/lldp-speaker/src/test/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslatorTest.java index a526922043..3426d29fcc 100644 --- a/applications/lldp-speaker/src/test/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslatorTest.java +++ b/applications/lldp-speaker/src/test/java/org/opendaylight/openflowplugin/applications/lldpspeaker/NodeConnectorInventoryEventTranslatorTest.java @@ -36,6 +36,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @RunWith(MockitoJUnitRunner.class) public class NodeConnectorInventoryEventTranslatorTest { static InstanceIdentifier id = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:1"); + static InstanceIdentifier iiToConnector = id.augmentation(FlowCapableNodeConnector.class); static FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector().build(); @Mock DataBroker dataBroker; @@ -48,6 +49,7 @@ public class NodeConnectorInventoryEventTranslatorTest { @Before public void setUp() { + when(dataBroker.registerDataChangeListener( any(LogicalDatastoreType.class), any(InstanceIdentifier.class), @@ -64,7 +66,7 @@ public class NodeConnectorInventoryEventTranslatorTest { @Test public void testNodeConnectorCreation() { // Setup dataChangedEvent to mock new port creation in inventory - dataChangedEvent.created.put(id, fcnc); + dataChangedEvent.created.put(iiToConnector, fcnc); // Invoke NodeConnectorInventoryEventTranslator and check result translator.onDataChanged(dataChangedEvent); @@ -111,7 +113,7 @@ public class NodeConnectorInventoryEventTranslatorTest { FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(true, false).build(); // Setup dataChangedEvent to mock link down - dataChangedEvent.updated.put(id, fcnc); + dataChangedEvent.updated.put(iiToConnector, fcnc); // Invoke NodeConnectorInventoryEventTranslator and check result translator.onDataChanged(dataChangedEvent); @@ -128,7 +130,7 @@ public class NodeConnectorInventoryEventTranslatorTest { FlowCapableNodeConnector fcnc = TestUtils.createFlowCapableNodeConnector(false, true).build(); // Setup dataChangedEvent to mock link down and administrative port down - dataChangedEvent.updated.put(id, fcnc); + dataChangedEvent.updated.put(iiToConnector, fcnc); // Invoke NodeConnectorInventoryEventTranslator and check result translator.onDataChanged(dataChangedEvent); @@ -143,7 +145,7 @@ public class NodeConnectorInventoryEventTranslatorTest { @Test public void testNodeConnectorUpdateToUp() { // Setup dataChangedEvent to mock link up and administrative port up - dataChangedEvent.updated.put(id, fcnc); + dataChangedEvent.updated.put(iiToConnector, fcnc); // Invoke NodeConnectorInventoryEventTranslator and check result translator.onDataChanged(dataChangedEvent); @@ -157,7 +159,7 @@ public class NodeConnectorInventoryEventTranslatorTest { @Test public void testNodeConnectorRemoval() { // Setup dataChangedEvent to mock node connector removal - dataChangedEvent.removed.add(id); + dataChangedEvent.removed.add(iiToConnector); // Invoke NodeConnectorInventoryEventTranslator and check result translator.onDataChanged(dataChangedEvent); @@ -173,10 +175,11 @@ public class NodeConnectorInventoryEventTranslatorTest { public void testMultipleObserversNotified() throws Exception { // Create prerequisites InstanceIdentifier id2 = TestUtils.createNodeConnectorId("openflow:1", "openflow:1:2"); + InstanceIdentifier iiToConnector2 = id2.augmentation(FlowCapableNodeConnector.class); // Setup dataChangedEvent to mock port creation and removal - dataChangedEvent.created.put(id, fcnc); - dataChangedEvent.removed.add(id2); + dataChangedEvent.created.put(iiToConnector, fcnc); + dataChangedEvent.removed.add(iiToConnector2); // Invoke onDataChanged and check that both observers notified translator.onDataChanged(dataChangedEvent); @@ -197,7 +200,7 @@ public class NodeConnectorInventoryEventTranslatorTest { translator.close(); // Verify that ListenerRegistration to DOM events - verify(dataChangeListenerRegistration).close(); + verify(dataChangeListenerRegistration, times(2)).close(); } static class MockDataChangedEvent implements AsyncDataChangeEvent, DataObject> {