import org.slf4j.LoggerFactory;
/**
- * learning switch activator
- * <p>
+ * Learning switch activator
* Activator is derived from AbstractBindingAwareConsumer, which takes care
* of looking up MD-SAL in Service Registry and registering consumer
* when MD-SAL is present.
public class Activator extends AbstractBindingAwareConsumer implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(Activator.class);
-
private LearningSwitchManager learningSwitch;
-
@Override
protected void startImpl(BundleContext context) {
LOG.info("startImpl() passing");
* We create instance of our LearningSwitchManager
* and set all required dependencies,
*
- * which are
+ * which are
* Data Broker (data storage service) - for configuring flows and reading stored switch state
* PacketProcessingService - for sending out packets
* NotificationService - for receiving notifications such as packet in.
- *
*/
learningSwitch = new LearningSwitchManagerMultiImpl();
learningSwitch.setDataBroker(session.getSALService(DataBroker.class));
package org.opendaylight.openflowplugin.learningswitch;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
- *
+ * Holder for {@link org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener} registration.
*/
-public interface DataChangeListenerRegistrationHolder {
+public interface DataTreeChangeListenerRegistrationHolder {
/**
- * @return the dataChangeListenerRegistration
+ * @return the DataTreeChangeListenerRegistration
*/
- ListenerRegistration<DataChangeListener> getDataChangeListenerRegistration();
+ ListenerRegistration<DataTreeChangeListener> getDataTreeChangeListenerRegistration();
}
package org.opendaylight.openflowplugin.learningswitch;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
-
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-import com.google.common.collect.ImmutableList;
-
public class FlowUtils {
private FlowUtils() {
//prohibite to instantiate util class
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
public class InstanceIdentifierUtils {
private InstanceIdentifierUtils() {
return nodeChild.firstIdentifierOf(Node.class);
}
-
/**
* Creates a table path by appending table specific location to node path
*
/**
* Extracts NodeConnectorKey from node connector path.
- *
*/
public static NodeConnectorKey getNodeConnectorKey(final InstanceIdentifier<?> nodeConnectorPath) {
return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
}
-
- //
public static final InstanceIdentifier<NodeConnector> createNodeConnectorPath(final InstanceIdentifier<Node> nodeKey,final NodeConnectorKey nodeConnectorKey) {
return nodeKey.child(NodeConnector.class,nodeConnectorKey);
}
/**
* @param registrationPublisher the registrationPublisher to set
*/
- void setRegistrationPublisher(DataChangeListenerRegistrationHolder registrationPublisher);
+ void setRegistrationPublisher(DataTreeChangeListenerRegistrationHolder registrationPublisher);
}
/**
* Simple Learning Switch implementation which does mac learning for one switch.
- *
- *
*/
public class LearningSwitchHandlerSimpleImpl implements LearningSwitchHandler, PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(LearningSwitchHandlerSimpleImpl.class);
-
private static final byte[] ETH_TYPE_IPV4 = new byte[] { 0x08, 0x00 };
-
private static final int DIRECT_FLOW_PRIORITY = 512;
- private DataChangeListenerRegistrationHolder registrationPublisher;
+ private DataTreeChangeListenerRegistrationHolder registrationPublisher;
private FlowCommitWrapper dataStoreAccessor;
private PacketProcessingService packetProcessingService;
// disable listening - simple learning handles only one node (switch)
if (registrationPublisher != null) {
try {
- LOG.debug("closing dataChangeListenerRegistration");
- registrationPublisher.getDataChangeListenerRegistration().close();
+ LOG.debug("closing dataTreeChangeListenerRegistration");
+ registrationPublisher.getDataTreeChangeListenerRegistration().close();
} catch (Exception e) {
LOG.warn("closing registration upon flowCapable node update listener failed: {}", e.getMessage());
LOG.debug("closing registration upon flowCapable node update listener failed.. ", e);
}
@Override
- public void setRegistrationPublisher(DataChangeListenerRegistrationHolder registrationPublisher) {
+ public void setRegistrationPublisher(DataTreeChangeListenerRegistrationHolder registrationPublisher) {
this.registrationPublisher = registrationPublisher;
}
package org.opendaylight.openflowplugin.learningswitch;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
* corresponding MACs)</li>
* </ul>
*/
-public class LearningSwitchManagerSimpleImpl implements DataChangeListenerRegistrationHolder,
- LearningSwitchManager {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(LearningSwitchManagerSimpleImpl.class);
+public class LearningSwitchManagerSimpleImpl implements DataTreeChangeListenerRegistrationHolder, LearningSwitchManager {
+ private static final Logger LOG = LoggerFactory.getLogger(LearningSwitchManagerSimpleImpl.class);
private NotificationService notificationService;
private PacketProcessingService packetProcessingService;
private DataBroker data;
-
private Registration packetInRegistration;
-
- private ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ private ListenerRegistration<DataTreeChangeListener> dataTreeChangeListenerRegistration;
/**
* @param notificationService the notificationService to set
WakeupOnNode wakeupListener = new WakeupOnNode();
wakeupListener.setLearningSwitchHandler(learningSwitchHandler);
- dataChangeListenerRegistration = data.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(Nodes.class)
- .child(Node.class)
- .augmentation(FlowCapableNode.class)
- .child(Table.class).build(),
- wakeupListener,
- DataBroker.DataChangeScope.SUBTREE);
+ final InstanceIdentifier<Table> instanceIdentifier = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class)
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class);
+ final DataTreeIdentifier<Table> dataTreeIdentifier = new DataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ dataTreeChangeListenerRegistration = data.registerDataTreeChangeListener(dataTreeIdentifier, wakeupListener);
LOG.debug("start() <--");
}
LOG.debug("closing packetInRegistration failed..", e);
}
try {
- dataChangeListenerRegistration.close();
+ dataTreeChangeListenerRegistration.close();
} catch (Exception e) {
- LOG.warn("failed to close dataChangeListenerRegistration: {}", e.getMessage());
- LOG.debug("failed to close dataChangeListenerRegistration..", e);
+ LOG.warn("failed to close dataTreeChangeListenerRegistration: {}", e.getMessage());
+ LOG.debug("failed to close dataTreeChangeListenerRegistration..", e);
}
LOG.debug("stop() <--");
}
-
@Override
- public ListenerRegistration<DataChangeListener> getDataChangeListenerRegistration() {
- return dataChangeListenerRegistration;
+ public ListenerRegistration<DataTreeChangeListener> getDataTreeChangeListenerRegistration() {
+ return dataTreeChangeListenerRegistration;
}
}
package org.opendaylight.openflowplugin.learningswitch;
-import java.util.Map;
-import java.util.Map.Entry;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
*
*/
-public class WakeupOnNode implements DataChangeListener {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(WakeupOnNode.class);
+public class WakeupOnNode implements DataTreeChangeListener<Table> {
+ private static final Logger LOG = LoggerFactory.getLogger(WakeupOnNode.class);
private LearningSwitchHandler learningSwitchHandler;
@Override
- public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Table>> modifications) {
Short requiredTableId = 0;
-
// TODO add flow
- Map<InstanceIdentifier<?>, DataObject> updated = change.getUpdatedData();
- for (Entry<InstanceIdentifier<?>, DataObject> updateItem : updated.entrySet()) {
- DataObject table = updateItem.getValue();
- if (table instanceof Table) {
- Table tableSure = (Table) table;
- LOG.trace("table: {}", table);
-
- if (requiredTableId.equals(tableSure.getId())) {
- @SuppressWarnings("unchecked")
- InstanceIdentifier<Table> tablePath = (InstanceIdentifier<Table>) updateItem.getKey();
- learningSwitchHandler.onSwitchAppeared(tablePath);
+ for (DataTreeModification modification : modifications) {
+ if (modification.getRootNode().getModificationType() == ModificationType.SUBTREE_MODIFIED) {
+ DataObject table = modification.getRootNode().getDataAfter();
+ if (table instanceof Table) {
+ Table tableSure = (Table) table;
+ LOG.trace("table: {}", table);
+
+ if (requiredTableId.equals(tableSure.getId())) {
+ InstanceIdentifier<Table> tablePath = (InstanceIdentifier<Table>) modification.getRootPath().getRootIdentifier();
+ learningSwitchHandler.onSwitchAppeared(tablePath);
+ }
}
}
}
package org.opendaylight.openflowplugin.learningswitch.multi;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.NotificationService;
-import org.opendaylight.openflowplugin.learningswitch.DataChangeListenerRegistrationHolder;
+import org.opendaylight.openflowplugin.learningswitch.DataTreeChangeListenerRegistrationHolder;
import org.opendaylight.openflowplugin.learningswitch.FlowCommitWrapper;
import org.opendaylight.openflowplugin.learningswitch.FlowCommitWrapperImpl;
import org.opendaylight.openflowplugin.learningswitch.LearningSwitchManager;
* corresponding MACs)</li>
* </ul>
*/
-public class LearningSwitchManagerMultiImpl implements DataChangeListenerRegistrationHolder,
- LearningSwitchManager {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(LearningSwitchManagerMultiImpl.class);
+public class LearningSwitchManagerMultiImpl implements DataTreeChangeListenerRegistrationHolder, LearningSwitchManager {
+ private static final Logger LOG = LoggerFactory.getLogger(LearningSwitchManagerMultiImpl.class);
private NotificationService notificationService;
private PacketProcessingService packetProcessingService;
private DataBroker data;
-
private Registration packetInRegistration;
-
- private ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ private ListenerRegistration<DataTreeChangeListener> dataTreeChangeListenerRegistration;
/**
* @param notificationService the notificationService to set
WakeupOnNode wakeupListener = new WakeupOnNode();
wakeupListener.setLearningSwitchHandler(learningSwitchHandler);
- dataChangeListenerRegistration = data.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(Nodes.class)
- .child(Node.class)
- .augmentation(FlowCapableNode.class)
- .child(Table.class).build(),
- wakeupListener,
- DataBroker.DataChangeScope.SUBTREE);
+ final InstanceIdentifier<Table> instanceIdentifier = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class)
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class);
+ final DataTreeIdentifier<Table> dataTreeIdentifier = new DataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ dataTreeChangeListenerRegistration = data.registerDataTreeChangeListener(dataTreeIdentifier, wakeupListener);
LOG.debug("start() <--");
}
LOG.debug("Error unregistering packet in listener.. ", e);
}
try {
- dataChangeListenerRegistration.close();
+ dataTreeChangeListenerRegistration.close();
} catch (Exception e) {
LOG.warn("Error unregistering data change listener: {}", e.getMessage());
LOG.debug("Error unregistering data change listener.. ", e);
@Override
- public ListenerRegistration<DataChangeListener> getDataChangeListenerRegistration() {
- return dataChangeListenerRegistration;
+ public ListenerRegistration<DataTreeChangeListener> getDataTreeChangeListenerRegistration() {
+ return dataTreeChangeListenerRegistration;
}
}
package org.opendaylight.openflowplugin.learningswitch.multi;
-import org.opendaylight.openflowplugin.learningswitch.DataChangeListenerRegistrationHolder;
-import org.opendaylight.openflowplugin.learningswitch.InstanceIdentifierUtils;
+import org.opendaylight.openflowplugin.learningswitch.DataTreeChangeListenerRegistrationHolder;
import org.opendaylight.openflowplugin.learningswitch.FlowCommitWrapper;
+import org.opendaylight.openflowplugin.learningswitch.InstanceIdentifierUtils;
import org.opendaylight.openflowplugin.learningswitch.LearningSwitchHandler;
import org.opendaylight.openflowplugin.learningswitch.LearningSwitchHandlerSimpleImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- *
- */
public class MultipleLearningSwitchHandlerFacadeImpl implements LearningSwitchHandler {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(MultipleLearningSwitchHandlerFacadeImpl.class);
-
+
+ private static final Logger LOG = LoggerFactory.getLogger(MultipleLearningSwitchHandlerFacadeImpl.class);
private FlowCommitWrapper dataStoreAccessor;
private PacketProcessingService packetProcessingService;
private PacketInDispatcherImpl packetInDispatcher;
@Override
public synchronized void onSwitchAppeared(InstanceIdentifier<Table> appearedTablePath) {
LOG.debug("expected table acquired, learning ..");
-
+
/**
* appearedTablePath is in form of /nodes/node/node-id/table/table-id
* so we shorten it to /nodes/node/node-id to get identifier of switch.
- *
*/
InstanceIdentifier<Node> nodePath = InstanceIdentifierUtils.getNodePath(appearedTablePath);
-
+
/**
* We check if we already initialized dispatcher for that node,
* if not we create new handler for switch.
- *
*/
if (!packetInDispatcher.getHandlerMapping().containsKey(nodePath)) {
- // delegate this node (owning appearedTable) to SimpleLearningSwitchHandler
+ // delegate this node (owning appearedTable) to SimpleLearningSwitchHandler
LearningSwitchHandlerSimpleImpl simpleLearningSwitch = new LearningSwitchHandlerSimpleImpl();
/**
* We set runtime dependencies
*/
simpleLearningSwitch.setDataStoreAccessor(dataStoreAccessor);
simpleLearningSwitch.setPacketProcessingService(packetProcessingService);
-
+
/**
* We propagate table event to newly instantiated instance of learning switch
*/
@Override
public void setRegistrationPublisher(
- DataChangeListenerRegistrationHolder registrationPublisher) {
+ DataTreeChangeListenerRegistrationHolder registrationPublisher) {
//NOOP
}
-
+
@Override
public void setDataStoreAccessor(FlowCommitWrapper dataStoreAccessor) {
this.dataStoreAccessor = dataStoreAccessor;
}
-
+
@Override
public void setPacketProcessingService(
PacketProcessingService packetProcessingService) {
import java.util.HashMap;
import java.util.Map;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-/**
- *
- */
public class PacketInDispatcherImpl implements PacketProcessingListener {
-
+
private Map<InstanceIdentifier<Node>, PacketProcessingListener> handlerMapping;
-
+
/**
* default constructor
*/
/**
* Notification contains reference to ingress port
* in a form of path in inventory: /nodes/node/node-connector
- *
+ *
* In order to get path we shorten path to the first node reference
* by using firstIdentifierOf helper method provided by InstanceIdentifier,
* this will effectively shorten the path to /nodes/node.
- *
*/
InstanceIdentifier<?> ingressPort = notification.getIngress().getValue();
InstanceIdentifier<Node> nodeOfPacket = ingressPort.firstIdentifierOf(Node.class);
/**
* We lookup up the the packet-in listener for this node.
- *
*/
PacketProcessingListener nodeHandler = handlerMapping.get(nodeOfPacket);
-
+
/**
- *
* If we have packet-processing listener, we delegate notification.
- *
*/
if (nodeHandler != null) {
nodeHandler.onPacketReceived(notification);
}
}
-
+
/**
* @return the handlerMapping
*/
*/
package org.opendaylight.openflowplugin.openflow.samples.consumer;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+import java.util.Collection;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
public class SimpleDropFirewall {
private ConsumerContext context;
private SalFlowService flowService;
- private DataChangeListener listener = new NodeListener();
- private DataBrokerService data;
-
+ private DataTreeChangeListener listener = new NodeListener();
+ private DataBrokerService data;
+
public void setContext(ConsumerContext session) {
this.context = session;
}
return result.get(5, TimeUnit.SECONDS).isSuccessful();
}
-
- private class NodeListener implements DataChangeListener {
-
-
+
+ private class NodeListener implements DataTreeChangeListener<Node> {
@Override
- public void onDataChanged(
- DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-
- Map<InstanceIdentifier<?>, DataObject> updated = change.getUpdatedConfigurationData();
- Set<Entry<InstanceIdentifier<?>, DataObject>> set = updated.entrySet();
- for (Entry<InstanceIdentifier<?>, DataObject> entry : set) {
- Class<?> changedObjectType = entry.getKey().getTargetType();
- if(Node.class.equals(changedObjectType)) {
- // We now that this is node updated
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> modifications) {
+ for (DataTreeModification modification : modifications) {
+ if (modification.getRootNode().getModificationType() == ModificationType.SUBTREE_MODIFIED) {
+ // node updated
}
}
}