--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
--- /dev/null
+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
--- /dev/null
+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
+
--- /dev/null
+# 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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.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));
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+ }
+}