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.OFConstants;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.session.PortFeaturesUtil;
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.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.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatus;
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.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDescCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupFeaturesCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterFeaturesCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortDescCaseBuilder;
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;
* it will help while testing and isolating issues related to processing of
* BitMaps from switches.
*/
- protected boolean isBitmapNegotiationEnable = true;
+ private boolean isBitmapNegotiationEnable = true;
protected ErrorHandler errorHandler;
private final ConnectionAdapter connectionAdapter;
private SessionContext sessionContext;
- protected boolean isFirstHelloNegotiation = true;
- protected Short lastProposedVersion = null;
-
private QueueKeeper<OfHeader, DataObject> queueKeeper;
private ExecutorService hsPool;
private HandshakeManager handshakeManager;
+ private boolean firstHelloProcessed;
+
+ private PortFeaturesUtil portFeaturesUtils;
+
/**
* @param connectionAdapter
*/
this.connectionAdapter = connectionAdapter;
conductorState = CONDUCTOR_STATE.HANDSHAKING;
hsPool = Executors.newFixedThreadPool(1);
+ firstHelloProcessed = false;
handshakeManager = new HandshakeManagerImpl(connectionAdapter,
ConnectionConductor.versionOrder.get(0), ConnectionConductor.versionOrder);
handshakeManager.setUseVersionBitmap(isBitmapNegotiationEnable);
handshakeManager.setHandshakeListener(this);
+ portFeaturesUtils = PortFeaturesUtil.getInstance();
}
@Override
*/
@Override
public synchronized void onHelloMessage(final HelloMessage hello) {
- LOG.debug("processing HELLO.xid{}", hello.getXid());
+ LOG.debug("processing HELLO.xid: {}", hello.getXid());
+ firstHelloProcessed = true;
checkState(CONDUCTOR_STATE.HANDSHAKING);
- handshakeManager.setReceivedHello(hello);
- hsPool.execute(handshakeManager);
+ HandshakeStepWrapper handshakeStepWrapper = new HandshakeStepWrapper(
+ hello, handshakeManager, connectionAdapter);
+ hsPool.execute(handshakeStepWrapper);
}
/**
@Override
public void onPacketInMessage(PacketInMessage message) {
- queueKeeper.push(message, this);
+ queueKeeper.push(message, this, QueueKeeper.QueueType.UNORDERED);
}
@Override
public void onPortStatusMessage(PortStatusMessage message) {
- this.getSessionContext().processPortStatusMsg(message);
+ processPortStatusMsg(message);
queueKeeper.push(message, this);
}
+
+ protected void processPortStatusMsg(PortStatus msg) {
+ if (msg.getReason().getIntValue() == 2) {
+ updatePort(msg);
+ } else if (msg.getReason().getIntValue() == 0) {
+ updatePort(msg);
+ } else if (msg.getReason().getIntValue() == 1) {
+ deletePort(msg);
+ }
+ }
+
+ protected void updatePort(PortStatus msg) {
+ Long portNumber = msg.getPortNo();
+ Boolean portBandwidth = portFeaturesUtils.getPortBandwidth(msg);
+
+ if(portBandwidth == null) {
+ LOG.warn("can't get bandwidth info from port: {}, aborting port update", msg.toString());
+ } else {
+ this.getSessionContext().getPhysicalPorts().put(portNumber, msg);
+ this.getSessionContext().getPortsBandwidth().put(portNumber, portBandwidth);
+ }
+ }
+
+ protected void deletePort(Port port) {
+ Long portNumber = port.getPortNo();
+
+ this.getSessionContext().getPhysicalPorts().remove(portNumber);
+ this.getSessionContext().getPortsBandwidth().remove(portNumber);
+ }
@Override
public void onSwitchIdleEvent(SwitchIdleEvent notification) {
}
} catch (Exception e) {
LOG.error("while waiting for echoReply in TIMEOUTING state: "
- + e.getMessage(), e);
+ + e.getMessage());
+ errorHandler.handleException(e, sessionContext);
//switch is not responding
disconnect();
OFSessionUtil.getSessionManager().invalidateOnDisconnect(ConnectionConductorImpl.this);
}
@Override
- public void onConnectionReady() {
+ public synchronized void onConnectionReady() {
LOG.debug("connection is ready-to-use");
- hsPool.execute(handshakeManager);
+ if (! firstHelloProcessed) {
+ HandshakeStepWrapper handshakeStepWrapper = new HandshakeStepWrapper(
+ null, handshakeManager, connectionAdapter);
+ hsPool.execute(handshakeStepWrapper);
+ firstHelloProcessed = true;
+ } else {
+ LOG.debug("already touched by hello message");
+ }
}
@Override
conductorState = CONDUCTOR_STATE.WORKING;
OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
requestDesc();
+ requestPorts();
+ if(version == OFConstants.OFP_VERSION_1_3){
+ requestGroupFeatures();
+ requestMeterFeatures();
+ }
}
/*
builder.setType(MultipartType.OFPMPDESC);
builder.setVersion(getVersion());
builder.setFlags(new MultipartRequestFlags(false));
- builder.setMultipartRequestBody(new MultipartRequestDescBuilder().build());
+ builder.setMultipartRequestBody(new MultipartRequestDescCaseBuilder().build());
builder.setXid(getSessionContext().getNextXid());
getConnectionAdapter().multipartRequest(builder.build());
}
+ private void requestPorts() {
+ MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
+ builder.setType(MultipartType.OFPMPPORTDESC);
+ builder.setVersion(getVersion());
+ builder.setFlags(new MultipartRequestFlags(false));
+ builder.setMultipartRequestBody(new MultipartRequestPortDescCaseBuilder().build());
+ builder.setXid(getSessionContext().getNextXid());
+ getConnectionAdapter().multipartRequest(builder.build());
+ }
+ private void requestGroupFeatures(){
+ MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
+ mprInput.setType(MultipartType.OFPMPGROUPFEATURES);
+ mprInput.setVersion(getVersion());
+ mprInput.setFlags(new MultipartRequestFlags(false));
+ mprInput.setXid(getSessionContext().getNextXid());
+
+ MultipartRequestGroupFeaturesCaseBuilder mprGroupFeaturesBuild =
+ new MultipartRequestGroupFeaturesCaseBuilder();
+ mprInput.setMultipartRequestBody(mprGroupFeaturesBuild.build());
+
+ LOG.debug("Send group features statistics request :{}",mprGroupFeaturesBuild);
+ getConnectionAdapter().multipartRequest(mprInput.build());
+
+ }
+ private void requestMeterFeatures(){
+ MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
+ mprInput.setType(MultipartType.OFPMPMETERFEATURES);
+ mprInput.setVersion(getVersion());
+ mprInput.setFlags(new MultipartRequestFlags(false));
+ mprInput.setXid(getSessionContext().getNextXid());
+
+ MultipartRequestMeterFeaturesCaseBuilder mprMeterFeaturesBuild =
+ new MultipartRequestMeterFeaturesCaseBuilder();
+ mprInput.setMultipartRequestBody(mprMeterFeaturesBuild.build());
+
+ LOG.debug("Send meter features statistics request :{}",mprMeterFeaturesBuild);
+ getConnectionAdapter().multipartRequest(mprInput.build());
+
+ }
/**
* @param isBitmapNegotiationEnable the isBitmapNegotiationEnable to set
*/