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>
*/
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);
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();
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);
}
<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>
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
.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")
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;
private String affinityGroupFileName = null;
// private IForwardingRulesManager ruleManager;
private IFlowProgrammerService programmer = null;
+ private NFchainAgent nfchainagent = null;
private ISwitchManager switchManager = null;
private IfL2Agent l2agent = null;
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);
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);
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);
+ }
}
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);
private final ExecutorService executor;
private Future<RpcResult<Void>> currentTask;
+ private IFlowProgrammerService programmer = null;
+ private ISwitchManager switchManager = null;
+
public NfchainManager() {
executor = Executors.newFixedThreadPool(1);
}
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;
--- /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>
+ <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>
--- /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
+ */
+
+/* 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));
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
+
--- /dev/null
+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;
+ }
+}
+
+
</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>
<module>analytics/integrationtest</module>
<module>analytics/northbound</module>
<module>l2agent</module>
- <module>nfchain</module>
+ <module>nfchainagent</module>
</modules>
<repositories>