<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.opendaylight</artifactId>
- <version>1.4.0-SNAPSHOT</version>
+ <version>1.4.1-SNAPSHOT</version>
</parent>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>commons.openflowplugin</artifactId>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
</properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<build>
<pluginManagement>
<plugins>
<properties>
<yang.prototype.version>1.0-SNAPSHOT</yang.prototype.version>
+ <yang.version>0.5.9-SNAPSHOT</yang.version>
+ <openflow-protocol.version>0.1-SNAPSHOT</openflow-protocol.version>
</properties>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.0-SNAPSHOT</version>
+ <version>0.5.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal.connection</artifactId>
- <version>0.1.0-SNAPSHOT</version>
+ <version>0.1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<dependency>
<groupId>org.opendaylight.openflowjava</groupId>
<artifactId>openflow-protocol-api</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${openflow-protocol.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowjava</groupId>
<artifactId>openflow-protocol-spi</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>${openflow-protocol.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
</dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ </dependency>
+
+
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-util</artifactId>
package org.opendaylight.openflowplugin.openflow.md.core;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
/**
* @author mirehak
HANDSHAKING,
/** standard phase - interacting with switch */
WORKING,
+ /** connection is idle, waiting for echo reply from switch */
+ TIMEOUTING,
/** talking to switch is over - resting in pieces */
RIP
}
* @param conductorState
*/
public void setConductorState(CONDUCTOR_STATE conductorState);
-
- /**
- * @return the switch features
- */
- public GetFeaturesOutput getFeatures();
}
import java.util.concurrent.TimeUnit;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
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;
private ConnectionConductor.CONDUCTOR_STATE conductorState;
private Short version;
- private GetFeaturesOutput features;
-
/**
* @param connectionAdapter
*/
}
@Override
- public void onEchoRequestMessage(EchoRequestMessage arg0) {
- LOG.debug("echo request received: " + arg0.getXid());
+ public void onEchoRequestMessage(EchoRequestMessage echoRequestMessage) {
+ LOG.debug("echo request received: " + echoRequestMessage.getXid());
EchoReplyInputBuilder builder = new EchoReplyInputBuilder();
- builder.setVersion(arg0.getVersion());
- builder.setXid(arg0.getXid());
- builder.setData(arg0.getData());
+ builder.setVersion(echoRequestMessage.getVersion());
+ builder.setXid(echoRequestMessage.getXid());
+ builder.setData(echoRequestMessage.getData());
connectionAdapter.echoReply(builder.build());
}
try {
rpcFeatures = featuresFuture.get(getMaxTimeout(),
TimeUnit.MILLISECONDS);
- LOG.debug("obtained features: datapathId="
- + rpcFeatures.getResult().getDatapathId());
- conductorState = CONDUCTOR_STATE.WORKING;
- this.features = rpcFeatures.getResult();
- LOG.info("handshake SETTLED");
+ if (!rpcFeatures.isSuccessful()) {
+ LOG.error("obtained features problem: "
+ + rpcFeatures.getErrors());
+ } else {
+ LOG.debug("obtained features: datapathId="
+ + rpcFeatures.getResult().getDatapathId());
+ conductorState = CONDUCTOR_STATE.WORKING;
+
+ OFSessionUtil.registerSession(this, rpcFeatures.getResult(), version);
+ LOG.info("handshake SETTLED");
+ }
} catch (Exception e) {
handleException(e);
}
public Short getVersion() {
return version;
}
-
- @Override
- public GetFeaturesOutput getFeatures() {
- return features;
- }
}
/**
* @return wished connections configurations
*/
- private Collection<ConnectionConfiguration> getConnectionConfiguration() {
+ private static Collection<ConnectionConfiguration> getConnectionConfiguration() {
//TODO:: get config from state manager
ConnectionConfiguration configuration = ConnectionConfigurationFactory.getDefault();
return Lists.newArrayList(configuration);
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core;
+
+/**
+ * @author mirehak
+ */
+public interface SwitchConnectionDestinguisher {
+ /**
+ * @return encoded switch session identifier
+ */
+ public byte[] getId();
+
+}
@Override
public void onSwitchConnected(ConnectionAdapter connectionAdapter) {
ConnectionConductor conductor = ConnectionConductorFactory.createConductor(connectionAdapter);
- //TODO:: store conductor
}
}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.math.BigInteger;
+
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author mirehak
+ */
+public abstract class OFSessionUtil {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(OFSessionUtil.class);
+
+ /**
+ * @param connectionConductor
+ * @param features
+ * @param version
+ */
+ public static void registerSession(ConnectionConductor connectionConductor,
+ GetFeaturesOutput features, short version) {
+ SwitchConnectionDestinguisher sessionKey = createSwitchSessionKey(features
+ .getDatapathId());
+ SessionContext sessionContext = getSessionManager().getSessionContext(
+ sessionKey);
+
+ if (features.getAuxiliaryId() == 0) {
+ // handle primary
+ if (sessionContext != null) {
+ LOG.warn("duplicate datapathId occured while registering new switch session: "
+ + dumpDataPathId(features.getDatapathId()));
+ getSessionManager().invalidateSessionContext(sessionKey);
+ }
+ // register new session context (based primary conductor)
+ SessionContextOFImpl context = new SessionContextOFImpl();
+ context.setPrimaryConductor(connectionConductor);
+ context.setFeatures(features);
+ getSessionManager().addSessionContext(sessionKey, context);
+ } else {
+ // handle auxiliary
+ if (sessionContext == null) {
+ LOG.warn("unexpected auxiliary connection - primary connection missing: "
+ + dumpDataPathId(features.getDatapathId()));
+ } else {
+ // register auxiliary conductor into existing sessionContext
+ SwitchConnectionDestinguisher auxiliaryKey = createConnectionCookie(features);
+ if (sessionContext.getAuxiliaryConductor(auxiliaryKey) != null) {
+ LOG.warn("duplicate datapathId+auxiliary occured while registering switch session: "
+ + dumpDataPathId(features.getDatapathId())
+ + " | "
+ + features.getAuxiliaryId());
+ getSessionManager().invalidateAuxiliary(sessionKey,
+ auxiliaryKey);
+ }
+
+ sessionContext.addAuxiliaryConductor(auxiliaryKey,
+ connectionConductor);
+ }
+ }
+ }
+
+ /**
+ * @param datapathId
+ * @return readable version of datapathId (hex)
+ */
+ public static String dumpDataPathId(BigInteger datapathId) {
+ return datapathId.toString(16);
+ }
+
+ /**
+ * @param datapathId
+ * @return new session key
+ */
+ public static SwitchConnectionDestinguisher createSwitchSessionKey(
+ BigInteger datapathId) {
+ SwitchSessionKeyOFImpl key = new SwitchSessionKeyOFImpl();
+ key.setDatapathId(datapathId);
+ key.initId();
+ return key;
+ }
+
+ /**
+ * @param features
+ * @return connection cookie key
+ * @see #createConnectionCookie(BigInteger, short)
+ */
+ public static SwitchConnectionDestinguisher createConnectionCookie(
+ GetFeaturesOutput features) {
+ return createConnectionCookie(features.getDatapathId(),
+ features.getAuxiliaryId());
+ }
+
+ /**
+ * @param datapathId
+ * @param auxiliaryId
+ * @return connection cookie key
+ */
+ public static SwitchConnectionDestinguisher createConnectionCookie(
+ BigInteger datapathId, short auxiliaryId) {
+ SwitchConnectionCookieOFImpl cookie = null;
+ if (auxiliaryId != 0) {
+ cookie = new SwitchConnectionCookieOFImpl();
+ cookie.setDatapathId(datapathId);
+ cookie.setAuxiliaryId(auxiliaryId);
+ cookie.initId();
+ }
+ return cookie;
+ }
+
+ /**
+ * @return session manager singleton instance
+ */
+ public static SessionManager getSessionManager() {
+ return SessionManagerOFImpl.getInstance();
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.util.Iterator;
+
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+
+/**
+ * @author mirehak
+ */
+public interface SessionContext {
+
+ /**
+ * @return primary connection wrapper
+ */
+ public ConnectionConductor getPrimaryConductor();
+
+ /**
+ * @return the features of corresponding switch
+ */
+ public GetFeaturesOutput getFeatures();
+
+ /**
+ * @param auxiliaryKey
+ * key under which the auxiliary conductor is stored
+ * @return list of auxiliary connection wrappers
+ */
+ public ConnectionConductor getAuxiliaryConductor(
+ SwitchConnectionDestinguisher auxiliaryKey);
+
+ /**
+ * @return iterator through all auxiliary connections wrapped in conductors
+ */
+ public Iterator<ConnectionConductor> getAuxiliaryConductors();
+
+ /**
+ * register new auxiliary connection wrapped in {@link ConnectionConductor}
+ *
+ * @param auxiliaryKey
+ * @param conductor
+ */
+ public void addAuxiliaryConductor(SwitchConnectionDestinguisher auxiliaryKey,
+ ConnectionConductor conductor);
+
+ /**
+ * @param connectionCookie
+ * @return removed connectionConductor
+ */
+ public ConnectionConductor removeAuxiliaryConductor(
+ SwitchConnectionDestinguisher connectionCookie);
+
+ // TODO:: add listeners here, manager will set them and conductor use them
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+
+/**
+ * @author mirehak
+ */
+public class SessionContextOFImpl implements SessionContext {
+
+ private GetFeaturesOutput features;
+ private ConnectionConductor primaryConductor;
+ private ConcurrentHashMap<Object, ConnectionConductor> auxiliaryConductors;
+
+ /**
+ * default ctor
+ */
+ public SessionContextOFImpl() {
+ auxiliaryConductors = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public ConnectionConductor getPrimaryConductor() {
+ return primaryConductor;
+ }
+
+ @Override
+ public ConnectionConductor getAuxiliaryConductor(
+ SwitchConnectionDestinguisher auxiliaryKey) {
+ return auxiliaryConductors.get(auxiliaryKey);
+ }
+
+ @Override
+ public void addAuxiliaryConductor(
+ SwitchConnectionDestinguisher auxiliaryKey,
+ ConnectionConductor conductor) {
+ auxiliaryConductors.put(auxiliaryKey, conductor);
+ }
+
+ @Override
+ public Iterator<ConnectionConductor> getAuxiliaryConductors() {
+ return auxiliaryConductors.values().iterator();
+ }
+
+ @Override
+ public GetFeaturesOutput getFeatures() {
+ return features;
+ }
+
+ /**
+ * @param features
+ * the features to set
+ */
+ public void setFeatures(GetFeaturesOutput features) {
+ this.features = features;
+ }
+
+ /**
+ * @param primaryConductor
+ * the primaryConductor to set
+ */
+ public void setPrimaryConductor(ConnectionConductor primaryConductor) {
+ this.primaryConductor = primaryConductor;
+ }
+
+ @Override
+ public ConnectionConductor removeAuxiliaryConductor(
+ SwitchConnectionDestinguisher connectionCookie) {
+ return auxiliaryConductors.remove(connectionCookie);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+
+/**
+ * @author mirehak
+ */
+public interface SessionManager {
+
+ /**
+ * @param sessionKey
+ * @return corresponding conductor, holding {@link ConnectionAdapter} to
+ * primary connection
+ */
+ public SessionContext getSessionContext(
+ SwitchConnectionDestinguisher sessionKey);
+
+ /**
+ * disconnect all underlying {@link ConnectionAdapter}s and notify listeners
+ *
+ * @param fullKey
+ */
+ public void invalidateSessionContext(SwitchConnectionDestinguisher fullKey);
+
+ /**
+ * register session context
+ *
+ * @param sessionKey
+ * @param context
+ */
+ public void addSessionContext(SwitchConnectionDestinguisher sessionKey,
+ SessionContextOFImpl context);
+
+ /**
+ * disconnect particular auxiliary {@link ConnectionAdapter}, identified by
+ * sessionKey and connectionCookie
+ *
+ * @param sessionKey
+ * @param connectionCookie
+ */
+ public void invalidateAuxiliary(SwitchConnectionDestinguisher sessionKey,
+ SwitchConnectionDestinguisher connectionCookie);
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author mirehak
+ */
+public class SessionManagerOFImpl implements SessionManager {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SessionManagerOFImpl.class);
+ private static SessionManagerOFImpl instance;
+ private ConcurrentHashMap<SwitchConnectionDestinguisher, SessionContext> sessionLot;
+
+ /**
+ * @return singleton instance
+ */
+ public static synchronized SessionManager getInstance() {
+ if (instance == null) {
+ instance = new SessionManagerOFImpl();
+ }
+ return instance;
+ }
+
+ private SessionManagerOFImpl() {
+ sessionLot = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public SessionContext getSessionContext(
+ SwitchConnectionDestinguisher sessionKey) {
+ return sessionLot.get(sessionKey);
+ }
+
+ @Override
+ public void invalidateSessionContext(SwitchConnectionDestinguisher fullKey) {
+ // TODO:: do some invalidating and disconnecting and notifying
+ }
+
+ @Override
+ public void addSessionContext(SwitchConnectionDestinguisher sessionKey,
+ SessionContextOFImpl context) {
+ sessionLot.put(sessionKey, context);
+ // TODO:: notify listeners
+ }
+
+ @Override
+ public void invalidateAuxiliary(SwitchConnectionDestinguisher sessionKey,
+ SwitchConnectionDestinguisher connectionCookie) {
+ SessionContext context = getSessionContext(sessionKey);
+ if (context == null) {
+ LOG.warn("context for invalidation not found");
+ } else {
+ ConnectionConductor auxiliaryConductor = context
+ .removeAuxiliaryConductor(connectionCookie);
+ if (auxiliaryConductor == null) {
+ LOG.warn("auxiliary conductor not found");
+ } else {
+ // TODO:: disconnect, notify
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.security.MessageDigest;
+
+/**
+ * @author mirehak
+ */
+public class SwitchConnectionCookieOFImpl extends SwitchSessionKeyOFImpl {
+
+ private short auxiliaryId;
+
+ /**
+ * @param encodedId
+ * @see {@link SwitchSessionKeyOFImpl#SwitchSessionKeyOFImpl(byte[])}
+ */
+ public SwitchConnectionCookieOFImpl(byte[] encodedId) {
+ super(encodedId);
+ }
+
+ /**
+ * default ctor
+ */
+ public SwitchConnectionCookieOFImpl() {
+ // do nothing
+ }
+
+ /**
+ * @param auxiliaryId
+ * the auxiliaryId to set
+ */
+ public void setAuxiliaryId(short auxiliaryId) {
+ this.auxiliaryId = auxiliaryId;
+ }
+
+ @Override
+ protected void extend(MessageDigest medi) {
+ super.extend(medi);
+ medi.update(new byte[] { (byte) (auxiliaryId >> 8), (byte) auxiliaryId });
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+
+/**
+ * @author mirehak
+ */
+public class SwitchSessionKeyOFImpl implements SwitchConnectionDestinguisher {
+
+ protected byte[] encodedId;
+ private BigInteger datapathId;
+
+ /**
+ * default ctor
+ */
+ public SwitchSessionKeyOFImpl() {
+ // do nothing
+ }
+
+ /**
+ * Special constructor for situation where no datapathId available, do not
+ * call {@link #initId()} on this instance otherwise id will be overwritten.
+ *
+ * @param encodedId
+ */
+ public SwitchSessionKeyOFImpl(byte[] encodedId) {
+ this.encodedId = encodedId;
+ }
+
+ @Override
+ public byte[] getId() {
+ return encodedId;
+ }
+
+ /**
+ * @param datapathId
+ * the datapathId to set
+ */
+ public void setDatapathId(BigInteger datapathId) {
+ this.datapathId = datapathId;
+ }
+
+ /**
+ * compute and set {@link #encodedId} based on {@link #datapathId} and
+ * {@link #auxiliaryId}
+ */
+ public void initId() {
+ try {
+ MessageDigest medi = MessageDigest.getInstance("sha-1");
+ extend(medi);
+ encodedId = medi.digest();
+ } catch (NoSuchAlgorithmException | NullPointerException e) {
+ throw new IllegalArgumentException("can not proceed datapathId: "
+ + datapathId);
+ }
+ }
+
+ /**
+ * extend the content the hash sum is computed from
+ * @param medi
+ */
+ protected void extend(MessageDigest medi) {
+ medi.update(datapathId.toByteArray());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(encodedId);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SwitchSessionKeyOFImpl other = (SwitchSessionKeyOFImpl) obj;
+ if (!Arrays.equals(encodedId, other.encodedId))
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author mirehak
+ */
+public class SwitchConnectionCookieOFImplTest {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SwitchConnectionCookieOFImplTest.class);
+
+ private SwitchConnectionCookieOFImpl switchConnectionKey;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ switchConnectionKey = createSwitchSessionKey("a1a2a3a4a5a6", (short) 42);
+ }
+
+ /**
+ * @param datapathId
+ * @return
+ */
+ private static SwitchConnectionCookieOFImpl createSwitchSessionKey(
+ String datapathId, short auxiliary) {
+ SwitchConnectionCookieOFImpl key = new SwitchConnectionCookieOFImpl();
+ key.setDatapathId(new BigInteger(datapathId, 16));
+ key.setAuxiliaryId(auxiliary);
+ return key;
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl#getId()}
+ * .
+ */
+ @Test
+ public void testGetId() {
+ switchConnectionKey.initId();
+ LOG.debug("testKey.id: " + Arrays.toString(switchConnectionKey.getId()));
+ byte[] expected = new byte[] { 32, 9, -69, 43, -68, -53, 49, 105, -109,
+ -15, -20, 50, -121, -34, -22, 3, 27, 42, 90, -59 };
+ Assert.assertArrayEquals(expected, switchConnectionKey.getId());
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl#initUUID()}
+ * .
+ */
+ @Test
+ public void testInitId1() {
+ try {
+ switchConnectionKey.setDatapathId(null);
+ switchConnectionKey.initId();
+ Assert.fail("init should fail with no datapathId");
+ } catch (Exception e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl#equals(Object)}
+ * ,
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl#hashCode()}
+ * .
+ */
+ @Test
+ public void testHashAndEquals() {
+ // insert equal keys
+ SwitchConnectionCookieOFImpl key1 = createSwitchSessionKey("1234567890",
+ (short) 42);
+ key1.initId();
+
+ SwitchConnectionCookieOFImpl key2 = createSwitchSessionKey("1234567890",
+ (short) 42);
+ key2.initId();
+
+ SwitchConnectionCookieOFImpl key3 = createSwitchSessionKey("123456789",
+ (short) 42);
+ key3.initId();
+ SwitchConnectionCookieOFImpl key4 = createSwitchSessionKey("123456789",
+ (short) 21);
+ key4.initId();
+
+ Map<SwitchConnectionDestinguisher, Integer> keyLot = new HashMap<>();
+ keyLot.put(key1, System.identityHashCode(key1));
+ Assert.assertEquals(1, keyLot.size());
+ keyLot.put(key2, System.identityHashCode(key2));
+ Assert.assertEquals(1, keyLot.size());
+ keyLot.put(key3, System.identityHashCode(key3));
+ Assert.assertEquals(2, keyLot.size());
+ keyLot.put(key4, System.identityHashCode(key4));
+ Assert.assertEquals(3, keyLot.size());
+
+ // lookup using inited key
+ Assert.assertEquals(System.identityHashCode(key2), keyLot.get(key1)
+ .intValue());
+ Assert.assertEquals(System.identityHashCode(key2), keyLot.get(key2)
+ .intValue());
+ Assert.assertEquals(System.identityHashCode(key3), keyLot.get(key3)
+ .intValue());
+ Assert.assertEquals(System.identityHashCode(key4), keyLot.get(key4)
+ .intValue());
+
+ // lookup using not inited key
+ SwitchConnectionCookieOFImpl keyWithoutInit = createSwitchSessionKey(
+ "123456789", (short) 42);
+ Assert.assertNull(keyLot.get(keyWithoutInit));
+
+ // creating brand new key and lookup
+ SwitchConnectionCookieOFImpl keyWithInit = createSwitchSessionKey(
+ "123456789", (short) 42);
+ keyWithInit.initId();
+ Assert.assertEquals(System.identityHashCode(key3),
+ keyLot.get(keyWithInit).intValue());
+
+ // lookup with key containing encoded part only
+ LOG.debug("key3.id: " + Arrays.toString(key3.getId()));
+ SwitchConnectionCookieOFImpl keyWithoutDPID = new SwitchConnectionCookieOFImpl(
+ new byte[] { -12, -121, -45, -16, 98, 33, -19, -66, -93, -46, -52, 79, -13, -116, -97, 0, 121, 78, -104, 29 });
+ Assert.assertEquals(System.identityHashCode(key3),
+ keyLot.get(keyWithoutDPID).intValue());
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDestinguisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author mirehak
+ */
+public class SwitchSessionKeyOFImplTest {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SwitchSessionKeyOFImplTest.class);
+
+ private SwitchSessionKeyOFImpl switchConnectionKey;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ switchConnectionKey = createSwitchSessionKey("a1a2a3a4a5a6");
+ }
+
+ /**
+ * @param datapathId
+ * @return
+ */
+ private static SwitchSessionKeyOFImpl createSwitchSessionKey(
+ String datapathId) {
+ SwitchSessionKeyOFImpl key = new SwitchSessionKeyOFImpl();
+ key.setDatapathId(new BigInteger(datapathId, 16));
+ return key;
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchSessionKeyOFImpl#getId()}
+ * .
+ */
+ @Test
+ public void testGetId() {
+ switchConnectionKey.initId();
+ LOG.debug("testKey.id: " + Arrays.toString(switchConnectionKey.getId()));
+ byte[] expected = new byte[] { -128, 17, -128, 123, -110, 55, 126, 122,
+ -81, 69, 47, -29, -70, -41, 0, -24, 60, 73, 9, 19 };
+ Assert.assertArrayEquals(expected, switchConnectionKey.getId());
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchSessionKeyOFImpl#initUUID()}
+ * .
+ */
+ @Test
+ public void testInitId1() {
+ try {
+ switchConnectionKey.setDatapathId(null);
+ switchConnectionKey.initId();
+ Assert.fail("init should fail with no datapathId");
+ } catch (Exception e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchSessionKeyOFImpl#equals(Object)}
+ * ,
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.session.SwitchSessionKeyOFImpl#hashCode()}
+ * .
+ */
+ @Test
+ public void testHashAndEquals() {
+ // insert equal keys
+ SwitchSessionKeyOFImpl key1 = createSwitchSessionKey("1234567890");
+ key1.initId();
+
+ SwitchSessionKeyOFImpl key2 = createSwitchSessionKey("1234567890");
+ key2.initId();
+
+ SwitchSessionKeyOFImpl key3 = createSwitchSessionKey("123456789");
+ key3.initId();
+
+ Map<SwitchConnectionDestinguisher, Integer> keyLot = new HashMap<>();
+ keyLot.put(key1, System.identityHashCode(key1));
+ Assert.assertEquals(1, keyLot.size());
+ keyLot.put(key2, System.identityHashCode(key2));
+ Assert.assertEquals(1, keyLot.size());
+ keyLot.put(key3, System.identityHashCode(key3));
+ Assert.assertEquals(2, keyLot.size());
+
+ // lookup using inited key
+ Assert.assertEquals(System.identityHashCode(key2), keyLot.get(key1)
+ .intValue());
+ Assert.assertEquals(System.identityHashCode(key2), keyLot.get(key2)
+ .intValue());
+ Assert.assertEquals(System.identityHashCode(key3), keyLot.get(key3)
+ .intValue());
+
+ // lookup using not inited key
+ SwitchSessionKeyOFImpl keyWithoutInit = createSwitchSessionKey("123456789");
+ Assert.assertNull(keyLot.get(keyWithoutInit));
+
+ // creating brand new key and lookup
+ SwitchSessionKeyOFImpl keyWithInit = createSwitchSessionKey("123456789");
+ keyWithInit.initId();
+
+ Assert.assertEquals(System.identityHashCode(key3),
+ keyLot.get(keyWithInit).intValue());
+
+ // lookup with key containing encoded part only
+ LOG.debug("key3.id: " + Arrays.toString(key3.getId()));
+ SwitchSessionKeyOFImpl keyWithoutDPID = new SwitchSessionKeyOFImpl(
+ new byte[] { -106, 12, 30, 77, 23, -44, -116, -11, -49, 40,
+ -122, 5, -82, -33, 81, -65, 100, 51, 34, 76 });
+ Assert.assertEquals(System.identityHashCode(key3),
+ keyLot.get(keyWithoutDPID).intValue());
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">\r
+ <layout class="org.apache.log4j.PatternLayout">\r
+ <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n" />\r
+ </layout>\r
+ </appender>\r
+\r
+ <logger name="org.opendaylight.openflowplugin.openflow.md" additivity="false">\r
+ <level value="DEBUG" />\r
+ <appender-ref ref="console" />\r
+ </logger>\r
+\r
+ <root>\r
+ <priority value="INFO" />\r
+ <appender-ref ref="console" />\r
+ </root>\r
+</log4j:configuration>\r