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;
* instantiated in order to get an fully working implementation
* Object
*/
+ @Override
public Object[] getImplementations() {
Object[] res = { ArpHandler.class };
return res;
* 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
"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",
}
}
- 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);
// 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);
}
}
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<IHostFinder> hostFinder = new CopyOnWriteArraySet<IHostFinder>();;
+ protected final Set<IHostFinder> hostFinders = new CopyOnWriteArraySet<IHostFinder>();
protected ConcurrentMap<IHostId, HostNodeConnector> hostsDB;
/*
* Following is a list of hosts which have been requested by NB APIs to be
}
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) {
* 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;
}
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);
}
for (Entry<IHostId, ARPPending> 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()));
}
}
* 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++;
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
logger.trace("ARPHandler is not avaialable, can't send the probe");
continue;
}
- for (IHostFinder hf : hostFinder) {
+ for (IHostFinder hf : hostFinders) {
hf.probe(host);
}
}
for (Entry<IHostId, ARPPending> 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);
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) {
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;
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
* instantiated in order to get an fully working implementation
* Object
*/
+ @Override
public Object[] getImplementations() {
Object[] res = { SimpleForwardingImpl.class,
SimpleBroadcastHandlerImpl.class };
* 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<String, Object> props = new Hashtable<String, Object>();
+ 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(
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<String, String> props = new Hashtable<String, String>();
props.put("salListenerName", "simplebroadcasthandler");
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;
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.
*/
lock.writeLock().unlock();
}
+ @Override
public void setMode(BroadcastMode m) {
lock.writeLock().lock();
mode = m;
package org.opendaylight.controller.samples.simpleforwarding.internal;
+import java.net.InetAddress;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
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;
* installs those rules using <tt>installPerHostRules()</tt>.
*/
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;
private Map<Node, List<FlowEntry>> tobePrunedPos = new HashMap<Node, List<FlowEntry>>();
private IClusterContainerServices clusterContainerService = null;
private ISwitchManager switchManager;
+ private IDataPacketService dataPacketService;
/**
* Return codes from the programming of the perHost rules in HW
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;
}
}
}
- public ITopologyManager getTopologyManager() {
- return topologyManager;
- }
-
public void setTopologyManager(ITopologyManager topologyManager) {
log.debug("Setting topologyManager");
this.topologyManager = topologyManager;
*
* @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<NodeConnector, FlowEntry> pos;
FlowEntry po;
for (Node swId : switches) {
List<FlowEntry> 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<FlowEntry> 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();
}
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);
+ }
+
+ }
+ }
}