sessionManager proposal 38/1838/1
authorMichal Rehak <mirehak@cisco.com>
Fri, 11 Oct 2013 15:54:43 +0000 (17:54 +0200)
committerMichal Rehak <mirehak@cisco.com>
Fri, 11 Oct 2013 15:55:55 +0000 (17:55 +0200)
parent version update
yangtools version update
logging added
idle state added into conductor states enum

Change-Id: I5d849e44bd799e3127b6dafe2ab5df56fe774e38
Signed-off-by: Michal Rehak <mirehak@cisco.com>
17 files changed:
commons/pom.xml
openflowplugin/pom.xml
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductor.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductorImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/SwitchConnectionDestinguisher.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/SwitchConnectionHandlerImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/OFSessionUtil.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContext.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContextOFImpl.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManager.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManagerOFImpl.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImpl.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImpl.java [new file with mode: 0644]
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImplTest.java [new file with mode: 0644]
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImplTest.java [new file with mode: 0644]
openflowplugin/src/test/resources/log4j.xml [new file with mode: 0644]

index 05ca547e03b238b59e14a90f8410304df28ba174..1827f7d40a0d0e8b80a324999b2a8d377933c200 100755 (executable)
@@ -9,7 +9,7 @@
     <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>
index 4e1f34c9bc0fb4166937f9b0abe138696fb3843f..8fd2d8167781b195b9d963e33d615b0baa36a8b1 100644 (file)
@@ -15,6 +15,8 @@
 
     <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>
index 5c66743aee3c5c186e1befb0275672d2647c797b..bd33944458afa9ff5f52bdbe5bb10ecb83ed77be 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.openflowplugin.openflow.md.core;
 
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
 
 /**
  * @author mirehak
@@ -25,6 +24,8 @@ public interface ConnectionConductor {
         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
     }
@@ -48,9 +49,4 @@ public interface ConnectionConductor {
      * @param conductorState
      */
     public void setConductorState(CONDUCTOR_STATE conductorState);
-
-    /**
-     * @return the switch features
-     */
-    public GetFeaturesOutput getFeatures();
 }
index 626f21d03afd674c9e6615b13d46a666eb3f35fd..b906117f6a3bd297af4e7502863fa213fcd1dda3 100644 (file)
@@ -14,6 +14,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 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;
@@ -52,8 +53,6 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
     private ConnectionConductor.CONDUCTOR_STATE conductorState;
     private Short version;
 
-    private GetFeaturesOutput features;
-
     /**
      * @param connectionAdapter
      */
@@ -71,12 +70,12 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
     }
 
     @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());
     }
@@ -136,11 +135,17 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
             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);
             }
@@ -234,9 +239,4 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
     public Short getVersion() {
         return version;
     }
-
-    @Override
-    public GetFeaturesOutput getFeatures() {
-        return features;
-    }
 }
index d450573cf89f18d7c8f8b6c803119ce7d83654ea..b13eada421257205eb91fc58d0dcb6b0a858dc12 100644 (file)
@@ -68,7 +68,7 @@ public class MDController {
     /**
      * @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);
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/SwitchConnectionDestinguisher.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/SwitchConnectionDestinguisher.java
new file mode 100644 (file)
index 0000000..38b386e
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * 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();
+
+}
index 4838666431d95d65c86abe8c3e3cdee23c6d66e0..647626643f23010b4335836e2cd1359f51a094d3 100644 (file)
@@ -28,7 +28,6 @@ public class SwitchConnectionHandlerImpl implements SwitchConnectionHandler {
     @Override
     public void onSwitchConnected(ConnectionAdapter connectionAdapter) {
         ConnectionConductor conductor = ConnectionConductorFactory.createConductor(connectionAdapter);
-        //TODO:: store conductor
     }
 
 }
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/OFSessionUtil.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/OFSessionUtil.java
new file mode 100644 (file)
index 0000000..ad48183
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * 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();
+    }
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContext.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContext.java
new file mode 100644 (file)
index 0000000..56fe3f7
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * 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
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContextOFImpl.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionContextOFImpl.java
new file mode 100644 (file)
index 0000000..a4df782
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * 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);
+    }
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManager.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManager.java
new file mode 100644 (file)
index 0000000..094c29c
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * 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);
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManagerOFImpl.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManagerOFImpl.java
new file mode 100644 (file)
index 0000000..e978d7c
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * 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
+            }
+        }
+
+    }
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImpl.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImpl.java
new file mode 100644 (file)
index 0000000..992d7cf
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * 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 });
+    }
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImpl.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImpl.java
new file mode 100644 (file)
index 0000000..17fde93
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * 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;
+    }
+
+}
diff --git a/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImplTest.java b/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchConnectionCookieOFImplTest.java
new file mode 100644 (file)
index 0000000..b45e7b4
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * 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());
+    }
+
+}
diff --git a/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImplTest.java b/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/session/SwitchSessionKeyOFImplTest.java
new file mode 100644 (file)
index 0000000..69cfc2b
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * 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());
+    }
+
+}
diff --git a/openflowplugin/src/test/resources/log4j.xml b/openflowplugin/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..a7b2604
--- /dev/null
@@ -0,0 +1,20 @@
+<?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