Added a hand-coded implementation of service function chain. To be integrated with... 55/2255/1
authorSuchi Raman <suchi.raman@plexxi.com>
Mon, 28 Oct 2013 17:59:59 +0000 (13:59 -0400)
committerSuchi Raman <suchi.raman@plexxi.com>
Mon, 28 Oct 2013 17:59:59 +0000 (13:59 -0400)
Functions as a network tap, since only one hop is implemented. Chains with multiple service points are not yet implemented.

Signed-off-by: Suchi Raman <suchi.raman@plexxi.com>
affinity/api/src/main/java/org/opendaylight/affinity/affinity/IAffinityManager.java
affinity/implementation/pom.xml
affinity/implementation/src/main/java/org/opendaylight/affinity/affinity/internal/Activator.java
affinity/implementation/src/main/java/org/opendaylight/affinity/affinity/internal/AffinityManagerImpl.java
affinity/northbound/src/main/java/org/opendaylight/affinity/affinity/northbound/AffinityNorthbound.java
nfchain/impl/src/main/java/org/opendaylight/affinity/nfchain/provider/NfchainManager.java
nfchainagent/pom.xml [new file with mode: 0644]
nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/Activator.java [new file with mode: 0644]
nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainAgent.java [new file with mode: 0644]
nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainconfig.java [new file with mode: 0644]
pom.xml

index 0a276ad40289a036340bb7b7c9bbfc8eba35e514..7f29b132fb9a78db24dcc4da8514653ba53abbc8 100644 (file)
@@ -32,6 +32,12 @@ import org.opendaylight.affinity.affinity.AffinityLink;
  */
 public interface IAffinityManager {
 
+    public Status addAffinityGroup(AffinityGroup ag);
+    public Status removeAffinityGroup(String name);
+    
+    public AffinityGroup getAffinityGroup(String name);
+    public List<AffinityGroup> getAllAffinityGroups();
+
     public Status addAffinityLink(AffinityLink al);
     public Status removeAffinityLink(AffinityLink al);
     public Status removeAffinityLink(String linkName);
@@ -39,12 +45,6 @@ public interface IAffinityManager {
     public AffinityLink getAffinityLink(String name);    
     public List<AffinityLink> getAllAffinityLinks();
 
-    public Status addAffinityGroup(AffinityGroup ag);
-    public Status removeAffinityGroup(String name);
-    
-    public AffinityGroup getAffinityGroup(String name);
-    public List<AffinityGroup> getAllAffinityGroups();
-
     /* Save all configs to their respective files. */
     public Status saveAffinityConfig();
 
@@ -53,6 +53,12 @@ public interface IAffinityManager {
     public List<Entry<Host, Host>> getAllFlowsByHost(AffinityLink al);
     public List<Entry<AffinityIdentifier, AffinityIdentifier>> getAllFlowsByAffinityIdentifier(AffinityLink al);
 
-    public Status addFlowRulesForRedirect(AffinityLink al) throws Exception;
-    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] mac);
+
+    /* Program the nf service chain for this affinity link. */
+    /* Methods to add and enable network service chains. */
+    public Status addNfchain(AffinityLink al);
+    public Status enableRedirect(AffinityLink al) throws Exception;
+
+    //    public Status addFlowRulesForRedirect(AffinityLink al) throws Exception;
+    //    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] mac);
 }
index 28fc01fa01254e8aa78f5945a7fae7a03d1dd471..bc804fdd767168ee847890866f0a177b37d2792b 100644 (file)
@@ -36,6 +36,7 @@
             <Import-Package>
               org.opendaylight.affinity.affinity,
               org.opendaylight.affinity.l2agent,
+              org.opendaylight.affinity.nfchainagent,
               org.opendaylight.controller.clustering.services,
               org.opendaylight.controller.configuration,
               org.opendaylight.controller.hosttracker,
       <artifactId>l2agent</artifactId>
       <version>0.4.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.affinity</groupId>
+      <artifactId>nfchainagent</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index 88e55b9a8b5e0ea6fd9ee523f798d6293bfb0153..0a380f2ebef3dc1c84c9387abf1e33228deda656 100644 (file)
@@ -23,12 +23,11 @@ import org.opendaylight.affinity.affinity.IAffinityManagerAware;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.opendaylight.affinity.l2agent.IfL2Agent;
-import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
-//import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
 import org.opendaylight.controller.hosttracker.IfIptoHost;
 import org.opendaylight.controller.hosttracker.IfNewHostNotify;
-
+import org.opendaylight.affinity.l2agent.IfL2Agent;
+import org.opendaylight.affinity.nfchainagent.NFchainAgent;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
 
 /**
  * AffinityManager Bundle Activator
@@ -105,11 +104,10 @@ public class Activator extends ComponentActivatorAbstractBase {
                   .setService(IfL2Agent.class)
                   .setCallbacks("setL2Agent", "unsetL2Agent")
                   .setRequired(true));
-            /*            c.add(createContainerServiceDependency(containerName).setService(
-                    IForwardingRulesManager.class).setCallbacks(
-                    "setForwardingRulesManager", "unsetForwardingRulesManager")
+            c.add(createContainerServiceDependency(containerName).setService(
+                    NFchainAgent.class).setCallbacks(
+                    "setNfchainAgent", "unsetNfchainAgent")
                     .setRequired(true));
-            */
             c.add(createContainerServiceDependency(containerName)
                   .setService(IFlowProgrammerService.class)
                   .setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService")
index 32be680bb00d3eba46ef65a664984cb279490d59..4bd43c50b41e67d21712582579d23d5f65dbb523 100644 (file)
@@ -97,6 +97,8 @@ import org.opendaylight.controller.hosttracker.IfNewHostNotify;
 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.affinity.l2agent.IfL2Agent;
+import org.opendaylight.affinity.nfchainagent.NFchainAgent;
+import org.opendaylight.affinity.nfchainagent.NFchainconfig;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -114,6 +116,7 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
     private String affinityGroupFileName = null;
     //    private IForwardingRulesManager ruleManager;
     private IFlowProgrammerService programmer = null;
+    private NFchainAgent nfchainagent = null;
     
     private ISwitchManager switchManager = null;
     private IfL2Agent l2agent = null;
@@ -270,6 +273,19 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
             this.programmer = null;
         }
     }
+
+    void setNFchainAgent(NFchainAgent s)
+    {
+        log.info("Setting nfchainagent {}", s);
+        this.nfchainagent = s;
+    }
+
+    void unsetNFchainAgent(NFchainAgent s) {
+        if (this.nfchainagent == s) {
+            this.nfchainagent = null;
+        }
+    }
+
     void setL2Agent(IfL2Agent s)
     {
         log.info("Setting l2agent {}", s);
@@ -333,115 +349,13 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
         return new Status(StatusCode.SUCCESS);
     }
 
-    /*
-    private Status installRedirectionFlow(Node sw, Flow flow) {
-        FlowEntry fEntry = new FlowEntry("path-redir", "flow", flow, sw);
-        Status success = new Status(StatusCode.SUCCESS);
-        Status error = new Status(StatusCode.NOTFOUND);
-            
-        log.info("Install flow entry {} on node {}", fEntry.toString(), sw.toString());
-        
-        if (!this.ruleManager.checkFlowEntryConflict(fEntry)) {
-            if (this.ruleManager.installFlowEntry(fEntry).isSuccess()) {
-                return success;
-            } else {
-                log.error("Error in installing flow entry to node : {}", sw);
-            }
-        } else {
-            log.error("Conflicting flow entry exists : {}", fEntry.toString());
-        }
-        return error;
-    }
-    */
-
-    /** 
-     * Fetch all node connectors. Each switch port will receive a flow
-     * rule. Do not stop on error. Pass in the waypointMAC address so
-     * that the correct output port can be determined.
-     */
-    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] waypointMAC) {
-        /* Get all node connectors. */
-        Set<Node> nodes = switchManager.getNodes();
-        Status success = new Status(StatusCode.SUCCESS);
-        Status notfound = new Status(StatusCode.NOTFOUND);
-
-        if (nodes == null) {
-            log.debug("No nodes in network.");
-            return success;
-        } 
-
-        /* Send this flow rule to all nodes in the network. */
-        for (Node node: nodes) {
-            List<Action> actions = new ArrayList<Action>();
-            Match match = new Match();
-            match.setField(new MatchField(MatchType.NW_SRC, from, null));
-            match.setField(new MatchField(MatchType.NW_DST, to, null));
-            match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());  
-        
-            Flow f = new Flow(match, actions);
-            f.setMatch(match);
-            f.setPriority(REDIRECT_IPSWITCH_PRIORITY);
-
-            /* Look up the output port leading to the waypoint. */
-            NodeConnector dst_connector = l2agent.lookup_output_port(node, waypointMAC);
-
-            log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
-            if (dst_connector != null) {
-                f.setActions(actions);
-                f.addAction(new Output(dst_connector));
-                log.debug("flow push flow = {} to node = {} ", f, node);
-                /*                Status status = installRedirectionFlow(node, flow);*/
-                Status status = programmer.addFlow(node, f);
-                if (!status.isSuccess()) {
-                    log.debug("Error during addFlow: {} on {}. The failure is: {}",
-                              f, node, status.getDescription());
-                }
-            }
-        }
-        return success;
-    }
-
-    /** 
-     * add flow rules for each node connector.
-     */
-    public Status addFlowRulesForRedirect(AffinityLink al) throws Exception {
-
-        InetAddress address1, address2;
-        InetAddress mask;
-        mask = InetAddress.getByName("255.255.255.255");
-
-        String waypoint = al.getWaypoint();
-
-        log.debug("addFlowRulesForRedirect link = {} waypoint = {}", al.getName(), al.getWaypoint());
-        List<Entry<Host,Host>> hostPairList= getAllFlowsByHost(al);
-        for (Entry<Host,Host> hostPair : hostPairList) {
-            /* Create a match for each host pair in the affinity link. */
-            Match match = new Match();
-
-            log.debug("Processing next hostPair {}", hostPair);
-            Host host1 = hostPair.getKey();
-            Host host2 = hostPair.getValue();
-            if (host1 == null || host2 == null) {
-                log.debug("Hosts in hostpair {} -> {} not found in hosttracker.", host1, host2);
-                return new Status(StatusCode.NOTFOUND);
-            }
-            log.debug("Adding a flow for host pair {} -> {}", host1, host2);
-            address1 = host1.getNetworkAddress();
-            address2 = host2.getNetworkAddress();
-            log.debug("Adding a flow for {} -> {}", address1, address2);
-            byte [] waypointMAC = InetAddressToMAC(waypoint);
-            pushFlowRule(address1, address2, waypointMAC);
-        }
-       return new Status(StatusCode.SUCCESS);
-    }
-
-    public byte [] InetAddressToMAC(String ipaddress) {
-        InetAddress inetAddr = NetUtils.parseInetAddress(ipaddress);
-        HostNodeConnector host = (HostNodeConnector) hostTracker.hostFind(inetAddr);
+    /*    public byte [] InetAddressToMAC(InetAddress inetAddr) {
+        //        HostNodeConnector 
         log.debug("Find {} -> {} using hostTracker {}", inetAddr, host, hostTracker);
         byte [] dst_mac = host.getDataLayerAddressBytes();
         return dst_mac;
     }
+    */
 
     public Status removeAffinityLink(String name) {
        affinityLinkList.remove(name);
@@ -725,4 +639,55 @@ public class AffinityManagerImpl implements IAffinityManager, IfNewHostNotify,
             this.clusterContainerService = null;
         }
     }
+    
+    /* Add a nfchain config for this affinity link. */
+    List<Flow> getFlowlist(AffinityLink al) {
+        InetAddress from, to;
+
+        log.debug("get flowlist affinity link = {}", al.getName());
+        List<Flow> flowlist = new ArrayList<Flow>();
+        List<Entry<Host,Host>> hostPairList= getAllFlowsByHost(al);
+
+        /* Create a Flow for each host pair in the affinity link. */
+        for (Entry<Host,Host> hostPair : hostPairList) {
+            log.debug("Processing next hostPair {}", hostPair);
+
+            Match match = new Match();
+            from = hostPair.getKey().getNetworkAddress();
+            to = hostPair.getValue().getNetworkAddress();
+            log.debug("Adding a flow for {} -> {}", from, to);
+
+            if (from == null ||to == null) {
+                /* Skip host pairs if one end is null. */
+                log.debug("Hosts in hostpair {} -> {} not found in hosttracker.", from, to);
+                continue;
+            } else {
+                match.setField(new MatchField(MatchType.NW_SRC, from, null));
+                match.setField(new MatchField(MatchType.NW_DST, to, null));
+                match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());  
+                Flow flow = new Flow(match, null);
+                flow.setPriority(REDIRECT_IPSWITCH_PRIORITY);
+                flowlist.add(flow);
+            }
+        }
+       return flowlist;
+    }
+
+    /* From affinity link, create a nfc config. Pass this nfc config to nfchainagent. */
+    public Status addNfchain(AffinityLink al) {
+        List<Flow> flowlist = getFlowlist(al);
+        InetAddress waypoint = NetUtils.parseInetAddress(al.getWaypoint());
+        NFchainconfig nfcc = new NFchainconfig(al.getName(), flowlist, waypoint);
+        /* Only one hop initially... */
+        List<NFchainconfig> nfclist = new ArrayList<NFchainconfig>();
+        String key = al.getName();
+        nfclist.add(nfcc);
+        nfchainagent.addNfchain(key, nfclist);
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    public Status enableRedirect(AffinityLink al) throws Exception {
+        String nfccname = al.getName();
+        return nfchainagent.enable(nfccname);
+    }
 }
index bbf7cae1c1ac5f2540ae807ee3d02daaa56cc82e..5b073748d6f814c622f533a06d160c2aa2c00032 100644 (file)
@@ -275,7 +275,7 @@ public class AffinityNorthbound {
         AffinityLink al1 = affinityManager.getAffinityLink(affinityLinkName);
         al1.setWaypoint(waypointIP);
         try {
-            affinityManager.addFlowRulesForRedirect(al1);
+            affinityManager.enableRedirect(al1);
         } catch (Exception e) {
             String message = "An error occurred during flow programming.";
             log.error(message, e);
index a9085a0123e4655119ae3213c0d98792f1d77beb..9d935170f7b094c317077cc06f904b987812bbbe 100644 (file)
@@ -54,6 +54,9 @@ public class NfchainManager implements NfchainService, NfchainData {
     private final ExecutorService executor;
     private Future<RpcResult<Void>> currentTask;
 
+    private IFlowProgrammerService programmer = null;
+    private ISwitchManager switchManager = null;
+
     public NfchainManager() {
         executor = Executors.newFixedThreadPool(1);
     }
@@ -95,6 +98,78 @@ public class NfchainManager implements NfchainService, NfchainData {
         this.notificationProvider = salService;
     }
 
+    public void setFlowProgrammerService(IFlowProgrammerService s)
+    {
+        this.programmer = s;
+    }
+
+    public void unsetFlowProgrammerService(IFlowProgrammerService s) {
+        if (this.programmer == s) {
+            this.programmer = null;
+        }
+    }
+
+    void setSwitchManager(ISwitchManager s)
+    {
+        this.switchManager = s;
+    }
+
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            this.switchManager = null;
+        }
+    }
+
+
+    /* Include this once dependencies are correctly established in osgi. 
+    /** 
+     * Fetch all node connectors. Each switch port will receive a flow
+     * rule. Do not stop on error. Pass in the waypointMAC address so
+     * that the correct output port can be determined.
+     */
+    public Status pushFlowRule(InetAddress from, InetAddress to, byte [] waypointMAC) {
+        /* Get all node connectors. */
+        Set<Node> nodes = switchManager.getNodes();
+        Status success = new Status(StatusCode.SUCCESS);
+        Status notfound = new Status(StatusCode.NOTFOUND);
+
+        if (nodes == null) {
+            log.debug("No nodes in network.");
+            return success;
+        } 
+
+        /* Send this flow rule to all nodes in the network. */
+        for (Node node: nodes) {
+            List<Action> actions = new ArrayList<Action>();
+            Match match = new Match();
+            match.setField(new MatchField(MatchType.NW_SRC, from, null));
+            match.setField(new MatchField(MatchType.NW_DST, to, null));
+            match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());  
+        
+            Flow f = new Flow(match, actions);
+            f.setMatch(match);
+            f.setPriority(REDIRECT_IPSWITCH_PRIORITY);
+
+            /* Look up the output port leading to the waypoint. */
+            NodeConnector dst_connector = l2agent.lookup_output_port(node, waypointMAC);
+
+            log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
+            if (dst_connector != null) {
+                f.setActions(actions);
+                f.addAction(new Output(dst_connector));
+                log.debug("flow push flow = {} to node = {} ", f, node);
+                /*                Status status = installRedirectionFlow(node, flow);*/
+                Status status = programmer.addFlow(node, f);
+                if (!status.isSuccess()) {
+                    log.debug("Error during addFlow: {} on {}. The failure is: {}",
+                              f, node, status.getDescription());
+                }
+            }
+        }
+        return success;
+    }
+    */
+
     private class addGatewayTask implements Callable<RpcResult<Void>> {
 
         final AddInput input;
diff --git a/nfchainagent/pom.xml b/nfchainagent/pom.xml
new file mode 100644 (file)
index 0000000..1fb787b
--- /dev/null
@@ -0,0 +1,84 @@
+<?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>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+  </scm>
+
+  <groupId>org.opendaylight.affinity</groupId>
+  <artifactId>nfchainagent</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>${bundle.plugin.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.forwardingrulesmanager,
+              org.opendaylight.controller.hosttracker,
+              org.opendaylight.controller.hosttracker.hostAware,
+              org.opendaylight.controller.switchmanager,
+              org.opendaylight.controller.clustering.services,
+              org.opendaylight.controller.sal.action,
+              org.opendaylight.controller.sal.flowprogrammer,
+              org.opendaylight.controller.sal.match,
+              org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.routing,
+              org.opendaylight.controller.topologymanager,
+              org.apache.commons.lang3.builder,
+              org.opendaylight.affinity.l2agent,
+              org.junit;resolution:=optional,
+              org.slf4j,
+              org.apache.felix.dm,
+              javax.xml.bind.annotation
+            </Import-Package>
+            <Export-Package>
+              org.opendaylight.affinity.nfchainagent
+            </Export-Package>
+            <Bundle-Activator>
+              org.opendaylight.affinity.nfchainagent.Activator
+            </Bundle-Activator>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+      <version>0.4.0-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.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.affinity</groupId>
+      <artifactId>affinity</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/Activator.java b/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/Activator.java
new file mode 100644 (file)
index 0000000..2cfa61a
--- /dev/null
@@ -0,0 +1,103 @@
+
+/*
+ * 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
+ */
+
+/* Network function chaining service. */
+package org.opendaylight.affinity.nfchainagent;
+
+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.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+
+import org.opendaylight.affinity.l2agent.IfL2Agent;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+//import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+
+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 = { NFchainAgent.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(NFchainAgent.class)) {
+            // export the services
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "NFchainAgent");
+            c.setInterface(new String[] { IListenDataPacket.class.getName(),                    
+                                          NFchainAgent.class.getName() }, props);
+
+            // register dependent modules
+            c.add(createContainerServiceDependency(containerName)
+                  .setService(IfL2Agent.class)
+                  .setCallbacks("setL2Agent", "unsetL2Agent")
+                  .setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    ISwitchManager.class).setCallbacks("setSwitchManager",
+                    "unsetSwitchManager").setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IFlowProgrammerService.class).setCallbacks(
+                    "setFlowProgrammerService", "unsetFlowProgrammerService")
+                    .setRequired(true));
+        }
+    }
+}
diff --git a/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainAgent.java b/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainAgent.java
new file mode 100644 (file)
index 0000000..ae2183f
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013 Plexxi, Inc.  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.nfchainagent;
+
+import java.lang.Short;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+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 org.opendaylight.controller.sal.utils.NetUtils;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.affinity.affinity.IAffinityManager;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.sal.core.Host;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchField;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.packet.address.EthernetAddress;
+
+import org.opendaylight.affinity.l2agent.IfL2Agent;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+
+import java.io.Serializable;
+
+public class NFchainAgent implements Serializable {
+
+    private static final Logger log = LoggerFactory.getLogger(NFchainAgent.class);
+    private IFlowProgrammerService programmer = null;    
+    private IfL2Agent l2agent = null;
+    private IfIptoHost hostTracker = null;
+    private ISwitchManager switchManager = null;
+    
+    private HashMap<String, List<NFchainconfig>> allconfigs;
+
+    void init() {
+        log.debug("INIT called!");
+    }
+
+    void destroy() {
+        log.debug("DESTROY called!");
+    }
+
+    void start() {
+        log.debug("START called!");
+    }
+
+    void started(){
+    }
+
+    void stop() {
+        log.debug("STOP called!");
+    }
+
+    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 setFlowProgrammerService(IFlowProgrammerService s)
+    {
+        this.programmer = s;
+    }
+
+    public void unsetFlowProgrammerService(IFlowProgrammerService s) {
+        if (this.programmer == s) {
+            this.programmer = null;
+        }
+    }
+    void setL2Agent(IfL2Agent s)
+    {
+        log.info("Setting l2agent {}", s);
+        this.l2agent = s;
+    }
+
+    void unsetL2Agent(IfL2Agent s) {
+        if (this.l2agent == s) {
+            this.l2agent = null;
+        }
+    }
+
+    void setSwitchManager(ISwitchManager s)
+    {
+        this.switchManager = s;
+    }
+
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            this.switchManager = null;
+        }
+    }
+
+    public Status addNfchain(String key, List<NFchainconfig> nfclist) {
+       String name;
+
+        if (allconfigs == null) {
+            allconfigs = new HashMap<String, List<NFchainconfig>>();
+        }
+        /* xxx compute changelist and push flow changes. */
+       if (allconfigs.containsKey(key)) {
+           return new Status(StatusCode.CONFLICT,
+                             "NFchain with the specified name already configured.");
+       } 
+       List<NFchainconfig> oldcfg = allconfigs.get(key);
+       if (oldcfg == null) {
+           if (allconfigs.put(key, nfclist) == null) {
+                return new Status(StatusCode.SUCCESS); 
+           } 
+       }
+        return new Status(StatusCode.CONFLICT,
+                          "Unknown error during addNFchain.");
+    }
+
+    /** 
+     * add flow rules for set of flows in nfchainconfig. Do this for
+     * each node connector in the network proactively.
+     */
+    public Status addrules(Node node, NFchainconfig nfcc) throws Exception {
+        List<Flow> flowlist = nfcc.getFlowList();
+        for (Flow f: flowlist) {
+            HostNodeConnector wphost = (HostNodeConnector) hostTracker.hostFind(nfcc.getWaypointIP()); 
+            List<Action> actions = new ArrayList<Action>();
+            /* Look up the output port leading to the waypoint. */
+            NodeConnector dst_connector = l2agent.lookup_output_port(node, wphost.getDataLayerAddressBytes());
+
+            log.debug("Waypoint direction: node {} and connector {}", node, dst_connector);
+            if (dst_connector != null) {
+                f.setActions(actions);
+                f.addAction(new Output(dst_connector));
+                log.debug("flow push flow = {} to node = {} ", f, node);
+                Status status = programmer.addFlow(node, f);
+                if (!status.isSuccess()) {
+                    log.debug("Error during addFlow: {} on {}. The failure is: {}",
+                              f, node, status.getDescription());
+                }
+            }
+        }
+        return new Status(StatusCode.SUCCESS); 
+    }
+
+
+    /** 
+     * Enable the nfchain by programming flow rules on its behalf. 
+     */
+    public Status enable(String cfgname) throws Exception {
+        /* Get all node connectors. */
+        Set<Node> nodes = switchManager.getNodes();
+        NFchainconfig cfg = allconfigs.get(cfgname).get(0);
+
+        Status success = new Status(StatusCode.SUCCESS);
+        Status notfound = new Status(StatusCode.NOTFOUND);
+        Status ret;
+
+        if (nodes == null) {
+            log.debug("No nodes in network.");
+            return success;
+        } 
+
+        /* Send this flow rule to all nodes in the network. */
+        for (Node node: nodes) {
+            ret = addrules(node, cfg);
+        }
+        return new Status(StatusCode.SUCCESS);         
+    }
+}
+
diff --git a/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainconfig.java b/nfchainagent/src/main/java/org/opendaylight/affinity/nfchainagent/NFchainconfig.java
new file mode 100644 (file)
index 0000000..0a7211e
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.affinity.nfchainagent;
+
+import org.opendaylight.controller.sal.utils.NetUtils;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+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 javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+
+/** 
+ * Configuration object representing a network function chain. 
+ * flowlist is the set of flows to be redirected. 
+ * dstIP is the singleton waypoint, representing the waypoint server. 
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NFchainconfig implements Cloneable, Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @XmlAttribute
+    private String name;
+    @XmlElement
+    private final List<Flow> flowlist;
+    private InetAddress dstIP;
+    
+    public NFchainconfig(String name) {
+       this.name = name;
+       flowlist = new ArrayList<Flow>();
+        dstIP = null;
+    }
+
+    // Set the flowlist and destination IP of the network function. 
+    public NFchainconfig(String name, List<Flow> flowlist, InetAddress dstIP) {
+       this.name = name;
+       this.flowlist = flowlist;
+        this.dstIP = dstIP;
+    }
+
+    // add a flow to the flowlist. 
+    public Status addFlow(Flow f) {
+        flowlist.add(f);
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    public List<Flow> getFlowList() {
+        return this.flowlist;
+    }
+    public InetAddress getWaypointIP() {
+        return this.dstIP;
+    }
+    public void print() {
+       System.out.println("Printing NFchain config " + this.name);
+       for (Flow value : flowlist) {
+           System.out.println("flow is " + value);
+       }
+    }
+    public String getName() {
+       return name;
+    }
+}
+
+
diff --git a/pom.xml b/pom.xml
index 127e28f6f16f6eeb2496a5a31b84094fd4aca2f4..6c032e525469571c32771fa0ce36de3a97ea97c2 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
   </scm>
 
   <properties>
+    <bundle.plugin.version>2.3.7</bundle.plugin.version>
     <checkstyle.version>2.10</checkstyle.version>
     <commons.lang.version>3.1</commons.lang.version>
     <compiler.version>2.3.2</compiler.version>
@@ -58,7 +59,7 @@
       <module>analytics/integrationtest</module>
       <module>analytics/northbound</module>
       <module>l2agent</module>
-      <module>nfchain</module>
+      <module>nfchainagent</module>
     </modules>
 
     <repositories>