<instructions>
<Import-Package>
org.opendaylight.affinity.affinity,
+ org.opendaylight.affinity.l2agent,
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.configuration,
org.opendaylight.controller.hosttracker,
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.packet,
org.opendaylight.controller.sal.inventory,
- org.opendaylight.controller.tutorial_L2_forwarding,
org.opendaylight.controller.sal.flowprogrammer,
org.opendaylight.controller.sal.match,
org.opendaylight.controller.sal.action,
<version>0.4.0-SNAPSHOT</version>
</dependency>
<dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>tutorial_L2_forwarding</artifactId>
+ <groupId>org.opendaylight.affinity</groupId>
+ <artifactId>l2agent</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
-import org.opendaylight.controller.tutorial_L2_forwarding.TutorialL2Forwarding;
+import org.opendaylight.affinity.l2agent.L2Agent;
import org.opendaylight.controller.switchmanager.ISwitchManager;
/**
"setFlowProgrammerService", "unsetFlowProgrammerService")
.setRequired(true));
c.add(createContainerServiceDependency(containerName).setService(
- TutorialL2Forwarding.class).setCallbacks(
+ L2Agent.class).setCallbacks(
"setL2AgentService", "unsetL2AgentService")
.setRequired(true));
c.add(createContainerServiceDependency(containerName).setService(
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.tutorial_L2_forwarding.TutorialL2Forwarding;
+import org.opendaylight.affinity.l2agent.L2Agent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private String affinityGroupFileName = null;
private IFlowProgrammerService fps = null;
private ISwitchManager switchManager = null;
- private TutorialL2Forwarding l2agent = null;
+ private L2Agent l2agent = null;
private ConcurrentMap<String, AffinityGroup> affinityGroupList;
private ConcurrentMap<String, AffinityLink> affinityLinkList;
this.fps = null;
}
}
- public void setL2Agent(TutorialL2Forwarding s)
+ public void setL2Agent(L2Agent s)
{
this.l2agent = s;
}
- public void unsetL2Agent(TutorialL2Forwarding s) {
+ public void unsetL2Agent(L2Agent s) {
if (this.l2agent == s) {
this.l2agent = null;
}
--- /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>l2agent</artifactId>
+ <version>0.4.0-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.slf4j
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.affinity.l2agent
+ </Export-Package>
+ <Bundle-Activator>
+ org.opendaylight.affinity.l2agent.Activator
+ </Bundle-Activator>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.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
+ */
+
+package org.opendaylight.affinity.l2agent;
+
+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;
+
+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 = { L2Agent.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(L2Agent.class)) {
+ // export the services
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "L2Agent");
+ c.setInterface(new String[] { IListenDataPacket.class.getName() }, props);
+
+ // register dependent modules
+ c.add(createContainerServiceDependency(containerName).setService(
+ ISwitchManager.class).setCallbacks("setSwitchManager",
+ "unsetSwitchManager").setRequired(true));
+
+ c.add(createContainerServiceDependency(containerName).setService(
+ IDataPacketService.class).setCallbacks(
+ "setDataPacketService", "unsetDataPacketService")
+ .setRequired(true));
+
+ c.add(createContainerServiceDependency(containerName).setService(
+ IFlowProgrammerService.class).setCallbacks(
+ "setFlowProgrammerService", "unsetFlowProgrammerService")
+ .setRequired(true));
+ }
+ }
+}
--- /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.l2agent;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.lang.String;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.packet.ARP;
+import org.opendaylight.controller.sal.packet.BitBufferHelper;
+import org.opendaylight.controller.sal.packet.Ethernet;
+import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.packet.Packet;
+import org.opendaylight.controller.sal.packet.PacketResult;
+import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.action.Flood;
+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.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.NetUtils;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.Subnet;
+
+public class L2Agent implements IListenDataPacket {
+ private static final Logger logger = LoggerFactory
+ .getLogger(L2Agent.class);
+ private ISwitchManager switchManager = null;
+ private IFlowProgrammerService programmer = null;
+ private IDataPacketService dataPacketService = null;
+ private Map<Long, NodeConnector> mac_to_port = new HashMap<Long, NodeConnector>();
+ private String function = "switch";
+
+ void setDataPacketService(IDataPacketService s) {
+ this.dataPacketService = s;
+ }
+
+ void unsetDataPacketService(IDataPacketService s) {
+ if (this.dataPacketService == s) {
+ this.dataPacketService = null;
+ }
+ }
+
+ public void setFlowProgrammerService(IFlowProgrammerService s)
+ {
+ this.programmer = s;
+ }
+
+ public void unsetFlowProgrammerService(IFlowProgrammerService s) {
+ if (this.programmer == s) {
+ this.programmer = null;
+ }
+ }
+
+ void setSwitchManager(ISwitchManager s) {
+ logger.debug("SwitchManager set");
+ this.switchManager = s;
+ }
+
+ void unsetSwitchManager(ISwitchManager s) {
+ if (this.switchManager == s) {
+ logger.debug("SwitchManager removed!");
+ this.switchManager = null;
+ }
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init() {
+ logger.info("Initialized");
+ }
+
+ /**
+ * 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() {
+ }
+
+ /**
+ * 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() {
+ logger.info("Started");
+ }
+
+ /**
+ * Function called by the dependency manager before the services
+ * exported by the component are unregistered, this will be
+ * followed by a "destroy ()" calls
+ *
+ */
+ void stop() {
+ logger.info("Stopped");
+ }
+
+ private void floodPacket(RawPacket inPkt) {
+ NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
+ Node incoming_node = incoming_connector.getNode();
+
+ Set<NodeConnector> nodeConnectors =
+ this.switchManager.getUpNodeConnectors(incoming_node);
+
+ for (NodeConnector p : nodeConnectors) {
+ if (!p.equals(incoming_connector)) {
+ try {
+ RawPacket destPkt = new RawPacket(inPkt);
+ destPkt.setOutgoingNodeConnector(p);
+ this.dataPacketService.transmitDataPacket(destPkt);
+ } catch (ConstructionException e2) {
+ continue;
+ }
+ }
+ }
+ }
+
+ @Override
+ public PacketResult receiveDataPacket(RawPacket inPkt) {
+ if (inPkt == null) {
+ return PacketResult.IGNORED;
+ }
+ logger.trace("Received a frame of size: {}",
+ inPkt.getPacketData().length);
+
+ Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
+ NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
+ Node incoming_node = incoming_connector.getNode();
+
+ if (formattedPak instanceof Ethernet) {
+ byte[] srcMAC = ((Ethernet)formattedPak).getSourceMACAddress();
+ byte[] dstMAC = ((Ethernet)formattedPak).getDestinationMACAddress();
+
+ // Hub implementation
+ if (function.equals("hub")) {
+ floodPacket(inPkt);
+ return PacketResult.CONSUME;
+ }
+
+ // Switch
+ else {
+ long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
+ long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
+
+ this.mac_to_port.put(srcMAC_val, incoming_connector);
+
+ Match match = new Match();
+ match.setField( new MatchField(MatchType.IN_PORT, incoming_connector) );
+ match.setField( new MatchField(MatchType.DL_DST, dstMAC.clone()) );
+
+ NodeConnector dst_connector;
+
+ // Do I know the destination MAC?
+ if ((dst_connector = this.mac_to_port.get(dstMAC_val)) != null) {
+ List<Action> actions = new ArrayList<Action>();
+ actions.add(new Output(dst_connector));
+
+ Flow f = new Flow(match, actions);
+
+ // Modify the flow on the network node
+ Status status = programmer.addFlow(incoming_node, f);
+ if (!status.isSuccess()) {
+ logger.warn(
+ "SDN Plugin failed to program the flow: {}. The failure is: {}",
+ f, status.getDescription());
+ return PacketResult.IGNORED;
+ }
+ logger.info("Installed flow {} in node {}",
+ f, incoming_node);
+ }
+ else
+ floodPacket(inPkt);
+ }
+ }
+ return PacketResult.IGNORED;
+ }
+
+ /*
+ * Return MAC adderss to port
+ */
+ public NodeConnector lookupMacAddress(byte[] macAddress) {
+ NodeConnector dst_connector;
+ return this.mac_to_port.get(macAddress);
+ }
+}
--- /dev/null
+\r
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.affinity.l2agent;\r
+\r
+\r
+import junit.framework.TestCase;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+\r
+public class L2AgentTest extends TestCase {\r
+\r
+ @Test\r
+ public void testL2AgentCreation() {\r
+\r
+ L2Agent ah = null;\r
+ ah = new L2Agent();\r
+ Assert.assertTrue(ah != null);\r
+\r
+ }\r
+\r
+}\r
<module>analytics/implementation</module>
<module>analytics/integrationtest</module>
<module>analytics/northbound</module>
+ <module>l2agent</module>
</modules>
<repositories>