X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fsamples%2Fsimpleforwarding%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsamples%2Fsimpleforwarding%2Finternal%2FSimpleBroadcastHandlerImpl.java;fp=opendaylight%2Fsamples%2Fsimpleforwarding%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsamples%2Fsimpleforwarding%2Finternal%2FSimpleBroadcastHandlerImpl.java;h=d2016b1f6337b6923662268ae7d8029d34ae85b0;hb=867026efeb7046076e7e0cf34b5ac2d18c54618b;hp=0000000000000000000000000000000000000000;hpb=a3dbf5335c352c7463674e31314ce2b5285cb6fe;p=controller.git diff --git a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java new file mode 100644 index 0000000000..d2016b1f63 --- /dev/null +++ b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleBroadcastHandlerImpl.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2013 IBM 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.controller.samples.simpleforwarding.internal; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +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.core.ConstructionException; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +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.utils.EtherTypes; +import org.opendaylight.controller.samples.simpleforwarding.IBroadcastHandler; +import org.opendaylight.controller.samples.simpleforwarding.IBroadcastPortSelector; +import org.opendaylight.controller.switchmanager.ISwitchManager; +import org.opendaylight.controller.topologymanager.ITopologyManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The simple broadcast handler simply sends broadcast packets out all ports + * that are not known to belong to an internal, i.e., switch-switch, link. Note + * that this is *not* safe in the general case when an OpenDaylight-controlled + * network has L2 peering with normal a normal L2 network. It is entirely + * possible for a packet to be flooded to a legacy/non-controlled switch and + * then be reflected back into the OpenDaylight-controlled region resulting in a + * loop. + */ +public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDataPacket { + + private static Logger log = LoggerFactory.getLogger(SimpleBroadcastHandlerImpl.class); + protected IDataPacketService dataPacketService = null; + protected ITopologyManager topoManager = null; + protected ISwitchManager swMgr = null; + protected IBroadcastPortSelector bcastPorts = null; + + protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + + BroadcastMode mode = BroadcastMode.DISABLED; + + @Override + public PacketResult receiveDataPacket(RawPacket inPkt) { + /* + * note that this assumes that the protocol plugin will do appropriate + * filtering to ensure that this only receives packets for it's + * container. + */ + + if (mode == BroadcastMode.DISABLED) { + return PacketResult.IGNORED; + } + + Packet decodedPkt = this.dataPacketService.decodeDataPacket(inPkt); + if (decodedPkt instanceof Ethernet) { + Ethernet eth = (Ethernet) decodedPkt; + + // TODO: should we offer an option to not handle ARP since the + // ARPHandler already does that + + // ignore LLDP + if (eth.getEtherType() != EtherTypes.LLDP.shortValue()) { + + if (eth.isBroadcast()) { + broadcastPacket(inPkt); + } else if (eth.isMulticast()) { + // TODO: for now just treat multicast as broadcast + broadcastPacket(inPkt); + } + } + } + + return PacketResult.KEEP_PROCESSING; + } + + @Override + public boolean broadcastPacket(RawPacket pkt) { + Set toPacketOut = new HashSet(); + + // make sure that topoManager/datPacketService aren't pulled out from + // under us + lock.readLock().lock(); + if (topoManager == null || dataPacketService == null + || swMgr == null) { + return false; + } + + // find all non-internal NodeConnectors + switch (mode) { + case DISABLED: + // intentionally blank; don't send the packet anywhere + break; + + case BROADCAST_TO_HOSTS: + toPacketOut.addAll(topoManager.getNodeConnectorWithHost()); + break; + + case BROADCAST_TO_NONINTERNAL: + for (Node n : swMgr.getNodes()) { + // getUpNodeConnectors will filter out NodeConnectors of type "SW" + for (NodeConnector nc : swMgr.getUpNodeConnectors(n)) { + if (!topoManager.isInternal(nc)) { + toPacketOut.add(nc); + } + } + } + break; + + case EXTERNAL_QUERY: + if (bcastPorts != null) { + toPacketOut.addAll(bcastPorts.getBroadcastPorts()); + } else { + log.error("Mode set to " + + BroadcastMode.EXTERNAL_QUERY + + ", but no external source of broadcast ports was provided."); + return false; + } + break; + + default: + log.error("Mode " + mode + " is not supported."); + break; + } + + // remove the NodeConnector it came in on + toPacketOut.remove(pkt.getIncomingNodeConnector()); + + // send it out all the node connectors + for (NodeConnector nc : toPacketOut) { + try { + RawPacket toSend = new RawPacket(pkt); + toSend.setOutgoingNodeConnector(nc); + dataPacketService.transmitDataPacket(toSend); + } catch (ConstructionException e) { + log.error("Could create packet: {}", e); + } + } + + lock.readLock().unlock(); + + return true; + } + + public void setDataPacketService(IDataPacketService s) { + // make sure dataPacketService doesn't change while we're in the middle + // of stuff + lock.writeLock().lock(); + this.dataPacketService = s; + lock.writeLock().unlock(); + } + + public void unsetDataPacketService(IDataPacketService s) { + // make sure dataPacketService doesn't change while we're in the middle + // of stuff + lock.writeLock().lock(); + if (this.dataPacketService == s) { + this.dataPacketService = null; + } + lock.writeLock().unlock(); + } + + public void setTopologyManager(ITopologyManager t) { + // make sure topoManager doesn't change while we're in the middle of + // stuff + lock.writeLock().lock(); + this.topoManager = t; + lock.writeLock().unlock(); + } + + public void unsetTopologyManager(ITopologyManager t) { + // make sure topoManager doesn't change while we're in the middle of + // stuff + lock.writeLock().lock(); + if (this.topoManager == t) { + this.topoManager = null; + } + lock.writeLock().unlock(); + } + + public void setSwitchManager(ISwitchManager i) { + lock.writeLock().lock(); + this.swMgr = i; + lock.writeLock().unlock(); + } + + public void unsetSwitchManager(ISwitchManager i) { + lock.writeLock().lock(); + if (this.swMgr == i) { + this.swMgr = null; + } + lock.writeLock().unlock(); + } + + public void setBroadcastPortSelector(IBroadcastPortSelector bps) { + lock.writeLock().lock(); + bcastPorts = bps; + lock.writeLock().unlock(); + } + + public void unsetBroadcastPortSelector(IBroadcastPortSelector bps) { + lock.writeLock().lock(); + if (bcastPorts == bps) { + this.bcastPorts = null; + } + lock.writeLock().unlock(); + } + + public void setMode(BroadcastMode m) { + lock.writeLock().lock(); + mode = m; + lock.writeLock().unlock(); + } + +}