</pluginManagement>
</build>
+ <profiles>
+ <profile>
+ <id>findbugsReport</id>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>2.5.2</version>
+ </plugin>
+ </plugins>
+ </reporting>
+ </profile>
+ </profiles>
+
<repositories>
<!-- OpenDayLight Released artifact -->
<repository>
package org.opendaylight.openflowplugin.openflow.md.core;
+import java.util.concurrent.Future;
+
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+
/**
* @author mirehak
* @param conductorState
*/
public void setConductorState(CONDUCTOR_STATE conductorState);
+
+ /**
+ * terminates owned connection
+ * @return future result of disconnect action
+ */
+ public Future<Boolean> disconnect();
+
+ /**
+ * assign corresponding {@link SessionContext} to this conductor (to handle disconnect caused by switch)
+ * @param context
+ */
+ public void setSessionContext(SessionContext context);
+
+ /**
+ * assign corresponding {@link SwitchConnectionDistinguisher} to this conductor
+ * to handle disconnect caused by switch. This involves auxiliary conductors only.
+ * @param auxiliaryKey
+ */
+ public void setConnectionCookie(SwitchConnectionDistinguisher auxiliaryKey);
+
+ /**
+ * @return the sessionContext
+ */
+ public SessionContext getSessionContext();
+
+ /**
+ * @return the auxiliaryKey (null if this is a primary connection)
+ */
+ public SwitchConnectionDistinguisher getAuxiliaryKey();
}
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
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.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.EchoRequestMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
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.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;
+import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private ConnectionConductor.CONDUCTOR_STATE conductorState;
private Short version;
+ private SwitchConnectionDistinguisher auxiliaryKey;
+
+ private SessionContext sessionContext;
+
/**
* @param connectionAdapter
*/
+ rpcFeatures.getResult().getDatapathId());
conductorState = CONDUCTOR_STATE.WORKING;
- OFSessionUtil.registerSession(this, rpcFeatures.getResult(), version);
+ OFSessionUtil.registerSession(this,
+ rpcFeatures.getResult(), version);
LOG.info("handshake SETTLED");
}
} catch (Exception e) {
// TODO Auto-generated method stub
}
+ @Override
+ public void onSwitchIdleEvent(SwitchIdleEvent notification) {
+ if (!CONDUCTOR_STATE.WORKING.equals(conductorState)) {
+ // idle state in any other conductorState than WORKING means real
+ // problem and wont
+ // be handled by echoReply
+ // TODO: invalidate this connection + notify
+ } else {
+ LOG.debug("first idle state occured");
+ EchoInputBuilder builder = new EchoInputBuilder();
+ builder.setVersion(version);
+ // TODO: get xid from sessionContext
+ builder.setXid(42L);
+
+ Future<RpcResult<EchoOutput>> echoReplyFuture = connectionAdapter
+ .echo(builder.build());
+
+ try {
+ // TODO: read timeout from config
+ RpcResult<EchoOutput> echoReplyValue = echoReplyFuture.get(5,
+ TimeUnit.SECONDS);
+ if (echoReplyValue.isSuccessful()) {
+ conductorState = CONDUCTOR_STATE.WORKING;
+ } else {
+ for (RpcError replyError : echoReplyValue.getErrors()) {
+ Throwable cause = replyError.getCause();
+ LOG.error(
+ "while receiving echoReply in TIMEOUTING state: "
+ + cause.getMessage(), cause);
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("while waiting for echoReply in TIMEOUTING state: "
+ + e.getMessage(), e);
+ }
+ }
+ }
+
/**
* @param conductorState
* the connectionState to set
@Override
public void onDisconnectEvent(DisconnectEvent arg0) {
- // TODO Auto-generated method stub
+ SessionManager sessionManager = OFSessionUtil.getSessionManager();
+ sessionManager.invalidateOnDisconnect(this);
}
protected short proposeVersion(short remoteVersion) {
public Short getVersion() {
return version;
}
+
+ @Override
+ public Future<Boolean> disconnect() {
+ return connectionAdapter.disconnect();
+ }
+
+ @Override
+ public void setConnectionCookie(SwitchConnectionDistinguisher auxiliaryKey) {
+ this.auxiliaryKey = auxiliaryKey;
+ }
+
+ @Override
+ public void setSessionContext(SessionContext sessionContext) {
+ this.sessionContext = sessionContext;
+ }
+
+ @Override
+ public SwitchConnectionDistinguisher getAuxiliaryKey() {
+ return auxiliaryKey;
+ }
+
+ @Override
+ public SessionContext getSessionContext() {
+ return sessionContext;
+ }
}
// TODO:: TCP/UDP ...
return null;
}
+
+ @Override
+ public long getSwitchIdleTimeout() {
+ return 5000;
+ }
+
+ @Override
+ public Object getSslContext() {
+ return null;
+ }
};
}
/**
* @author mirehak
*/
-public interface SwitchConnectionDestinguisher {
+public interface SwitchConnectionDistinguisher {
/**
* @return encoded switch session identifier
*/
import java.math.BigInteger;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public static void registerSession(ConnectionConductor connectionConductor,
GetFeaturesOutput features, short version) {
- SwitchConnectionDestinguisher sessionKey = createSwitchSessionKey(features
+ SwitchConnectionDistinguisher sessionKey = createSwitchSessionKey(features
.getDatapathId());
SessionContext sessionContext = getSessionManager().getSessionContext(
sessionKey);
SessionContextOFImpl context = new SessionContextOFImpl();
context.setPrimaryConductor(connectionConductor);
context.setFeatures(features);
+ context.setSessionKey(sessionKey);
+ connectionConductor.setSessionContext(context);
+ context.setValid(true);
getSessionManager().addSessionContext(sessionKey, context);
} else {
// handle auxiliary
+ dumpDataPathId(features.getDatapathId()));
} else {
// register auxiliary conductor into existing sessionContext
- SwitchConnectionDestinguisher auxiliaryKey = createConnectionCookie(features);
+ SwitchConnectionDistinguisher auxiliaryKey = createConnectionCookie(features);
if (sessionContext.getAuxiliaryConductor(auxiliaryKey) != null) {
LOG.warn("duplicate datapathId+auxiliary occured while registering switch session: "
+ dumpDataPathId(features.getDatapathId())
sessionContext.addAuxiliaryConductor(auxiliaryKey,
connectionConductor);
+ connectionConductor.setSessionContext(sessionContext);
+ connectionConductor.setConnectionCookie(auxiliaryKey);
}
}
}
* @param datapathId
* @return new session key
*/
- public static SwitchConnectionDestinguisher createSwitchSessionKey(
+ public static SwitchConnectionDistinguisher createSwitchSessionKey(
BigInteger datapathId) {
SwitchSessionKeyOFImpl key = new SwitchSessionKeyOFImpl();
key.setDatapathId(datapathId);
* @return connection cookie key
* @see #createConnectionCookie(BigInteger, short)
*/
- public static SwitchConnectionDestinguisher createConnectionCookie(
+ public static SwitchConnectionDistinguisher createConnectionCookie(
GetFeaturesOutput features) {
return createConnectionCookie(features.getDatapathId(),
features.getAuxiliaryId());
* @param auxiliaryId
* @return connection cookie key
*/
- public static SwitchConnectionDestinguisher createConnectionCookie(
+ public static SwitchConnectionDistinguisher createConnectionCookie(
BigInteger datapathId, short auxiliaryId) {
SwitchConnectionCookieOFImpl cookie = null;
if (auxiliaryId != 0) {
package org.opendaylight.openflowplugin.openflow.md.core.session;
-import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
/**
* @return list of auxiliary connection wrappers
*/
public ConnectionConductor getAuxiliaryConductor(
- SwitchConnectionDestinguisher auxiliaryKey);
+ SwitchConnectionDistinguisher auxiliaryKey);
/**
- * @return iterator through all auxiliary connections wrapped in conductors
+ * @return entries of all auxiliary connections wrapped in conductors in this session
*/
- public Iterator<ConnectionConductor> getAuxiliaryConductors();
+ public Set<Entry<SwitchConnectionDistinguisher, ConnectionConductor>> getAuxiliaryConductors();
/**
* register new auxiliary connection wrapped in {@link ConnectionConductor}
* @param auxiliaryKey
* @param conductor
*/
- public void addAuxiliaryConductor(SwitchConnectionDestinguisher auxiliaryKey,
+ public void addAuxiliaryConductor(SwitchConnectionDistinguisher auxiliaryKey,
ConnectionConductor conductor);
/**
* @return removed connectionConductor
*/
public ConnectionConductor removeAuxiliaryConductor(
- SwitchConnectionDestinguisher connectionCookie);
+ SwitchConnectionDistinguisher connectionCookie);
+
+ /**
+ * @return true if this session is valid
+ */
+ public boolean isValid();
+
+ /**
+ * @param valid the valid to set
+ */
+ public void setValid(boolean valid);
+
+ /**
+ * @return the sessionKey
+ */
+ public SwitchConnectionDistinguisher getSessionKey();
// TODO:: add listeners here, manager will set them and conductor use them
package org.opendaylight.openflowplugin.openflow.md.core.session;
-import java.util.Iterator;
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
/**
private GetFeaturesOutput features;
private ConnectionConductor primaryConductor;
- private ConcurrentHashMap<Object, ConnectionConductor> auxiliaryConductors;
+ private ConcurrentHashMap<SwitchConnectionDistinguisher, ConnectionConductor> auxiliaryConductors;
+ private boolean valid;
+ private SwitchConnectionDistinguisher sessionKey;
/**
* default ctor
@Override
public ConnectionConductor getAuxiliaryConductor(
- SwitchConnectionDestinguisher auxiliaryKey) {
+ SwitchConnectionDistinguisher auxiliaryKey) {
return auxiliaryConductors.get(auxiliaryKey);
}
@Override
public void addAuxiliaryConductor(
- SwitchConnectionDestinguisher auxiliaryKey,
+ SwitchConnectionDistinguisher auxiliaryKey,
ConnectionConductor conductor) {
auxiliaryConductors.put(auxiliaryKey, conductor);
}
@Override
- public Iterator<ConnectionConductor> getAuxiliaryConductors() {
- return auxiliaryConductors.values().iterator();
+ public Set<Entry<SwitchConnectionDistinguisher, ConnectionConductor>> getAuxiliaryConductors() {
+ return Collections.unmodifiableSet(auxiliaryConductors.entrySet());
}
@Override
@Override
public ConnectionConductor removeAuxiliaryConductor(
- SwitchConnectionDestinguisher connectionCookie) {
+ SwitchConnectionDistinguisher connectionCookie) {
return auxiliaryConductors.remove(connectionCookie);
}
+
+ @Override
+ public boolean isValid() {
+ return valid;
+ }
+
+ @Override
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ }
+
+ /**
+ * @param sessionKey the sessionKey to set
+ */
+ public void setSessionKey(SwitchConnectionDistinguisher sessionKey) {
+ this.sessionKey = sessionKey;
+ }
+
+ @Override
+ public SwitchConnectionDistinguisher getSessionKey() {
+ return sessionKey;
+ }
}
package org.opendaylight.openflowplugin.openflow.md.core.session;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
/**
* @author mirehak
* primary connection
*/
public SessionContext getSessionContext(
- SwitchConnectionDestinguisher sessionKey);
+ SwitchConnectionDistinguisher sessionKey);
/**
* disconnect all underlying {@link ConnectionAdapter}s and notify listeners
*
- * @param fullKey
+ * @param sessionKey
*/
- public void invalidateSessionContext(SwitchConnectionDestinguisher fullKey);
+ public void invalidateSessionContext(SwitchConnectionDistinguisher sessionKey);
/**
* register session context
* @param sessionKey
* @param context
*/
- public void addSessionContext(SwitchConnectionDestinguisher sessionKey,
- SessionContextOFImpl context);
+ public void addSessionContext(SwitchConnectionDistinguisher sessionKey,
+ SessionContext context);
/**
* disconnect particular auxiliary {@link ConnectionAdapter}, identified by
* @param sessionKey
* @param connectionCookie
*/
- public void invalidateAuxiliary(SwitchConnectionDestinguisher sessionKey,
- SwitchConnectionDestinguisher connectionCookie);
+ public void invalidateAuxiliary(SwitchConnectionDistinguisher sessionKey,
+ SwitchConnectionDistinguisher connectionCookie);
+
+ /**
+ * @param connectionConductor
+ */
+ public void invalidateOnDisconnect(ConnectionConductor connectionConductor);
}
package org.opendaylight.openflowplugin.openflow.md.core.session;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory
.getLogger(SessionManagerOFImpl.class);
private static SessionManagerOFImpl instance;
- private ConcurrentHashMap<SwitchConnectionDestinguisher, SessionContext> sessionLot;
+ private ConcurrentHashMap<SwitchConnectionDistinguisher, SessionContext> sessionLot;
/**
* @return singleton instance
@Override
public SessionContext getSessionContext(
- SwitchConnectionDestinguisher sessionKey) {
+ SwitchConnectionDistinguisher sessionKey) {
return sessionLot.get(sessionKey);
}
@Override
- public void invalidateSessionContext(SwitchConnectionDestinguisher fullKey) {
- // TODO:: do some invalidating and disconnecting and notifying
+ public void invalidateSessionContext(
+ SwitchConnectionDistinguisher sessionKey) {
+ SessionContext context = getSessionContext(sessionKey);
+ if (context == null) {
+ LOG.warn("context for invalidation not found");
+ } else {
+ for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context
+ .getAuxiliaryConductors()) {
+ invalidateAuxiliary(sessionKey, auxEntry.getKey());
+ }
+ context.getPrimaryConductor().disconnect();
+ context.setValid(false);
+ sessionLot.remove(sessionKey);
+ // TODO:: notify listeners
+ }
+ }
+
+ private void invalidateDeadSessionContext(SessionContext sessionContext) {
+ if (sessionContext == null) {
+ LOG.warn("context for invalidation not found");
+ } else {
+ for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
+ .getAuxiliaryConductors()) {
+ invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
+ }
+ sessionContext.setValid(false);
+ sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
+ // TODO:: notify listeners
+ }
}
@Override
- public void addSessionContext(SwitchConnectionDestinguisher sessionKey,
- SessionContextOFImpl context) {
+ public void addSessionContext(SwitchConnectionDistinguisher sessionKey,
+ SessionContext context) {
sessionLot.put(sessionKey, context);
// TODO:: notify listeners
}
@Override
- public void invalidateAuxiliary(SwitchConnectionDestinguisher sessionKey,
- SwitchConnectionDestinguisher connectionCookie) {
+ public void invalidateAuxiliary(SwitchConnectionDistinguisher sessionKey,
+ SwitchConnectionDistinguisher connectionCookie) {
SessionContext context = getSessionContext(sessionKey);
+ invalidateAuxiliary(context, connectionCookie, true);
+
+ }
+
+ /**
+ * @param context
+ * @param connectionCookie
+ * @param disconnect
+ * true if auxiliary connection is to be disconnected
+ */
+ private static void invalidateAuxiliary(SessionContext context,
+ SwitchConnectionDistinguisher connectionCookie, boolean disconnect) {
if (context == null) {
LOG.warn("context for invalidation not found");
} else {
if (auxiliaryConductor == null) {
LOG.warn("auxiliary conductor not found");
} else {
- // TODO:: disconnect, notify
+ if (disconnect) {
+ auxiliaryConductor.disconnect();
+ }
}
}
+ }
+
+ @Override
+ public void invalidateOnDisconnect(ConnectionConductor conductor) {
+ if (conductor.getAuxiliaryKey() == null) {
+ invalidateDeadSessionContext(conductor.getSessionContext());
+ } else {
+ invalidateAuxiliary(conductor.getSessionContext(),
+ conductor.getAuxiliaryKey(), false);
+ }
}
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
/**
* @author mirehak
*/
-public class SwitchSessionKeyOFImpl implements SwitchConnectionDestinguisher {
+public class SwitchSessionKeyOFImpl implements SwitchConnectionDistinguisher {
protected byte[] encodedId;
private BigInteger datapathId;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
(short) 21);
key4.initId();
- Map<SwitchConnectionDestinguisher, Integer> keyLot = new HashMap<>();
+ Map<SwitchConnectionDistinguisher, Integer> keyLot = new HashMap<>();
keyLot.put(key1, System.identityHashCode(key1));
Assert.assertEquals(1, keyLot.size());
keyLot.put(key2, System.identityHashCode(key2));
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
SwitchSessionKeyOFImpl key3 = createSwitchSessionKey("123456789");
key3.initId();
- Map<SwitchConnectionDestinguisher, Integer> keyLot = new HashMap<>();
+ Map<SwitchConnectionDistinguisher, Integer> keyLot = new HashMap<>();
keyLot.put(key1, System.identityHashCode(key1));
Assert.assertEquals(1, keyLot.size());
keyLot.put(key2, System.identityHashCode(key2));