import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.ConnectionException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
private Short version;
private ErrorHandler errorHandler;
- private long maxTimeout = 1000;
+ private long maxTimeout = 8000;
private TimeUnit maxTimeoutUnit = TimeUnit.MILLISECONDS;
private Short highestVersion;
}
@Override
- public synchronized void run() {
- LOG.info("handshake STARTED");
- setActiveXid(20L);
- HelloMessage receivedHelloLoc = receivedHello;
-
- if (receivedHelloLoc == null) {
- // first Hello sending
- sendHelloMessage(highestVersion, getNextXid());
- lastProposedVersion = highestVersion;
- LOG.debug("ret - firstHello+wait");
+ public void shake() {
+
+ if (version != null) {
+ // Some switches respond with a second HELLO acknowledging our HELLO
+ // but we've already completed the handshake based on the negotiated
+ // version and have registered this switch.
+ LOG.debug("Hello recieved after handshake already settled ... ignoring.");
return;
}
-
- // process the 2. and later hellos
- Short remoteVersion = receivedHelloLoc.getVersion();
- List<Elements> elements = receivedHelloLoc.getElements();
- setActiveXid(receivedHelloLoc.getXid());
- List<Boolean> remoteVersionBitmap = MessageFactory.digVersions(elements);
- LOG.debug("Hello message: version={}, bitmap={}, xid={}", remoteVersion,
- remoteVersionBitmap, receivedHelloLoc.getXid());
+
+ LOG.trace("handshake STARTED");
+ setActiveXid(20L);
+ HelloMessage receivedHelloLoc = receivedHello;
try {
+ if (receivedHelloLoc == null) {
+ // first Hello sending
+ sendHelloMessage(highestVersion, getNextXid());
+ lastProposedVersion = highestVersion;
+ LOG.trace("ret - firstHello+wait");
+ return;
+ }
+
+ // process the 2. and later hellos
+ Short remoteVersion = receivedHelloLoc.getVersion();
+ List<Elements> elements = receivedHelloLoc.getElements();
+ setActiveXid(receivedHelloLoc.getXid());
+ List<Boolean> remoteVersionBitmap = MessageFactory.digVersions(elements);
+ LOG.debug("Hello message: version={}, bitmap={}, xid={}", remoteVersion,
+ remoteVersionBitmap, receivedHelloLoc.getXid());
+
if (useVersionBitmap && remoteVersionBitmap != null) {
// versionBitmap on both sides -> ONE STEP DECISION
handleVersionBitmapNegotiation(elements);
} catch (Exception ex) {
errorHandler.handleException(ex, null);
connectionAdapter.disconnect();
- LOG.debug("ret - "+ex.getMessage());
+ LOG.trace("ret - shake fail: {}", ex.getMessage());
}
}
/**
* @param remoteVersion
+ * @throws Exception
*/
- private void handleStepByStepVersionNegotiation(Short remoteVersion) {
+ private void handleStepByStepVersionNegotiation(Short remoteVersion) throws Exception {
LOG.debug("remoteVersion:{} lastProposedVersion:{}, highestVersion:{}",
remoteVersion, lastProposedVersion, highestVersion);
+
+ if (lastProposedVersion == null) {
+ // first hello has not been sent yet, send it and either wait for next remote
+ // version or proceed
+ lastProposedVersion = proposeNextVersion(remoteVersion);
+ sendHelloMessage(lastProposedVersion, getNextXid());
+ }
+
if (remoteVersion == lastProposedVersion) {
postHandshake(lastProposedVersion, getNextXid());
- LOG.debug("ret - OK - switch answered with lastProposedVersion");
+ LOG.trace("ret - OK - switch answered with lastProposedVersion");
} else {
checkNegotiationStalling(remoteVersion);
if (remoteVersion > (lastProposedVersion == null ? highestVersion : lastProposedVersion)) {
// wait for next version
- LOG.debug("ret - wait");
+ LOG.trace("ret - wait");
} else {
//propose lower version
handleLowerVersionProposal(remoteVersion);
/**
* @param remoteVersion
+ * @throws Exception
*/
- private void handleLowerVersionProposal(Short remoteVersion) {
+ private void handleLowerVersionProposal(Short remoteVersion) throws Exception {
Short proposedVersion;
// find the version from header version field
proposedVersion = proposeNextVersion(remoteVersion);
sendHelloMessage(proposedVersion, getNextXid());
if (proposedVersion != remoteVersion) {
- LOG.debug("ret - sent+wait");
+ LOG.trace("ret - sent+wait");
} else {
- LOG.debug("ret - sent+OK");
+ LOG.trace("ret - sent+OK");
postHandshake(proposedVersion, getNextXid());
}
}
/**
* @param elements
+ * @throws Exception
*/
- private void handleVersionBitmapNegotiation(List<Elements> elements) {
+ private void handleVersionBitmapNegotiation(List<Elements> elements) throws Exception {
Short proposedVersion;
proposedVersion = proposeCommonBitmapVersion(elements);
+ if (lastProposedVersion == null) {
+ // first hello has not been sent yet
+ sendHelloMessage(proposedVersion, getNextXid());
+ }
postHandshake(proposedVersion, getNextXid());
- LOG.debug("ret - OK - versionBitmap");
+ LOG.trace("ret - OK - versionBitmap");
}
/**
if (lastReceivedVersion != null && lastReceivedVersion.equals(remoteVersion)) {
throw new IllegalStateException("version negotiation stalled: version = "+remoteVersion);
}
+ lastReceivedVersion = remoteVersion;
}
@Override
* send hello reply without versionBitmap
* @param helloVersion
* @param helloXid
+ * @throws Exception
*/
- protected void sendHelloMessage(Short helloVersion, Long helloXid) {
+ private void sendHelloMessage(Short helloVersion, Long helloXid) throws Exception {
//Short highestVersion = ConnectionConductor.versionOrder.get(0);
//final Long helloXid = 21L;
HelloInput helloInput = MessageFactory.createHelloInput(helloVersion, helloXid, versionOrder);
- LOG.debug("sending first hello message: version{}, xid={}, version bitmap={}",
+ LOG.debug("sending hello message: version{}, xid={}, version bitmap={}",
helloVersion, helloXid, MessageFactory.digVersions(helloInput.getElements()));
try {
RpcResult<Void> helloResult = connectionAdapter.hello(helloInput).get(maxTimeout, maxTimeoutUnit);
RpcUtil.smokeRpc(helloResult);
LOG.debug("FIRST HELLO sent.");
- } catch (Throwable e) {
- LOG.debug("FIRST HELLO sending failed.");
- errorHandler.handleException(e, null);
+ } catch (Exception e) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("FIRST HELLO sent.", e);
+ }
+ throw new ConnectionException("FIRST HELLO sending failed because of connection issue.");
}
}
+
/**
* after handshake set features, register to session
* @param proposedVersion
* @param xId
+ * @throws Exception
*/
- protected void postHandshake(Short proposedVersion, Long xid) {
+ protected void postHandshake(Short proposedVersion, Long xid) throws Exception {
// set version
version = proposedVersion;
- LOG.debug("version set: " + proposedVersion);
+
+ LOG.debug("version set: {}", proposedVersion);
// request features
GetFeaturesInputBuilder featuresBuilder = new GetFeaturesInputBuilder();
featuresBuilder.setVersion(version).setXid(xid);
featureOutput.getDatapathId());
LOG.debug("obtained features: auxiliaryId={}",
featureOutput.getAuxiliaryId());
- LOG.info("handshake SETTLED: version={}, datapathId={}, auxiliaryId={}",
+ LOG.trace("handshake SETTLED: version={}, datapathId={}, auxiliaryId={}",
version, featureOutput.getDatapathId(), featureOutput.getAuxiliaryId());
handshakeListener.onHandshakeSuccessfull(featureOutput, proposedVersion);
- } catch (Throwable e) {
- //handshake failed
- LOG.error("issuing disconnect during handshake, reason: "+e.getMessage());
- errorHandler.handleException(e, null);
+ } catch (TimeoutException e) {
+ // handshake failed
+ LOG.warn("issuing disconnect during handshake, reason: future expired", e);
+ connectionAdapter.disconnect();
+ throw e;
+ } catch (Exception e) {
+ // handshake failed
+ LOG.warn("issuing disconnect during handshake, reason - RPC: {}", e.getMessage(), e);
connectionAdapter.disconnect();
+ throw e;
}
LOG.debug("postHandshake DONE");