From: Yevgeny Khodorkovsky Date: Mon, 10 Mar 2014 19:49:39 +0000 (-0500) Subject: Moving simple fwding logic from ARPHandler into SimpleForwarding X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~321^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=9424e5125b6557606415eaa92a7c25b4b4e1e864 Moving simple fwding logic from ARPHandler into SimpleForwarding - Per Colin's idea, moving reactive fwding logic into SimpleForwarding - SimpleForwarding listens to packet-in. Forwards IP packets between known hosts to dest (assuming a simple path will be installed). - Some cleanup and debug stmts Change-Id: Ib0f29af34d6dead26f7393b4238d62fe1935ecdf Signed-off-by: Colin Dixon Signed-off-by: Yevgeny Khodorkovsky --- diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java index b253179c87..b7639bed2b 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java @@ -24,7 +24,6 @@ import org.opendaylight.controller.hosttracker.hostAware.IHostFinder; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; import org.opendaylight.controller.sal.packet.IDataPacketService; import org.opendaylight.controller.sal.packet.IListenDataPacket; -import org.opendaylight.controller.sal.routing.IRouting; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.topologymanager.ITopologyManager; import org.slf4j.Logger; @@ -44,6 +43,7 @@ public class Activator extends ComponentActivatorAbstractBase { * instantiated in order to get an fully working implementation * Object */ + @Override public Object[] getImplementations() { Object[] res = { ArpHandler.class }; return res; @@ -62,6 +62,7 @@ public class Activator extends ComponentActivatorAbstractBase { * also optional per-container different behavior if needed, usually * should not be the case though. */ + @Override public void configureInstance(Component c, Object imp, String containerName) { if (imp.equals(ArpHandler.class)) { // export the service @@ -100,10 +101,6 @@ public class Activator extends ComponentActivatorAbstractBase { "setClusterContainerService", "unsetClusterContainerService") .setRequired(true)); - c.add(createContainerServiceDependency(containerName).setService( - IRouting.class).setCallbacks("setRouting","unsetRouting") - .setRequired(false)); - // the Host Listener is optional c.add(createContainerServiceDependency(containerName).setService( IfHostListener.class).setCallbacks("setHostListener", diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java index fa883829cc..083e2ed0e9 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java @@ -113,16 +113,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } } - void setRouting(IRouting r) { - this.routing = r; - } - - void unsetRouting(IRouting r) { - if (this.routing == r) { - this.routing = null; - } - } - void setHostListener(IfHostListener s) { if (this.hostListeners != null) { this.hostListeners.add(s); @@ -507,41 +497,18 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA // see if we know about the host // Hosttracker hosts db key implementation - IHostId id = HostIdFactory.create(dIP, null); - HostNodeConnector host = hostTracker.hostFind(id); + HostNodeConnector host = hostTracker.hostFind(dIP); if (host == null) { - // if we don't, know about the host, try to find it + // if we don't know about the host, try to find it log.trace("Punted IP pkt to {}, sending bcast ARP event...", dIP); /* * unknown destination host, initiate bcast ARP request */ arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false); - } else if (routing == null || routing.getRoute(p.getNode(), host.getnodeconnectorNode()) != null) { - /* - * if IRouting is available, make sure that this packet can get it's - * destination normally before teleporting it there. If it's not - * available, then assume it's reachable. - * - * TODO: come up with a way to do this in the absence of IRouting - */ - - log.trace("forwarding punted IP pkt to {} received at {}", dIP, p); - - /* - * if we know where the host is and there's a path from where this - * packet was punted to where the host is, then deliver it to the - * host for now - */ - NodeConnector nc = host.getnodeConnector(); - - // re-encode the Ethernet packet (the parent of the IPv4 packet) - RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent()); - rp.setOutgoingNodeConnector(nc); - this.dataPacketService.transmitDataPacket(rp); } else { - log.trace("ignoring punted IP pkt to {} because there is no route from {}", dIP, p); + log.trace("Ignoring punted IP pkt to known host: {} (received on: {})", dIP, p); } } diff --git a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java index 734a392bc1..ce49b599e1 100644 --- a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java +++ b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java @@ -105,7 +105,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw static final String ACTIVE_HOST_CACHE = "hosttracker.ActiveHosts"; static final String INACTIVE_HOST_CACHE = "hosttracker.InactiveHosts"; private static final Logger logger = LoggerFactory.getLogger(HostTracker.class); - protected final Set hostFinder = new CopyOnWriteArraySet();; + protected final Set hostFinders = new CopyOnWriteArraySet(); protected ConcurrentMap hostsDB; /* * Following is a list of hosts which have been requested by NB APIs to be @@ -256,16 +256,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } public void setArpHandler(IHostFinder hostFinder) { - if (this.hostFinder != null) { - this.hostFinder.add(hostFinder); - } + this.hostFinders.add(hostFinder); } public void unsetArpHandler(IHostFinder hostFinder) { - if (this.hostFinder != null) { - logger.debug("Arp Handler Service removed!"); - this.hostFinder.remove(hostFinder); - } + logger.debug("Arp Handler Service removed!"); + this.hostFinders.remove(hostFinder); } public void setTopologyManager(ITopologyManager s) { @@ -352,8 +348,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * already handles the null return */ - if (hostFinder == null) { - logger.debug("Exiting hostFind, null hostFinder"); + if (hostFinders.isEmpty()) { + logger.debug("No available host finders, exiting hostFind()"); return null; } @@ -369,7 +365,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...", id); /* host is not found, initiate a discovery */ - for (IHostFinder hf : hostFinder) { + for (IHostFinder hf : hostFinders) { InetAddress addr = decodeIPFromId(id); hf.find(addr); } @@ -936,12 +932,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw for (Entry entry : failedARPReqList.entrySet()) { ARPPending arphost; arphost = entry.getValue(); - if (hostFinder == null) { - logger.warn("ARPHandler Services are not available on subnet addition"); + if (hostFinders.isEmpty()) { + logger.debug("ARPHandler Services are not available on subnet addition"); continue; } logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", decodeIPFromId(arphost.getHostId())); - for (IHostFinder hf : hostFinder) { + for (IHostFinder hf : hostFinders) { hf.find(decodeIPFromId(arphost.getHostId())); } } @@ -977,11 +973,11 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * next one. Before sending the ARP, check if ARPHandler * is available or not */ - if (hostFinder == null) { + if (hostFinders.isEmpty()) { logger.warn("ARPHandler Services are not available for Outstanding ARPs"); continue; } - for (IHostFinder hf : hostFinder) { + for (IHostFinder hf : hostFinders) { hf.find(decodeIPFromId(arphost.getHostId())); } arphost.sent_count++; @@ -1063,7 +1059,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw HexEncode.bytesToHexString(host.getDataLayerAddressBytes()) }); } host.setArpSendCountDown(arp_cntdown); - if (hostFinder == null) { + if (hostFinders.isEmpty()) { /* * If hostfinder is not available, then can't send * the probe. However, continue the age out the @@ -1073,7 +1069,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.trace("ARPHandler is not avaialable, can't send the probe"); continue; } - for (IHostFinder hf : hostFinder) { + for (IHostFinder hf : hostFinders) { hf.probe(host); } } @@ -1417,7 +1413,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw for (Entry entry : failedARPReqList.entrySet()) { arphost = entry.getValue(); logger.trace("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostId()); - if (hostFinder == null) { + if (hostFinders.isEmpty()) { logger.warn("ARPHandler is not available at interface up"); logger.warn("Since this event is missed, host(s) connected to interface {} may not be discovered", nodeConnector); @@ -1430,7 +1426,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw byte[] dataLayerAddress = NetUtils.getBroadcastMACAddr(); host = new HostNodeConnector(dataLayerAddress, decodeIPFromId(arphost.getHostId()), nodeConnector, (short) 0); - for (IHostFinder hf : hostFinder) { + for (IHostFinder hf : hostFinders) { hf.probe(host); } } catch (ConstructionException e) { diff --git a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/Activator.java b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/Activator.java index 1a71511ef5..ed9374b6fa 100644 --- a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/Activator.java +++ b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/Activator.java @@ -13,9 +13,6 @@ import java.util.Dictionary; import java.util.Hashtable; import org.apache.felix.dm.Component; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager; import org.opendaylight.controller.hosttracker.IfIptoHost; @@ -30,6 +27,8 @@ import org.opendaylight.controller.samples.simpleforwarding.IBroadcastPortSelect import org.opendaylight.controller.switchmanager.IInventoryListener; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.topologymanager.ITopologyManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Activator extends ComponentActivatorAbstractBase { protected static final Logger logger = LoggerFactory @@ -45,6 +44,7 @@ public class Activator extends ComponentActivatorAbstractBase { * instantiated in order to get an fully working implementation * Object */ + @Override public Object[] getImplementations() { Object[] res = { SimpleForwardingImpl.class, SimpleBroadcastHandlerImpl.class }; @@ -64,12 +64,17 @@ public class Activator extends ComponentActivatorAbstractBase { * also optional per-container different behavior if needed, usually * should not be the case though. */ + @Override public void configureInstance(Component c, Object imp, String containerName) { if (imp.equals(SimpleForwardingImpl.class)) { + Dictionary props = new Hashtable(); + props.put("salListenerName", "simpleforwarding"); + // export the service c.setInterface(new String[] { IInventoryListener.class.getName(), IfNewHostNotify.class.getName(), - IListenRoutingUpdates.class.getName() }, null); + IListenRoutingUpdates.class.getName(), + IListenDataPacket.class.getName() }, props); c.add(createContainerServiceDependency(containerName).setService( IClusterContainerServices.class).setCallbacks( @@ -96,7 +101,11 @@ public class Activator extends ComponentActivatorAbstractBase { c.add(createContainerServiceDependency(containerName).setService( IRouting.class).setCallbacks("setRouting", "unsetRouting") .setRequired(false)); - }else if (imp.equals(SimpleBroadcastHandlerImpl.class)) { + c.add(createContainerServiceDependency(containerName).setService( + IDataPacketService.class).setCallbacks("setDataPacketService", + "unsetDataPacketService").setRequired(false)); + + } else if (imp.equals(SimpleBroadcastHandlerImpl.class)) { Dictionary props = new Hashtable(); props.put("salListenerName", "simplebroadcasthandler"); 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 index d2016b1f63..e39ae65693 100644 --- 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 @@ -12,12 +12,12 @@ 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.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; @@ -54,7 +54,7 @@ public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDat 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 + * filtering to ensure that this only receives packets for its * container. */ @@ -216,6 +216,7 @@ public class SimpleBroadcastHandlerImpl implements IBroadcastHandler, IListenDat lock.writeLock().unlock(); } + @Override public void setMode(BroadcastMode m) { lock.writeLock().lock(); mode = m; diff --git a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java index 4b3363b832..b9d8fee986 100644 --- a/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java +++ b/opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.samples.simpleforwarding.internal; +import java.net.InetAddress; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; @@ -45,9 +46,17 @@ import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; +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.IPv4; +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.routing.IListenRoutingUpdates; import org.opendaylight.controller.sal.routing.IRouting; import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.samples.simpleforwarding.HostNodePair; @@ -70,11 +79,10 @@ import org.slf4j.LoggerFactory; * installs those rules using installPerHostRules(). */ public class SimpleForwardingImpl implements IfNewHostNotify, - IListenRoutingUpdates, IInventoryListener { - private static Logger log = LoggerFactory - .getLogger(SimpleForwardingImpl.class); + IListenRoutingUpdates, IInventoryListener, IListenDataPacket { + private static Logger log = LoggerFactory.getLogger(SimpleForwardingImpl.class); private static short DEFAULT_IPSWITCH_PRIORITY = 1; - private static String FORWARDING_RULES_CACHE_NAME = "forwarding.ipswitch.rules"; + static final String FORWARDING_RULES_CACHE_NAME = "forwarding.ipswitch.rules"; private IfIptoHost hostTracker; private IForwardingRulesManager frm; private ITopologyManager topologyManager; @@ -90,6 +98,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, private Map> tobePrunedPos = new HashMap>(); private IClusterContainerServices clusterContainerService = null; private ISwitchManager switchManager; + private IDataPacketService dataPacketService; /** * Return codes from the programming of the perHost rules in HW @@ -97,8 +106,19 @@ public class SimpleForwardingImpl implements IfNewHostNotify, public enum RulesProgrammingReturnCode { SUCCESS, FAILED_FEW_SWITCHES, FAILED_ALL_SWITCHES, FAILED_WRONG_PARAMS } + public void setDataPacketService(IDataPacketService s) { + log.debug("Setting dataPacketService"); + this.dataPacketService = s; + } + + public void unsetDataPacketService(IDataPacketService s) { + if (this.dataPacketService == s) { + this.dataPacketService = null; + } + } public void setRouting(IRouting routing) { + log.debug("Setting routing"); this.routing = routing; } @@ -108,10 +128,6 @@ public class SimpleForwardingImpl implements IfNewHostNotify, } } - public ITopologyManager getTopologyManager() { - return topologyManager; - } - public void setTopologyManager(ITopologyManager topologyManager) { log.debug("Setting topologyManager"); this.topologyManager = topologyManager; @@ -670,8 +686,7 @@ public class SimpleForwardingImpl implements IfNewHostNotify, * * @return a return code that convey the programming status of the HW */ - private RulesProgrammingReturnCode uninstallPerHostRules( - HostNodeConnector host) { + private RulesProgrammingReturnCode uninstallPerHostRules(HostNodeConnector host) { RulesProgrammingReturnCode retCode = RulesProgrammingReturnCode.SUCCESS; Map pos; FlowEntry po; @@ -768,16 +783,12 @@ public class SimpleForwardingImpl implements IfNewHostNotify, for (Node swId : switches) { List pl = tobePrunedPos.get(swId); if (pl != null) { - log - .debug( - "Policies for Switch: {} in the list to be deleted: {}", - swId, pl); + log.debug("Policies for Switch: {} in the list to be deleted: {}", swId, pl); Iterator plIter = pl.iterator(); //for (Policy po: pl) { while (plIter.hasNext()) { FlowEntry po = plIter.next(); - log.error("Removing Policy, Switch: {} Policy: {}", swId, - po); + log.error("Removing Policy, Switch: {} Policy: {}", swId, po); this.frm.uninstallFlowEntry(po); plIter.remove(); } @@ -962,4 +973,56 @@ public class SimpleForwardingImpl implements IfNewHostNotify, this.switchManager = null; } } + + @Override + public PacketResult receiveDataPacket(RawPacket inPkt) { + if (inPkt == null) { + return PacketResult.IGNORED; + } + log.trace("Received a frame of size: {}", inPkt.getPacketData().length); + Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt); + if (formattedPak instanceof Ethernet) { + Object nextPak = formattedPak.getPayload(); + if (nextPak instanceof IPv4) { + log.trace("Handle punted IP packet: {}", formattedPak); + handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector()); + } + } + return PacketResult.IGNORED; + + } + + private void handlePuntedIPPacket(IPv4 pkt, NodeConnector incomingNodeConnector) { + InetAddress dIP = NetUtils.getInetAddress(pkt.getDestinationAddress()); + if (dIP == null || hostTracker == null) { + log.debug("Invalid param(s) in handlePuntedIPPacket.. DestIP: {}. hostTracker: {}", dIP, hostTracker); + return; + } + HostNodeConnector destHost = hostTracker.hostFind(dIP); + if (destHost != null + && (routing == null || + routing.getRoute(incomingNodeConnector.getNode(), destHost.getnodeconnectorNode()) != null)) { + + log.trace("Host {} is at {}", dIP, destHost.getnodeConnector()); + HostNodePair key = new HostNodePair(destHost, incomingNodeConnector.getNode()); + + // If SimpleForwarding is aware of this host, it will try to install + // a path. Forward packet until it's done. + if (dataPacketService != null && this.rulesDB.containsKey(key)) { + + + /* + * if we know where the host is and there's a path from where this + * packet was punted to where the host is, then attempt best effort delivery to the host + */ + NodeConnector nc = destHost.getnodeConnector(); + log.trace("Forwarding punted IP received at {} to {}", incomingNodeConnector, nc); + // re-encode the Ethernet packet (the parent of the IPv4 packet) + RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent()); + rp.setOutgoingNodeConnector(nc); + this.dataPacketService.transmitDataPacket(rp); + } + + } + } }