2 * Copyright (c) 2013 IBM and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.samples.simpleforwarding.internal;
11 import java.util.HashSet;
13 import java.util.concurrent.locks.ReentrantReadWriteLock;
15 import org.opendaylight.controller.sal.core.ConstructionException;
16 import org.opendaylight.controller.sal.core.Node;
17 import org.opendaylight.controller.sal.core.NodeConnector;
18 import org.opendaylight.controller.sal.packet.Ethernet;
19 import org.opendaylight.controller.sal.packet.IDataPacketService;
20 import org.opendaylight.controller.sal.packet.IListenDataPacket;
21 import org.opendaylight.controller.sal.packet.Packet;
22 import org.opendaylight.controller.sal.packet.PacketResult;
23 import org.opendaylight.controller.sal.packet.RawPacket;
24 import org.opendaylight.controller.sal.utils.EtherTypes;
25 import org.opendaylight.controller.samples.simpleforwarding.IBroadcastHandler;
26 import org.opendaylight.controller.samples.simpleforwarding.IBroadcastPortSelector;
27 import org.opendaylight.controller.switchmanager.ISwitchManager;
28 import org.opendaylight.controller.topologymanager.ITopologyManager;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * The simple broadcast handler simply sends broadcast packets out all ports
34 * that are not known to belong to an internal, i.e., switch-switch, link. Note
35 * that this is *not* safe in the general case when an OpenDaylight-controlled
36 * network has L2 peering with normal a normal L2 network. It is entirely
37 * possible for a packet to be flooded to a legacy/non-controlled switch and
38 * then be reflected back into the OpenDaylight-controlled region resulting in a
41 public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDataPacket {
43 private static Logger log = LoggerFactory.getLogger(SimpleBroadcastHandlerImpl.class);
44 protected IDataPacketService dataPacketService = null;
45 protected ITopologyManager topoManager = null;
46 protected ISwitchManager swMgr = null;
47 protected IBroadcastPortSelector bcastPorts = null;
49 protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
51 BroadcastMode mode = BroadcastMode.DISABLED;
54 public PacketResult receiveDataPacket(RawPacket inPkt) {
56 * note that this assumes that the protocol plugin will do appropriate
57 * filtering to ensure that this only receives packets for its
61 if (mode == BroadcastMode.DISABLED) {
62 return PacketResult.IGNORED;
65 Packet decodedPkt = this.dataPacketService.decodeDataPacket(inPkt);
66 if (decodedPkt instanceof Ethernet) {
67 Ethernet eth = (Ethernet) decodedPkt;
69 // TODO: should we offer an option to not handle ARP since the
70 // ARPHandler already does that
73 if (eth.getEtherType() != EtherTypes.LLDP.shortValue()) {
75 if (eth.isBroadcast()) {
76 broadcastPacket(inPkt);
77 } else if (eth.isMulticast()) {
78 // TODO: for now just treat multicast as broadcast
79 broadcastPacket(inPkt);
84 return PacketResult.KEEP_PROCESSING;
88 public boolean broadcastPacket(RawPacket pkt) {
89 Set<NodeConnector> toPacketOut = new HashSet<NodeConnector>();
91 // make sure that topoManager/datPacketService aren't pulled out from
93 lock.readLock().lock();
94 if (topoManager == null || dataPacketService == null
96 lock.readLock().unlock();
100 // find all non-internal NodeConnectors
103 // intentionally blank; don't send the packet anywhere
106 case BROADCAST_TO_HOSTS:
107 toPacketOut.addAll(topoManager.getNodeConnectorWithHost());
110 case BROADCAST_TO_NONINTERNAL:
111 for (Node n : swMgr.getNodes()) {
112 // getUpNodeConnectors will filter out NodeConnectors of type "SW"
113 for (NodeConnector nc : swMgr.getUpNodeConnectors(n)) {
114 if (!topoManager.isInternal(nc)) {
122 if (bcastPorts != null) {
123 toPacketOut.addAll(bcastPorts.getBroadcastPorts());
125 log.error("Mode set to "
126 + BroadcastMode.EXTERNAL_QUERY
127 + ", but no external source of broadcast ports was provided.");
128 lock.readLock().unlock();
134 log.error("Mode " + mode + " is not supported.");
138 // remove the NodeConnector it came in on
139 toPacketOut.remove(pkt.getIncomingNodeConnector());
141 // send it out all the node connectors
142 for (NodeConnector nc : toPacketOut) {
144 RawPacket toSend = new RawPacket(pkt);
145 toSend.setOutgoingNodeConnector(nc);
146 dataPacketService.transmitDataPacket(toSend);
147 } catch (ConstructionException e) {
148 log.error("Could create packet: {}", e);
152 lock.readLock().unlock();
157 public void setDataPacketService(IDataPacketService s) {
158 // make sure dataPacketService doesn't change while we're in the middle
160 lock.writeLock().lock();
161 this.dataPacketService = s;
162 lock.writeLock().unlock();
165 public void unsetDataPacketService(IDataPacketService s) {
166 // make sure dataPacketService doesn't change while we're in the middle
168 lock.writeLock().lock();
169 if (this.dataPacketService == s) {
170 this.dataPacketService = null;
172 lock.writeLock().unlock();
175 public void setTopologyManager(ITopologyManager t) {
176 // make sure topoManager doesn't change while we're in the middle of
178 lock.writeLock().lock();
179 this.topoManager = t;
180 lock.writeLock().unlock();
183 public void unsetTopologyManager(ITopologyManager t) {
184 // make sure topoManager doesn't change while we're in the middle of
186 lock.writeLock().lock();
187 if (this.topoManager == t) {
188 this.topoManager = null;
190 lock.writeLock().unlock();
193 public void setSwitchManager(ISwitchManager i) {
194 lock.writeLock().lock();
196 lock.writeLock().unlock();
199 public void unsetSwitchManager(ISwitchManager i) {
200 lock.writeLock().lock();
201 if (this.swMgr == i) {
204 lock.writeLock().unlock();
207 public void setBroadcastPortSelector(IBroadcastPortSelector bps) {
208 lock.writeLock().lock();
210 lock.writeLock().unlock();
213 public void unsetBroadcastPortSelector(IBroadcastPortSelector bps) {
214 lock.writeLock().lock();
215 if (bcastPorts == bps) {
216 this.bcastPorts = null;
218 lock.writeLock().unlock();
222 public void setMode(BroadcastMode m) {
223 lock.writeLock().lock();
225 lock.writeLock().unlock();