package org.opendaylight.openflowplugin.openflow.md.core;
+import java.math.BigInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.openflow.md.core.session.SessionManager;
import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeper;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
this.connectionAdapter = connectionAdapter;
conductorState = CONDUCTOR_STATE.HANDSHAKING;
hsPool = Executors.newFixedThreadPool(1);
- handshakeManager = new HandshakeManagerImpl(connectionAdapter,
+ handshakeManager = new HandshakeManagerImpl(connectionAdapter,
ConnectionConductor.versionOrder.get(0), ConnectionConductor.versionOrder);
handshakeManager.setUseVersionBitmap(isBitmapNegotiationEnable);
handshakeManager.setHandshakeListener(this);
connectionAdapter.setSystemListener(this);
connectionAdapter.setConnectionReadyListener(this);
}
-
+
@Override
public void setQueueKeeper(QueueKeeper<OfHeader, DataObject> queueKeeper) {
this.queueKeeper = queueKeeper;
LOG.debug("connection is ready-to-use");
hsPool.execute(handshakeManager);
}
-
+
@Override
public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput,
Short negotiatedVersion) {
version = negotiatedVersion;
conductorState = CONDUCTOR_STATE.WORKING;
-
- OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
+ OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
+ requestDesc();
+ }
+
+ /*
+ * Send an OFPMP_DESC request message to the switch
+ */
+
+ private void requestDesc() {
+ MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
+ builder.setType(MultipartType.OFPMPDESC);
+ builder.setVersion(getVersion());
+ builder.setFlags(new MultipartRequestFlags(false));
+ builder.setMultipartRequestBody(new MultipartRequestDescBuilder().build());
+ builder.setXid(getSessionContext().getNextXid());
+ getConnectionAdapter().multipartRequest(builder.build());
}
-
+
/**
* @param isBitmapNegotiationEnable the isBitmapNegotiationEnable to set
*/
boolean isBitmapNegotiationEnable) {
this.isBitmapNegotiationEnable = isBitmapNegotiationEnable;
}
-
+
protected void shutdownPool() {
hsPool.shutdownNow();
LOG.debug("pool is terminated: {}", hsPool.isTerminated());
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.openflowplugin.openflow.md.core.translator.ErrorTranslator;
import org.opendaylight.openflowplugin.openflow.md.core.translator.ExperimenterTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.translator.MultiPartMessageDescToNodeUpdatedTranslator;
import org.opendaylight.openflowplugin.openflow.md.core.translator.PacketInTranslator;
import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
- addMessageTranslator(ExperimenterMessage.class, OF10, new ExperimenterTranslator());
+ addMessageTranslator(MultipartReplyMessage.class,OF13, new MultiPartMessageDescToNodeUpdatedTranslator());
+ addMessageTranslator(ExperimenterMessage.class, OF10, new ExperimenterTranslator());
//TODO: move registration to factory
NotificationPopListener<DataObject> notificationPopListener = new NotificationPopListener<DataObject>();
addMessagePopListener(PacketReceived.class,notificationPopListener);
addMessagePopListener(TransmitPacketInput.class, notificationPopListener);
+ addMessagePopListener(NodeUpdated.class, notificationPopListener);
// Push the updated Listeners to Session Manager which will be then picked up by ConnectionConductor eventually
OFSessionUtil.getSessionManager().setTranslatorMapping(messageTranslators);
this.providerContext = session;
this.publishService = session.getSALService(NotificationProviderService.class);
this.dataService = session.getSALService(DataProviderService.class);
-
// We register as listener for Session Manager
getSessionManager().registerSessionListener(this);
getSessionManager().setNotificationProviderService(publishService);
}
public static InstanceIdentifier<Node> identifierFromDatapathId(BigInteger datapathId) {
- InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
-
NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
- return builder.node(Node.class, nodeKey).toInstance();
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder(Node.class,nodeKey);
+ return (InstanceIdentifier<Node>) builder.toInstance();
}
public static NodeKey nodeKeyFromDatapathId(BigInteger datapathId) {
--- /dev/null
+package org.opendaylight.openflowplugin.openflow.md.core.translator;
+
+import java.math.BigInteger;
+
+import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDesc;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultiPartMessageDescToNodeUpdatedTranslator implements IMDMessageTranslator<OfHeader, DataObject> {
+ protected static final Logger LOG = LoggerFactory.getLogger(PacketInTranslator.class);
+ @Override
+ public NodeUpdated translate(SwitchConnectionDistinguisher cookie,
+ SessionContext sc, OfHeader msg) {
+ if(msg instanceof MultipartReply && ((MultipartReply) msg).getType() == MultipartType.OFPMPDESC) {
+ LOG.info("MultipartReplyMessage Being translated to NodeUpdated ");
+ MultipartReplyMessage message = (MultipartReplyMessage) msg;
+ BigInteger datapathId = sc.getFeatures().getDatapathId();
+ NodeUpdatedBuilder builder = InventoryDataServiceUtil.nodeUpdatedBuilderFromDataPathId(datapathId);
+ FlowCapableNodeUpdatedBuilder fnub = new FlowCapableNodeUpdatedBuilder();
+ MultipartReplyDesc body = (MultipartReplyDesc) message.getMultipartReplyBody();
+ fnub.setHardware(body.getHwDesc());
+ fnub.setManufacturer(body.getMfrDesc());
+ fnub.setSerialNumber(body.getSerialNum());
+ fnub.setDescription(body.getDpDesc());
+ fnub.setSoftware(body.getSwDesc());
+ builder.addAugmentation(FlowCapableNodeUpdated.class, fnub.build());
+ return builder.build();
+ } else {
+ return null;
+ }
+ }
+
+}
--- /dev/null
+package org.opendaylight.openflowplugin.openflow.md.util;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InventoryDataServiceUtil {
+ private final static Logger LOG = LoggerFactory.getLogger(InventoryDataServiceUtil.class);
+ /*
+ * Get an InstanceIdentifier for the Nodes class that is the root of the inventory tree
+ * We use this alot, so its worth keeping around
+ */
+ private InstanceIdentifier<Nodes> nodesIdentifier = InstanceIdentifier.builder().node(Nodes.class).toInstance();
+
+ /*
+ * The DataProviderService is how we access the DataTree
+ */
+ private DataProviderService dataService;
+
+ public InventoryDataServiceUtil(DataProviderService dataService) {
+ // Save the dataService
+ this.dataService = dataService;
+ }
+
+ public List<Node> readAllNodes() {
+ Nodes nodes = (Nodes) dataService.readOperationalData(nodesIdentifier);
+ return nodes.getNode();
+ }
+
+ public Node readNode(InstanceIdentifier<Node> instance) {
+ return (Node) dataService.readOperationalData(instance);
+ }
+
+ public Node readNode(NodeRef nodeRef) {
+ return readNode((InstanceIdentifier<Node>) nodeRef.getValue());
+ }
+
+ public Node readNode(NodeKey nodeKey) {
+ return readNode(nodeKeyToInstanceIdentifier(nodeKey));
+ }
+
+ public Node readNode(NodeId nodeId) {
+ return readNode(new NodeKey(nodeId));
+ }
+
+
+ public Node readNodeByDataPath(BigInteger datapathId) {
+ return (Node) dataService.readOperationalData(identifierFromDatapathId(datapathId));
+ }
+
+ public void putNode(Node node) {
+ DataModificationTransaction transaction = dataService.beginTransaction();
+ transaction.putOperationalData(nodesIdentifier, node);
+ transaction.commit();
+ }
+
+ public void putNodeConnector(InstanceIdentifier<Node> instance,NodeConnector nodeConnector) {
+ DataModificationTransaction transaction = dataService.beginTransaction();
+ transaction.putOperationalData(instance, nodeConnector);
+ transaction.commit();
+ }
+
+ public void putNodeConnector(NodeKey nodeKey,NodeConnector nodeConnector) {
+ InstanceIdentifier<Node> instance = nodeKeyToInstanceIdentifier(nodeKey);
+ putNodeConnector(instance,nodeConnector);
+ }
+
+
+
+ public void putNodeConnector(NodeId nodeId,NodeConnector nodeConnector) {
+ putNodeConnector(new NodeKey(nodeId),nodeConnector);
+ }
+
+ public void putNodeConnector(BigInteger datapathId, NodeConnector nodeConnector) {
+ putNodeConnector(new NodeId("openflow:" + datapathId),nodeConnector);
+ }
+
+ public static InstanceIdentifier<Node> identifierFromDatapathId(BigInteger datapathId) {
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+
+ NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
+ return builder.node(Node.class, nodeKey).toInstance();
+ }
+
+ public static NodeKey nodeKeyFromDatapathId(BigInteger datapathId) {
+ return new NodeKey(nodeIdFromDatapathId(datapathId));
+ }
+
+ public static NodeUpdatedBuilder nodeUpdatedBuilderFromDataPathId(BigInteger datapathId) {
+ NodeUpdatedBuilder builder = new NodeUpdatedBuilder();
+ builder.setId(nodeIdFromDatapathId(datapathId));
+ builder.setNodeRef(nodeRefFromNodeKey(new NodeKey(builder.getId())));
+ return builder;
+ }
+
+ public static NodeId nodeIdFromDatapathId(BigInteger datapathId) {
+ // FIXME: Convert to textual representation of datapathID
+ String current = datapathId.toString();
+ return new NodeId("openflow:" + current);
+ }
+
+ public static NodeRef nodeRefFromNode(Node node) {
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+ return new NodeRef(builder.node(Node.class,node.getKey()).toInstance());
+ }
+
+ public static NodeRef nodeRefFromNodeKey(NodeKey nodeKey) {
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+ return new NodeRef(builder.node(Node.class,nodeKey).toInstance());
+ }
+
+ public static InstanceIdentifier<Node> nodeKeyToInstanceIdentifier(NodeKey nodeKey) {
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+ InstanceIdentifier<Node> instance = builder.node(Node.class,nodeKey).toInstance();
+ return instance;
+ }
+
+}