2 * Copyright (c) 2014 Pacnet and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.applications.lldpspeaker;
11 import com.google.common.collect.Iterables;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
15 import java.util.HashMap;
16 import com.google.common.collect.ImmutableSet;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
21 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortState;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
38 * NodeConnectorInventoryEventTranslator is listening for changes in inventory operational DOM tree
39 * and update LLDPSpeaker and topology.
41 public class NodeConnectorInventoryEventTranslator implements DataChangeListener, AutoCloseable {
45 private static final InstanceIdentifier<State> II_TO_STATE
46 = InstanceIdentifier.builder(Nodes.class)
48 .child(NodeConnector.class)
49 .augmentation(FlowCapableNodeConnector.class)
53 private static final InstanceIdentifier<FlowCapableNodeConnector> II_TO_FLOW_CAPABLE_NODE_CONNECTOR
54 = InstanceIdentifier.builder(Nodes.class)
56 .child(NodeConnector.class)
57 .augmentation(FlowCapableNodeConnector.class)
60 private static final Logger LOG = LoggerFactory.getLogger(NodeConnectorInventoryEventTranslator.class);
62 private final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
63 private final ListenerRegistration<DataChangeListener> listenerOnPortStateRegistration;
64 private final Set<NodeConnectorEventsObserver> observers;
65 private final Map<InstanceIdentifier<?>,FlowCapableNodeConnector> iiToDownFlowCapableNodeConnectors = new HashMap<>();
67 public NodeConnectorInventoryEventTranslator(DataBroker dataBroker, NodeConnectorEventsObserver... observers) {
68 this.observers = ImmutableSet.copyOf(observers);
69 dataChangeListenerRegistration = dataBroker.registerDataChangeListener(
70 LogicalDatastoreType.OPERATIONAL,
71 II_TO_FLOW_CAPABLE_NODE_CONNECTOR,
72 this, AsyncDataBroker.DataChangeScope.BASE);
73 listenerOnPortStateRegistration = dataBroker.registerDataChangeListener(
74 LogicalDatastoreType.OPERATIONAL,
76 this, AsyncDataBroker.DataChangeScope.SUBTREE);
81 dataChangeListenerRegistration.close();
82 listenerOnPortStateRegistration.close();
86 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
87 LOG.trace("Node connectors in inventory changed: {} created, {} updated, {} removed",
88 change.getCreatedData().size(), change.getUpdatedData().size(), change.getRemovedPaths().size());
90 // Iterate over created node connectors
91 for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : change.getCreatedData().entrySet()) {
92 InstanceIdentifier<NodeConnector> nodeConnectorInstanceId =
93 entry.getKey().firstIdentifierOf(NodeConnector.class);
94 if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
95 FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
96 if (!isPortDown(flowConnector)) {
97 notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
99 iiToDownFlowCapableNodeConnectors.put(nodeConnectorInstanceId, flowConnector);
104 // Iterate over updated node connectors (port down state may change)
105 for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : change.getUpdatedData().entrySet()) {
106 InstanceIdentifier<NodeConnector> nodeConnectorInstanceId =
107 entry.getKey().firstIdentifierOf(NodeConnector.class);
108 if (compareIITail(entry.getKey(),II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
109 FlowCapableNodeConnector flowConnector = (FlowCapableNodeConnector) entry.getValue();
110 if (isPortDown(flowConnector)) {
111 notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
113 notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowConnector);
115 } else if (compareIITail(entry.getKey(),II_TO_STATE)) {
116 FlowCapableNodeConnector flowNodeConnector = iiToDownFlowCapableNodeConnectors.get(nodeConnectorInstanceId);
117 if (flowNodeConnector != null) {
118 State state = (State)entry.getValue();
119 if (!state.isLinkDown()) {
120 FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder(flowNodeConnector);
121 flowCapableNodeConnectorBuilder.setState(state);
122 notifyNodeConnectorAppeared(nodeConnectorInstanceId, flowCapableNodeConnectorBuilder.build());
123 iiToDownFlowCapableNodeConnectors.remove(nodeConnectorInstanceId);
129 // Iterate over removed node connectors
130 for (InstanceIdentifier<?> removed : change.getRemovedPaths()) {
131 if (compareIITail(removed,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
132 InstanceIdentifier<NodeConnector> nodeConnectorInstanceId = removed.firstIdentifierOf(NodeConnector.class);
133 notifyNodeConnectorDisappeared(nodeConnectorInstanceId);
140 * @param iiToFlowCapableNodeConnector
143 private boolean compareIITail(InstanceIdentifier<?> ii1,
144 InstanceIdentifier<?> ii2) {
145 return Iterables.getLast(ii1.getPathArguments()).equals(Iterables.getLast(ii2.getPathArguments()));
148 private static boolean isPortDown(FlowCapableNodeConnector flowCapableNodeConnector) {
149 PortState portState = flowCapableNodeConnector.getState();
150 PortConfig portConfig = flowCapableNodeConnector.getConfiguration();
151 return portState != null && portState.isLinkDown() ||
152 portConfig != null && portConfig.isPORTDOWN();
155 private void notifyNodeConnectorAppeared(InstanceIdentifier<NodeConnector> nodeConnectorInstanceId,
156 FlowCapableNodeConnector flowConnector) {
157 for (NodeConnectorEventsObserver observer : observers) {
158 observer.nodeConnectorAdded(nodeConnectorInstanceId, flowConnector);
162 private void notifyNodeConnectorDisappeared(InstanceIdentifier<NodeConnector> nodeConnectorInstanceId) {
163 for (NodeConnectorEventsObserver observer : observers) {
164 observer.nodeConnectorRemoved(nodeConnectorInstanceId);