2 * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
6 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
8 * This program and the accompanying materials are made available under the
9 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
10 * and is available at http://www.eclipse.org/legal/epl-v10.html
14 * Adapted from tutorial L2 forwarding demo (http://archive.openflow.org/).
16 package org.opendaylight.affinity.l2agent;
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20 import java.util.List;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashSet;
25 import java.lang.String;
27 import java.util.HashMap;
28 import java.util.Timer;
29 import java.util.TimerTask;
30 import java.util.concurrent.ConcurrentHashMap;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import org.opendaylight.controller.sal.core.ConstructionException;
36 import org.opendaylight.controller.sal.core.Node;
37 import org.opendaylight.controller.sal.core.NodeConnector;
38 import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
39 import org.opendaylight.controller.sal.flowprogrammer.Flow;
40 import org.opendaylight.controller.sal.packet.ARP;
41 import org.opendaylight.controller.sal.packet.BitBufferHelper;
42 import org.opendaylight.controller.sal.packet.Ethernet;
43 import org.opendaylight.controller.sal.packet.IDataPacketService;
44 import org.opendaylight.controller.sal.packet.IListenDataPacket;
45 import org.opendaylight.controller.sal.packet.Packet;
46 import org.opendaylight.controller.sal.packet.PacketResult;
47 import org.opendaylight.controller.sal.packet.RawPacket;
48 import org.opendaylight.controller.sal.action.Action;
49 import org.opendaylight.controller.sal.action.Output;
50 import org.opendaylight.controller.sal.action.Flood;
51 import org.opendaylight.controller.sal.match.Match;
52 import org.opendaylight.controller.sal.match.MatchType;
53 import org.opendaylight.controller.sal.match.MatchField;
54 import org.opendaylight.controller.sal.utils.EtherTypes;
55 import org.opendaylight.controller.sal.utils.Status;
56 import org.opendaylight.controller.sal.utils.NetUtils;
57 import org.opendaylight.controller.switchmanager.ISwitchManager;
58 import org.opendaylight.controller.switchmanager.Subnet;
60 public class L2Agent implements IListenDataPacket {
61 private static final Logger logger = LoggerFactory
62 .getLogger(L2Agent.class);
63 private ISwitchManager switchManager = null;
64 private IFlowProgrammerService programmer = null;
65 private IDataPacketService dataPacketService = null;
66 private Map<Long, NodeConnector> mac_to_port = new HashMap<Long, NodeConnector>();
67 private String function = "switch";
69 void setDataPacketService(IDataPacketService s) {
70 this.dataPacketService = s;
73 void unsetDataPacketService(IDataPacketService s) {
74 if (this.dataPacketService == s) {
75 this.dataPacketService = null;
79 public void setFlowProgrammerService(IFlowProgrammerService s)
84 public void unsetFlowProgrammerService(IFlowProgrammerService s) {
85 if (this.programmer == s) {
86 this.programmer = null;
90 void setSwitchManager(ISwitchManager s) {
91 logger.debug("SwitchManager set");
92 this.switchManager = s;
95 void unsetSwitchManager(ISwitchManager s) {
96 if (this.switchManager == s) {
97 logger.debug("SwitchManager removed!");
98 this.switchManager = null;
103 * Function called by the dependency manager when all the required
104 * dependencies are satisfied
108 logger.info("Initialized");
112 * Function called by the dependency manager when at least one
113 * dependency become unsatisfied or when the component is shutting
114 * down because for example bundle is being stopped.
121 * Function called by dependency manager after "init ()" is called
122 * and after the services provided by the class are registered in
123 * the service registry
127 logger.info("Started");
131 * Function called by the dependency manager before the services
132 * exported by the component are unregistered, this will be
133 * followed by a "destroy ()" calls
137 logger.info("Stopped");
140 private void floodPacket(RawPacket inPkt) {
141 NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
142 Node incoming_node = incoming_connector.getNode();
144 Set<NodeConnector> nodeConnectors =
145 this.switchManager.getUpNodeConnectors(incoming_node);
147 for (NodeConnector p : nodeConnectors) {
148 if (!p.equals(incoming_connector)) {
150 RawPacket destPkt = new RawPacket(inPkt);
151 destPkt.setOutgoingNodeConnector(p);
152 this.dataPacketService.transmitDataPacket(destPkt);
153 } catch (ConstructionException e2) {
161 public PacketResult receiveDataPacket(RawPacket inPkt) {
163 return PacketResult.IGNORED;
165 logger.trace("Received a frame of size: {}",
166 inPkt.getPacketData().length);
168 Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
169 NodeConnector incoming_connector = inPkt.getIncomingNodeConnector();
170 Node incoming_node = incoming_connector.getNode();
172 if (formattedPak instanceof Ethernet) {
173 byte[] srcMAC = ((Ethernet)formattedPak).getSourceMACAddress();
174 byte[] dstMAC = ((Ethernet)formattedPak).getDestinationMACAddress();
176 // Hub implementation
177 if (function.equals("hub")) {
179 return PacketResult.CONSUME;
184 long srcMAC_val = BitBufferHelper.toNumber(srcMAC);
185 long dstMAC_val = BitBufferHelper.toNumber(dstMAC);
187 this.mac_to_port.put(srcMAC_val, incoming_connector);
189 Match match = new Match();
190 match.setField( new MatchField(MatchType.IN_PORT, incoming_connector) );
191 match.setField( new MatchField(MatchType.DL_DST, dstMAC.clone()) );
193 NodeConnector dst_connector;
195 // Do I know the destination MAC?
196 if ((dst_connector = this.mac_to_port.get(dstMAC_val)) != null) {
197 List<Action> actions = new ArrayList<Action>();
198 actions.add(new Output(dst_connector));
200 Flow f = new Flow(match, actions);
202 // Modify the flow on the network node
203 Status status = programmer.addFlow(incoming_node, f);
204 if (!status.isSuccess()) {
206 "SDN Plugin failed to program the flow: {}. The failure is: {}",
207 f, status.getDescription());
208 return PacketResult.IGNORED;
210 logger.info("Installed flow {} in node {}",
217 return PacketResult.IGNORED;
221 * Return MAC adderss to port
223 public NodeConnector lookupMacAddress(byte[] macAddress) {
224 NodeConnector dst_connector;
225 return this.mac_to_port.get(macAddress);