Consolidate test/debug flatl2 network manager into a single bundle. 75/3775/1
authorSuchi Raman <suchi.raman@plexxi.com>
Mon, 16 Dec 2013 22:07:06 +0000 (17:07 -0500)
committerSuchi Raman <suchi.raman@plexxi.com>
Mon, 16 Dec 2013 22:07:06 +0000 (17:07 -0500)
Signed-off-by: Suchi Raman <suchi.raman@plexxi.com>
12 files changed:
flatl2/northbound/enunciate.xml [new file with mode: 0644]
flatl2/northbound/pom.xml [new file with mode: 0644]
flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2Northbound.java [new file with mode: 0644]
flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2NorthboundRSApplication.java [new file with mode: 0644]
flatl2/northbound/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
flatl2/northbound/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
flatl2/northbound/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
flatl2/northbound/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
flatl2/northbound/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
flatl2/pom.xml [new file with mode: 0644]
flatl2/src/main/java/org/opendaylight/affinity/flatl2/Activator.java [new file with mode: 0644]
flatl2/src/main/java/org/opendaylight/affinity/flatl2/FlatL2AffinityImpl.java [new file with mode: 0644]

diff --git a/flatl2/northbound/enunciate.xml b/flatl2/northbound/enunciate.xml
new file mode 100644 (file)
index 0000000..7dd5757
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+
+  <services>
+    <rest defaultRestSubcontext="/affinity/nb/v2/flatl2"/>
+  </services>
+
+  <modules>
+    <docs docsDir="rest" title="Flat L2 affinity REST API" includeExampleXml="true" includeExampleJson="true"/>
+  </modules>
+</enunciate>
diff --git a/flatl2/northbound/pom.xml b/flatl2/northbound/pom.xml
new file mode 100644 (file)
index 0000000..4d3037c
--- /dev/null
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.affinity</groupId>
+    <artifactId>affinityParent</artifactId>
+    <version>0.4.1-SNAPSHOT</version>
+    <relativePath>../..</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.affinity</groupId>
+  <artifactId>flatl2.northbound</artifactId>
+  <version>0.4.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.enunciate</groupId>
+        <artifactId>maven-enunciate-plugin</artifactId>
+        <version>${enunciate.version}</version>
+        <dependencies>
+          <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.5.0-SNAPSHOT</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>
+            </Export-Package>
+              <Import-Package>
+                com.sun.jersey.spi.container.servlet,
+                javax.ws.rs,
+                javax.ws.rs.core,
+                javax.xml.bind.annotation,
+                org.opendaylight.affinity.flatl2,
+                org.opendaylight.controller.containermanager,
+                org.opendaylight.controller.northbound.commons,
+                org.opendaylight.controller.northbound.commons.exception,
+                org.opendaylight.controller.northbound.commons.utils,
+                org.opendaylight.controller.sal.authorization,
+                org.opendaylight.controller.sal.core,
+                org.opendaylight.controller.sal.utils,
+                org.slf4j,
+                !org.codehaus.enunciate.jaxrs
+              </Import-Package>
+            <Export-Package>
+            </Export-Package>
+            <Web-ContextPath>/affinity/nb/v2/flatl2</Web-ContextPath>
+          </instructions>
+          <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.affinity</groupId>
+      <artifactId>flatl2</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+      <version>1.17-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.northbound</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.enunciate</groupId>
+      <artifactId>enunciate-core-annotations</artifactId>
+      <version>${enunciate.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2Northbound.java b/flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2Northbound.java
new file mode 100644 (file)
index 0000000..201bb3c
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013 Plexxi, 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.affinity.flatl2.northbound;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Set;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.*;
+import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
+import org.opendaylight.controller.sal.authorization.Privilege;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import org.opendaylight.affinity.flatl2.FlatL2AffinityImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Northbound APIs that provides FlatL2 methods available to control
+ * the affinity aspects of a flat L2 network. This is an example
+ * service and should ultimately be implemented by components
+ * providing basic forwarding services.
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+@Path("/")
+public class FlatL2Northbound {
+
+    private String username;
+
+    private static final Logger log = LoggerFactory.getLogger(FlatL2Northbound.class);
+
+    @Context
+    public void setSecurityContext(SecurityContext context) {
+        username = context.getUserPrincipal().getName();
+    }
+
+    protected String getUserName() {
+        return username;
+    }
+
+    private FlatL2AffinityImpl getFlatL2AffinityService(String containerName) {
+        IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
+        if (containerManager == null)
+            throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString());
+
+        boolean found = false;
+        List<String> containerNames = containerManager.getContainerNames();
+        for (String cName : containerNames)
+            if (cName.trim().equalsIgnoreCase(containerName.trim()))
+                found = true;
+        if (found == false)
+            throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
+
+        FlatL2AffinityImpl l2mgr = (FlatL2AffinityImpl) ServiceHelper.getInstance(FlatL2AffinityImpl.class, containerName, this);
+        if (l2mgr == null)
+            throw new ServiceUnavailableException("FlatL2AffinityImpl " + RestMessages.SERVICEUNAVAILABLE.toString());
+        return l2mgr;
+    }
+
+    @Path("/{containerName}/enableaffinitylink/{affinityLinkName}")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response enableAffinityLink(
+            @PathParam("containerName") String containerName,
+            @PathParam("affinityLinkName") String affinityLinkName) {
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+        
+        FlatL2AffinityImpl l2affmgr = getFlatL2AffinityService(containerName);
+        log.info("Enable " + affinityLinkName);
+        try {
+            l2affmgr.enableAffinityLink(affinityLinkName);
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
+
+    @Path("/{containerName}/disableaffinitylink/{affinityLinkName}")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response disableLink(
+            @PathParam("containerName") String containerName,
+            @PathParam("affinityLinkName") String affinityLinkName) {
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+
+
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+        
+        FlatL2AffinityImpl l2affmgr = getFlatL2AffinityService(containerName);
+        log.info("Disable " + affinityLinkName);
+        try {
+            l2affmgr.disableAffinityLink(affinityLinkName);
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
+
+    
+    @Path("/{containerName}/disableaffinity")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response disableAffinity(@PathParam("containerName") String containerName) {
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+        
+        FlatL2AffinityImpl l2affmgr = getFlatL2AffinityService(containerName);
+        log.info("Remove all affinity rules.");
+        try {
+            l2affmgr.disableAllAffinityLinks(); // Disable the currently programmed affinity. 
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
+
+
+    @Path("/{containerName}/enableaffinity")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @TypeHint(Response.class)
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+    public Response enableAffinity(@PathParam("containerName") String containerName) {
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                                            + containerName);
+        }
+        
+        FlatL2AffinityImpl l2affmgr = getFlatL2AffinityService(containerName);
+        log.info("Push all affinity rules.");
+        try {
+            l2affmgr.enableAllAffinityLinks(); // Read a new snapshot of affinity config and push flow rules for it. 
+        } catch (Exception e) {
+            String message = "An error occurred during flow programming.";
+            log.error(message, e);
+        }
+        return Response.status(Response.Status.CREATED).build();
+    }
+
+}
diff --git a/flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2NorthboundRSApplication.java b/flatl2/northbound/src/main/java/org/opendaylight/affinity/flatl2/northbound/FlatL2NorthboundRSApplication.java
new file mode 100644 (file)
index 0000000..fd6f925
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Plexxi, 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.affinity.flatl2.northbound;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.core.Application;
+
+/**
+ * Instance of javax.ws.rs.core.Application used to return the classes
+ * that will be instantiated for JAXRS processing, this is necessary
+ * because the package scanning in jersey doesn't yet work in OSGi
+ * environment.
+ *
+ */
+public class FlatL2NorthboundRSApplication extends Application {
+    @Override
+    public Set<Class<?>> getClasses() {
+        Set<Class<?>> classes = new HashSet<Class<?>>();
+        classes.add(FlatL2Northbound.class);
+        return classes;
+    }
+}
diff --git a/flatl2/northbound/src/main/resources/META-INF/spring.factories b/flatl2/northbound/src/main/resources/META-INF/spring.factories
new file mode 100644 (file)
index 0000000..93db02e
--- /dev/null
@@ -0,0 +1 @@
+org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
diff --git a/flatl2/northbound/src/main/resources/META-INF/spring.handlers b/flatl2/northbound/src/main/resources/META-INF/spring.handlers
new file mode 100644 (file)
index 0000000..957af91
--- /dev/null
@@ -0,0 +1,10 @@
+http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
+http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
+http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
+http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
+http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
+http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
+http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
+http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
+http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
+http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
diff --git a/flatl2/northbound/src/main/resources/META-INF/spring.schemas b/flatl2/northbound/src/main/resources/META-INF/spring.schemas
new file mode 100644 (file)
index 0000000..d865edc
--- /dev/null
@@ -0,0 +1,49 @@
+http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
+http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
+http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
+http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
+http\://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd
+http\://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd
+http\://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
+http\://www.springframework.org/schema/context/spring-context-3.2.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.1.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.2.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.1.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.2.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd
+http\://www.springframework.org/schema/task/spring-task-3.1.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd
+http\://www.springframework.org/schema/task/spring-task-3.2.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.1.xsd=org/springframework/cache/config/spring-cache-3.1.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.2.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/security/spring-security-3.1.xsd=org/springframework/security/config/spring-security-3.1.xsd
+http\://www.springframework.org/schema/security/spring-security-3.2.xsd=org/springframework/security/config/spring-security-3.2.xsd
+
diff --git a/flatl2/northbound/src/main/resources/META-INF/spring.tooling b/flatl2/northbound/src/main/resources/META-INF/spring.tooling
new file mode 100644 (file)
index 0000000..057d834
--- /dev/null
@@ -0,0 +1,39 @@
+# Tooling related information for the beans namespace
+http\://www.springframework.org/schema/beans@name=beans Namespace
+http\://www.springframework.org/schema/beans@prefix=beans
+http\://www.springframework.org/schema/beans@icon=org/springframework/beans/factory/xml/spring-beans.gif
+
+# Tooling related information for the util namespace
+http\://www.springframework.org/schema/util@name=util Namespace
+http\://www.springframework.org/schema/util@prefix=util
+http\://www.springframework.org/schema/util@icon=org/springframework/beans/factory/xml/spring-util.gif
+
+# Tooling related information for the context namespace
+http\://www.springframework.org/schema/context@name=context Namespace
+http\://www.springframework.org/schema/context@prefix=context
+http\://www.springframework.org/schema/context@icon=org/springframework/context/config/spring-context.gif
+
+# Tooling related information for the jee namespace
+http\://www.springframework.org/schema/jee@name=jee Namespace
+http\://www.springframework.org/schema/jee@prefix=jee
+http\://www.springframework.org/schema/jee@icon=org/springframework/ejb/config/spring-jee.gif
+
+# Tooling related information for the scheduling namespace
+http\://www.springframework.org/schema/task@name=task Namespace
+http\://www.springframework.org/schema/task@prefix=task
+http\://www.springframework.org/schema/task@icon=org/springframework/scheduling/config/spring-task.gif
+
+# Tooling related information for the lang namespace
+http\://www.springframework.org/schema/lang@name=lang Namespace
+http\://www.springframework.org/schema/lang@prefix=lang
+http\://www.springframework.org/schema/lang@icon=org/springframework/scripting/config/spring-lang.gif
+
+# Tooling related information for the cache namespace
+http\://www.springframework.org/schema/cache@name=cache Namespace
+http\://www.springframework.org/schema/cache@prefix=cache
+http\://www.springframework.org/schema/cache@icon=org/springframework/cache/config/spring-cache.gif
+
+# Tooling related information for the mvc namespace
+http\://www.springframework.org/schema/mvc@name=mvc Namespace
+http\://www.springframework.org/schema/mvc@prefix=mvc
+http\://www.springframework.org/schema/mvc@icon=org/springframework/web/servlet/config/spring-mvc.gif
diff --git a/flatl2/northbound/src/main/resources/WEB-INF/web.xml b/flatl2/northbound/src/main/resources/WEB-INF/web.xml
new file mode 100644 (file)
index 0000000..b3a3e91
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+        version="3.0">
+  <servlet>
+    <servlet-name>JAXRSAnalytics</servlet-name>
+    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <init-param>
+      <param-name>javax.ws.rs.Application</param-name>
+      <param-value>org.opendaylight.affinity.flatl2.northbound.FlatL2NorthboundRSApplication</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>JAXRSAnalytics</servlet-name>
+    <url-pattern>/*</url-pattern>
+  </servlet-mapping>
+
+        <security-constraint>
+                <web-resource-collection>
+                        <web-resource-name>NB api</web-resource-name>
+                        <url-pattern>/*</url-pattern>
+                </web-resource-collection>
+                <auth-constraint>
+                        <role-name>System-Admin</role-name>
+                        <role-name>Network-Admin</role-name>
+                        <role-name>Network-Operator</role-name>
+                        <role-name>Container-User</role-name>
+                </auth-constraint>
+        </security-constraint>
+
+        <security-role>
+                <role-name>System-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Admin</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Network-Operator</role-name>
+        </security-role>
+        <security-role>
+                <role-name>Container-User</role-name>
+        </security-role>
+
+        <login-config>
+                <auth-method>BASIC</auth-method>
+                <realm-name>opendaylight</realm-name>
+        </login-config>
+</web-app>
diff --git a/flatl2/pom.xml b/flatl2/pom.xml
new file mode 100644 (file)
index 0000000..e875eba
--- /dev/null
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.affinity</groupId>
+    <artifactId>affinityParent</artifactId>
+    <version>0.4.1-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+
+  <artifactId>flatl2</artifactId>
+  <version>0.4.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.match,
+              org.opendaylight.controller.sal.action,
+              org.opendaylight.controller.sal.flowprogrammer,
+              org.opendaylight.controller.switchmanager,
+              org.apache.felix.dm,
+              org.osgi.service.component,
+              org.opendaylight.affinity.affinity,
+              org.opendaylight.controller.forwardingrulesmanager, 
+              org.opendaylight.controller.hosttracker, 
+              org.opendaylight.controller.hosttracker.hostAware, 
+              org.opendaylight.controller.sal.packet.address, 
+              org.opendaylight.controller.sal.routing,
+              org.opendaylight.affinity.l2agent, 
+              org.slf4j
+            </Import-Package>
+            <Export-Package>
+              org.opendaylight.affinity.flatl2
+            </Export-Package>
+            <Bundle-Activator>
+              org.opendaylight.affinity.flatl2.Activator
+            </Bundle-Activator>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.affinity</groupId>
+      <artifactId>affinity</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topologymanager</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager</artifactId>
+      <version>0.7.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwardingrulesmanager</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+      <version>${hosttracker.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>${junit.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.affinity</groupId>
+      <artifactId>l2agent</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+  </dependencies>                           
+</project>
diff --git a/flatl2/src/main/java/org/opendaylight/affinity/flatl2/Activator.java b/flatl2/src/main/java/org/opendaylight/affinity/flatl2/Activator.java
new file mode 100644 (file)
index 0000000..965a1e4
--- /dev/null
@@ -0,0 +1,113 @@
+
+/*
+ * 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.affinity.flatl2;
+
+import java.util.Hashtable;
+import java.util.Dictionary;
+import org.apache.felix.dm.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.hosttracker.IfNewHostNotify;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.sal.routing.IRouting;
+import org.opendaylight.affinity.affinity.IAffinityManager;
+import org.opendaylight.affinity.l2agent.IfL2Agent;
+
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { FlatL2AffinityImpl.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(FlatL2AffinityImpl.class)) {
+            // export the services
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "FlatL2AffinityImpl");
+            c.setInterface(new String[] { IfNewHostNotify.class.getName(),                    
+                                          FlatL2AffinityImpl.class.getName() }, props);
+
+            // register dependent modules
+            c.add(createContainerServiceDependency(containerName).setService(
+                    ISwitchManager.class).setCallbacks("setSwitchManager",
+                    "unsetSwitchManager").setRequired(true));
+
+            // If using a layer 3 forwarding service such as simpleforwarding. 
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IRouting.class).setCallbacks("setRouting", "unsetRouting")
+                    .setRequired(false));
+
+            // If using a layer 2 forwarding service such as l2agent. 
+            c.add(createContainerServiceDependency(containerName)
+                  .setService(IfL2Agent.class)
+                  .setCallbacks("setL2Agent", "unsetL2Agent")
+                  .setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IfIptoHost.class).setCallbacks("setHostTracker",
+                    "unsetHostTracker").setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IForwardingRulesManager.class).setCallbacks(
+                    "setForwardingRulesManager", "unsetForwardingRulesManager")
+                  .setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(IAffinityManager.class).setCallbacks(                                                                                                                  "setAffinityManager", "unsetAffinityManager")
+                  .setRequired(true));
+        }
+    }
+}
diff --git a/flatl2/src/main/java/org/opendaylight/affinity/flatl2/FlatL2AffinityImpl.java b/flatl2/src/main/java/org/opendaylight/affinity/flatl2/FlatL2AffinityImpl.java
new file mode 100644 (file)
index 0000000..5064349
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2013 Plexxi, 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.affinity.flatl2;
+
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.AbstractMap;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.eclipse.osgi.framework.console.CommandInterpreter;
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.utils.IPProtocols;
+
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.Host;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.NodeTable;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.core.Path;
+
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.match.MatchField;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.action.Controller;
+import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.NetUtils;
+
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.IfNewHostNotify;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.affinity.affinity.InetAddressMask;
+
+import org.opendaylight.controller.hosttracker.HostIdFactory;
+import org.opendaylight.controller.hosttracker.IHostId;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.sal.routing.IRouting;
+import org.opendaylight.affinity.affinity.IAffinityManager;
+import org.opendaylight.affinity.affinity.AffinityAttributeType;
+import org.opendaylight.affinity.affinity.AffinityAttribute;
+import org.opendaylight.affinity.affinity.SetDeny;
+import org.opendaylight.affinity.affinity.SetPathRedirect;
+import org.opendaylight.affinity.l2agent.IfL2Agent;
+import org.opendaylight.affinity.l2agent.L2Agent;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Affinity rules engine for flat L2 network.
+ */
+public class FlatL2AffinityImpl implements IfNewHostNotify {
+    private static final Logger log = LoggerFactory.getLogger(FlatL2AffinityImpl.class);
+
+    private ISwitchManager switchManager = null;
+    private IAffinityManager am = null;
+    private IfIptoHost hostTracker;
+    private IForwardingRulesManager ruleManager;
+    private IRouting routing;
+    private IfL2Agent l2agent;
+
+    private String containerName = GlobalConstants.DEFAULT.toString();
+    private boolean isDefaultContainer = true;
+    private static final int REPLACE_RETRY = 1;
+
+    HashMap<String, List<Flow>> allfgroups;
+    HashMap<String, HashMap<AffinityAttributeType, AffinityAttribute>> attribs;
+
+    Set<Node> nodelist;
+
+    private static short REDIRECT_IPSWITCH_PRIORITY = 3;
+
+    public enum ReasonCode {
+        SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
+                "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
+                        "Configuration Conflict with Existing Entry");
+
+        private final String name;
+
+        private ReasonCode(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    /* Only default container. */
+    public String getContainerName() {
+        return containerName;
+    }
+
+    void setAffinityManager(IAffinityManager mgr) {
+        log.info("Setting affinity manager {}", mgr);
+        this.am = mgr;
+    }
+
+    void unsetAffinityManager(IAffinityManager mgr) {
+        if (this.am.equals(mgr)) {
+            this.am = null;
+        }
+    }
+    void setHostTracker(IfIptoHost h) {
+        log.info("Setting hosttracker {}", h);
+        this.hostTracker = h;
+    }
+
+    void unsetHostTracker(IfIptoHost h) {
+        if (this.hostTracker.equals(h)) {
+            this.hostTracker = null;
+        }
+    }
+    
+    public void setForwardingRulesManager(IForwardingRulesManager forwardingRulesManager) {
+        log.debug("Setting ForwardingRulesManager");
+        this.ruleManager = forwardingRulesManager;
+    }
+    
+    public void unsetForwardingRulesManager(IForwardingRulesManager forwardingRulesManager) {
+        if (this.ruleManager == forwardingRulesManager) {
+            this.ruleManager = null;
+        }
+    }
+    void setSwitchManager(ISwitchManager s)
+    {
+        this.switchManager = s;
+    }
+    
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            this.switchManager = null;
+        }
+    }
+
+    /**
+     * Redirect port lookup requires access to L2agent or Routing. For
+     * the time being, only one is assumed to be active.
+     */
+    void setL2Agent(IfL2Agent s)
+    {
+        log.info("Setting l2agent {}", s);
+        this.l2agent = s;
+    }
+
+    void unsetL2Agent(IfL2Agent s) {
+        if (this.l2agent == s) {
+            this.l2agent = null;
+        }
+    }
+    public void setRouting(IRouting routing) {
+        this.routing = routing;
+    }
+
+    public void unsetRouting(IRouting routing) {
+        if (this.routing == routing) {
+            this.routing = null;
+        }
+    }
+    
+    private void notifyHostUpdate(HostNodeConnector host, boolean added) {
+        if (host == null) {
+            return;
+        }
+        log.info("Host update received (new = {}).", added);
+    }
+
+    @Override
+    public void notifyHTClient(HostNodeConnector host) {
+        notifyHostUpdate(host, true);
+    }
+
+    @Override
+    public void notifyHTClientHostRemoved(HostNodeConnector host) {
+        notifyHostUpdate(host, false);
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init() {
+        log.debug("flat L2 implementation INIT called!");
+        containerName = GlobalConstants.DEFAULT.toString();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one
+     * dependency become unsatisfied or when the component is shutting
+     * down because for example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        log.debug("DESTROY called!");
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called
+     * and after the services provided by the class are registered in
+     * the service registry
+     *
+     */
+    void start() {
+        log.debug("START called!");
+    }
+
+    /**
+     * Function called after registering the service in OSGi service registry.
+     */
+    void started() {
+        log.debug("FlatL2AffinityImpl started!");
+    }
+
+    /**
+     * Clear all flows.
+     */
+    public boolean clearAllFlowGroups(List<String> groupnames) {
+        for (String groupName: groupnames) {
+            ruleManager.uninstallFlowEntryGroup(groupName);
+        } 
+        return true;
+    }
+    
+    // Called via northbound API -- push all affinities. 
+    public boolean enableAllAffinityLinks() {
+        this.nodelist = switchManager.getNodes();
+        if (this.nodelist == null) {
+            log.debug("No nodes in network.");
+            return true;
+        }
+        
+        // Get all flow groups and attribs from the affinity manager. 
+        this.allfgroups = am.getAllFlowGroups();
+        this.attribs = am.getAllAttributes();
+
+        for (Node node: this.nodelist) {
+            programFlowGroupsOnNode(this.allfgroups, this.attribs, node);
+        }
+        return true;
+    }
+    
+    /** 
+     * Add flow groups to forwarding rules manager as FlowEntry
+     * objects. Each flow group corresponds to a policy group in the
+     * forwarding rules manager. actions represent the forwarding
+     * actions to be applied to each flow group. Forwarding actions
+     * may be REDIRECT, DROP, or TAP. 
+     */
+    public boolean programFlowGroupsOnNode(HashMap<String, List<Flow>>flowgroups, 
+                                          HashMap<String, HashMap<AffinityAttributeType, AffinityAttribute>>attribs, 
+                                          Node node) {
+        for (String groupName: flowgroups.keySet()) {
+            List<Flow> flowlist = flowgroups.get(groupName);
+            log.info("flatl2: {} (#flows={})", groupName, flowgroups.get(groupName).size());
+            log.info("flatl2: {} (#attribs={})", groupName, attribs.get(groupName).size());
+            for (Flow f: flowlist) {
+                List<Action> actions = calcForwardingActions(node, attribs.get(groupName));
+                // Update flow with actions. 
+                log.info("Adding actions {} to flow {}", actions, f);
+                f.setActions(actions);
+                // Set the flow name based on end points for this flow. 
+                String flowName = null;
+                InetAddress srcIp = (InetAddress) f.getMatch().getField(MatchType.NW_SRC).getValue();
+                InetAddress dstIp = (InetAddress) f.getMatch().getField(MatchType.NW_DST).getValue();
+                flowName = "[" + groupName + ":" + srcIp + ":" + dstIp + "]";
+                // Make a flowEntry object. groupName is the policy name, from the affinity link name. Same for all flows in this bundle. 
+                FlowEntry fEntry = new FlowEntry(groupName, flowName, f, node);
+                log.info("Install flow entry {} on node {}", fEntry.toString(), node.toString());
+                installFlowEntry(fEntry);
+            }
+        }
+        return true; // error checking
+    }
+    /** 
+     * Calculate forwarding actions per node. Inputs are the node
+     * (switch) and the list of configured actions.
+     */
+
+    public List<Action> calcForwardingActions(Node node, HashMap<AffinityAttributeType, AffinityAttribute> attribs) {
+        List<Action> fwdactions = new ArrayList<Action>();
+
+        AffinityAttributeType aatype;
+        log.info("calcforwardingactions: node = {}", node);
+
+        // Apply drop
+        aatype = AffinityAttributeType.SET_DENY;
+
+        if (attribs.get(aatype) != null) {
+            Action dropaction = new Drop();
+            fwdactions.add(dropaction);
+            return fwdactions;
+        }
+
+        // Apply redirect 
+        aatype = AffinityAttributeType.SET_PATH_REDIRECT;
+
+        SetPathRedirect rdrct = (SetPathRedirect) attribs.get(aatype);
+        
+        if (rdrct != null) {
+            log.info("Found a path redirect setting.");
+            List<InetAddress> wplist = rdrct.getWaypointList();
+            if (wplist != null) {
+                // Only one waypoint server in list. 
+                InetAddress wp = wplist.get(0);
+                log.info("waypoint information = {}", wplist.get(0));
+                // Lookup output port on this node for this destination. 
+
+                // Using L2agent
+                Output output = getRedirectPortL2Agent(node, wp);
+                fwdactions.add(output);
+                // Using simpleforwarding.
+                // Output output = getRedirectPort(node, wp);
+                // Controller controller = new Controller();
+                // fwdactions.add(controller);
+            }
+        }
+
+        // tbd. Apply tap. 
+        return fwdactions;
+    }
+
+    /** 
+     * Using L2agent, get the redirect port toward this wp (waypoint)
+     * from this node (switch).
+     */
+    public Output getRedirectPortL2Agent(Node node, InetAddress wp) {
+        Output op = null;
+
+        if (l2agent != null) {
+            /* Look up the output port leading to the waypoint. */
+            HostNodeConnector wphost = (HostNodeConnector) hostTracker.hostFind(wp);
+            log.info("redirect port on node {} toward wphost {}", node, wphost);
+            NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
+            if (dst_connector != null) {
+                op = new Output(dst_connector);
+            }
+        } else {
+            log.info("l2agent is not set!!!");
+        }
+        return op;
+    }
+
+    public Output getRedirectPort(Node node, InetAddress wp) {
+        IHostId id = HostIdFactory.create(wp, null);
+        HostNodeConnector hnConnector = this.hostTracker.hostFind(id);
+        Node destNode = hnConnector.getnodeconnectorNode();
+        
+        log.debug("from node: {}", node.toString());
+        log.debug("dest node: {}", destNode.toString());
+
+        // Get path between both the nodes                                                                                                           
+        NodeConnector forwardPort = null;
+        if (node.getNodeIDString().equals(destNode.getNodeIDString())) {
+            forwardPort = hnConnector.getnodeConnector();
+            log.info("Both source and destination are connected to same switch nodes. output port is {}",
+                        forwardPort);
+        } else {
+            Path route = this.routing.getRoute(node, destNode);
+            log.info("Path between source and destination switch nodes : {}",
+                        route.toString());
+            forwardPort = route.getEdges().get(0).getTailNodeConnector();
+        }
+        return(new Output(forwardPort));
+    }
+
+    /**
+     * Install this flow entry object. 
+     */
+    public boolean installFlowEntry(FlowEntry fEntry) {
+        if (!this.ruleManager.checkFlowEntryConflict(fEntry)) {
+            if (this.ruleManager.installFlowEntry(fEntry).isSuccess()) {
+                return true;
+            } else {
+                log.error("Error in installing flow entry {} to node : {}", fEntry.toString(), fEntry.getNode());
+            }
+        } else {
+            log.error("Conflicting flow entry exists : {}", fEntry.toString());
+        }
+        return true;
+    }
+
+    public void enableAffinityLink(String affinityLinkName) {
+        List<Flow> flowgroup = this.allfgroups.get(affinityLinkName);
+        HashMap<AffinityAttributeType, AffinityAttribute> attribset = this.attribs.get(affinityLinkName);
+        
+        // Make a hashmap with one key, value pair representing this
+        // affinity link. Do this for flows and for attribs.
+        HashMap<String, List<Flow>> linkflows = new HashMap<String, List<Flow>>();
+        HashMap<String, HashMap<AffinityAttributeType, AffinityAttribute>> linkattribs = new HashMap<String, HashMap<AffinityAttributeType, AffinityAttribute>>();
+
+        if (flowgroup != null && attribset != null) {
+            linkflows.put(affinityLinkName, flowgroup);
+            linkattribs.put(affinityLinkName, attribset);
+            
+            if (this.nodelist != null) {
+                for (Node node: this.nodelist) {
+                    programFlowGroupsOnNode(this.allfgroups, this.attribs, node);
+                }
+            }
+        }
+    }
+    
+    public void disableAffinityLink(String affinityLinkName) {
+        ruleManager.uninstallFlowEntryGroup(affinityLinkName);
+    }
+
+    public void disableAllAffinityLinks() {
+        if (this.allfgroups != null) {
+            for (String s: this.allfgroups.keySet()) {
+                log.info("Clearing all flowrules for " + s);
+                ruleManager.uninstallFlowEntryGroup(s);
+            }
+        }
+    }
+}