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.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.MultipartRequestMessage;
+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.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.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);
- handshakeManager = new HandshakeManagerImpl(connectionAdapter,
+ firstHelloProcessed = false;
+ handshakeManager = new HandshakeManagerImpl(connectionAdapter,
ConnectionConductor.versionOrder.get(0), ConnectionConductor.versionOrder);
handshakeManager.setUseVersionBitmap(isBitmapNegotiationEnable);
handshakeManager.setHandshakeListener(this);
+ portFeaturesUtils = PortFeaturesUtil.getInstance();
}
@Override
connectionAdapter.setSystemListener(this);
connectionAdapter.setConnectionReadyListener(this);
}
-
+
@Override
public void setQueueKeeper(QueueKeeper<OfHeader, DataObject> queueKeeper) {
this.queueKeeper = queueKeeper;
@Override
public void onErrorMessage(ErrorMessage errorMessage) {
- queueKeeper.push(ErrorMessage.class, errorMessage, this);
+ queueKeeper.push(errorMessage, this);
}
@Override
public void onExperimenterMessage(ExperimenterMessage experimenterMessage) {
- queueKeeper.push(ExperimenterMessage.class, experimenterMessage, this);
+ queueKeeper.push(experimenterMessage, this);
}
@Override
public void onFlowRemovedMessage(FlowRemovedMessage message) {
- queueKeeper.push(FlowRemovedMessage.class, message, this);
+ queueKeeper.push(message, this);
}
*/
@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 onMultipartReplyMessage(MultipartReplyMessage message) {
- queueKeeper.push(MultipartReplyMessage.class, message, this);
- }
-
- @Override
- public void onMultipartRequestMessage(MultipartRequestMessage message) {
- queueKeeper.push(MultipartRequestMessage.class, message, this);
+ queueKeeper.push(message, this);
}
@Override
public void onPacketInMessage(PacketInMessage message) {
- queueKeeper.push(PacketInMessage.class, message, this);
+ queueKeeper.push(message, this, QueueKeeper.QueueType.UNORDERED);
}
@Override
public void onPortStatusMessage(PortStatusMessage message) {
- this.getSessionContext().processPortStatusMsg(message);
- queueKeeper.push(PortStatusMessage.class, message, this);
+ 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
}
} 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
public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput,
Short negotiatedVersion) {
version = negotiatedVersion;
conductorState = CONDUCTOR_STATE.WORKING;
+ OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
+ requestDesc();
+ requestPorts();
+ if(version == OFConstants.OFP_VERSION_1_3){
+ requestGroupFeatures();
+ requestMeterFeatures();
+ }
+ }
+
+ /*
+ * 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 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());
- OFSessionUtil.registerSession(this, featureOutput, negotiatedVersion);
}
-
/**
* @param isBitmapNegotiationEnable the isBitmapNegotiationEnable to set
*/
boolean isBitmapNegotiationEnable) {
this.isBitmapNegotiationEnable = isBitmapNegotiationEnable;
}
-
+
protected void shutdownPool() {
hsPool.shutdownNow();
LOG.debug("pool is terminated: {}", hsPool.isTerminated());