<tag>HEAD</tag>
</scm>
<artifactId>arphandler</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<build>
<configuration>
<instructions>
<Import-Package>
+ org.opendaylight.controller.sal.packet.address,
org.opendaylight.controller.connectionmanager,
org.opendaylight.controller.sal.connection,
org.opendaylight.controller.sal.core,
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
+import org.opendaylight.controller.hosttracker.HostIdFactory;
+import org.opendaylight.controller.hosttracker.IHostId;
import org.opendaylight.controller.hosttracker.IfHostListener;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
private BlockingQueue<ARPCacheEvent> ARPCacheEvents = new LinkedBlockingQueue<ARPCacheEvent>();
private Thread cacheEventHandler;
private boolean stopping = false;
+
/*
* A cluster allocated cache. Used for synchronizing ARP request/reply
- * events across all cluster controllers. To raise an event, we put() a specific
- * event object (as key) and all nodes handle it in the entryUpdated callback.
+ * events across all cluster controllers. To raise an event, we put() a
+ * specific event object (as key) and all nodes handle it in the
+ * entryUpdated callback.
*
* In case of ARPReply, we put true value to send replies to any requestors
* by calling generateAndSendReply
*/
private ConcurrentMap<ARPEvent, Boolean> arpRequestReplyEvent;
- void setConnectionManager(IConnectionManager cm){
+ void setConnectionManager(IConnectionManager cm) {
this.connectionManager = cm;
}
- void unsetConnectionManager(IConnectionManager cm){
- if (this.connectionManager == cm){
+ void unsetConnectionManager(IConnectionManager cm) {
+ if (this.connectionManager == cm) {
connectionManager = null;
}
}
- void setClusterContainerService(IClusterContainerServices s){
+ void setClusterContainerService(IClusterContainerServices s) {
this.clusterContainerService = s;
}
}
}
- protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP,
- byte[] tMAC, InetAddress tIP) {
+ protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP, byte[] tMAC, InetAddress tIP) {
byte[] senderIP = sIP.getAddress();
byte[] targetIP = tIP.getAddress();
- ARP arp = createARP(ARP.REPLY,sMAC,senderIP,tMAC,targetIP);
+ ARP arp = createARP(ARP.REPLY, sMAC, senderIP, tMAC, targetIP);
Ethernet ethernet = createEthernet(sMAC, tMAC, arp);
// Make sure that the host is a legitimate member of this subnet
if (!subnet.hasNodeConnector(p)) {
- log.debug("{} showing up on {} does not belong to {}",
- new Object[] { sourceIP, p, subnet });
+ log.debug("{} showing up on {} does not belong to {}", new Object[] { sourceIP, p, subnet });
return;
}
}
/*
- * OpCode != request -> ARP Reply. If there are hosts (in
- * arpRequestors) waiting for the ARP reply for this sourceIP, it's
- * time to generate the reply and send it to these hosts.
+ * OpCode != request -> ARP Reply. If there are hosts (in arpRequestors)
+ * waiting for the ARP reply for this sourceIP, it's time to generate
+ * the reply and send it to these hosts.
*
* If sourceIP==targetIP, it is a Gratuitous ARP. If there are hosts (in
* arpRequestors) waiting for the ARP reply for this sourceIP, it's time
*/
if (pkt.getOpCode() != ARP.REQUEST || sourceIP.equals(targetIP)) {
- // Raise a reply event so that any waiting requestors will be sent a reply
- // the true value indicates we should generate replies to requestors across the cluster
+ // Raise a reply event so that any waiting requestors will be sent a
+ // reply
+ // the true value indicates we should generate replies to requestors
+ // across the cluster
log.trace("Received ARP reply packet from {}, reply to all requestors.", sourceIP);
arpRequestReplyEvent.put(new ARPReply(sourceIP, sourceMAC), true);
return;
}
/*
- * ARP Request Handling:
- * If targetIP is the IP of the subnet, reply with ARP REPLY
- * If targetIP is a known host, PROXY ARP (by sending ARP REPLY) on behalf of known target hosts.
- * For unknown target hosts, generate and send an ARP request to ALL switches/ports using
- * the IP address defined in the subnet as source address
+ * ARP Request Handling: If targetIP is the IP of the subnet, reply with
+ * ARP REPLY If targetIP is a known host, PROXY ARP (by sending ARP
+ * REPLY) on behalf of known target hosts. For unknown target hosts,
+ * generate and send an ARP request to ALL switches/ports using the IP
+ * address defined in the subnet as source address
*/
/*
* If target IP is gateway IP, Send ARP reply
*/
if ((targetIP.equals(subnet.getNetworkAddress()))
&& (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(targetMAC, getControllerMAC()))) {
- if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL){
- if (log.isTraceEnabled()){
+ if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) {
+ if (log.isTraceEnabled()) {
log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}",
HexEncode.bytesToHexString(getControllerMAC()));
}
return;
}
-
- HostNodeConnector host = hostTracker.hostQuery(targetIP);
+ // Hosttracker hosts db key implementation
+ IHostId id = HostIdFactory.create(targetIP, null);
+ HostNodeConnector host = hostTracker.hostQuery(id);
// unknown host, initiate ARP request
if (host == null) {
// add the requestor to the list so that we can replay the reply
arpRequestors.put(targetIP, requestorSet);
}
requestorSet.add(requestor);
- countDownTimers.put(targetIP, (short) 2); // reset timeout to 2sec
+ countDownTimers.put(targetIP, (short) 2); // reset timeout to
+ // 2sec
}
- //Raise a bcast request event, all controllers need to send one
+ // Raise a bcast request event, all controllers need to send one
log.trace("Sending a bcast ARP request for {}", targetIP);
arpRequestReplyEvent.put(new ARPRequest(targetIP, subnet), false);
} else {
/*
- * Target host known (across the cluster), send ARP REPLY make sure that targetMAC
- * matches the host's MAC if it is not broadcastMAC
+ * Target host known (across the cluster), send ARP REPLY make sure
+ * that targetMAC matches the host's MAC if it is not broadcastMAC
*/
if (NetUtils.isBroadcastMACAddr(targetMAC) || Arrays.equals(host.getDataLayerAddressBytes(), targetMAC)) {
log.trace("Received ARP req. for known host {}, sending reply...", targetIP);
if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) {
- sendARPReply(p,
- host.getDataLayerAddressBytes(),
- host.getNetworkAddress(),
- pkt.getSenderHardwareAddress(),
- sourceIP);
+ sendARPReply(p, host.getDataLayerAddressBytes(), host.getNetworkAddress(),
+ pkt.getSenderHardwareAddress(), sourceIP);
} else {
- arpRequestReplyEvent.put(new ARPReply(
- p,
- host.getNetworkAddress(),
- host.getDataLayerAddressBytes(),
- sourceIP,
- pkt.getSenderHardwareAddress()), false);
+ arpRequestReplyEvent.put(new ARPReply(p, host.getNetworkAddress(), host.getDataLayerAddressBytes(),
+ sourceIP, pkt.getSenderHardwareAddress()), false);
}
} else {
/*
- * Target MAC has been changed. For now, discard it.
- * TODO: We may need to send unicast ARP REQUEST on behalf of
- * the target back to the sender to trigger the sender to update
- * its table
+ * Target MAC has been changed. For now, discard it. TODO: We
+ * may need to send unicast ARP REQUEST on behalf of the target
+ * back to the sender to trigger the sender to update its table
*/
}
}
}
/**
- * Send a broadcast ARP Request to the switch/ ports using
- * the networkAddress of the subnet as sender IP
- * the controller's MAC as sender MAC
- * the targetIP as the target Network Address
+ * Send a broadcast ARP Request to the switch/ ports using the
+ * networkAddress of the subnet as sender IP the controller's MAC as sender
+ * MAC the targetIP as the target Network Address
*/
protected void sendBcastARPRequest(InetAddress targetIP, Subnet subnet) {
log.trace("sendBcatARPRequest targetIP:{} subnet:{}", targetIP, subnet);
}
byte[] targetHardwareAddress = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
- //TODO: should use IBroadcastHandler instead
+ // TODO: should use IBroadcastHandler instead
for (NodeConnector p : nodeConnectors) {
- //filter out any non-local or internal ports
- if (!(connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) || topologyManager.isInternal(p)) {
+ // filter out any non-local or internal ports
+ if (!(connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL)
+ || topologyManager.isInternal(p)) {
continue;
}
log.trace("Sending toward nodeConnector:{}", p);
/**
* Send a unicast ARP Request to the known host on a specific switch/port as
- * defined in the host.
- * The sender IP is the networkAddress of the subnet
+ * defined in the host. The sender IP is the networkAddress of the subnet
* The sender MAC is the controller's MAC
*/
protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) {
Subnet subnet = null;
if (switchManager != null) {
- subnet = switchManager.getSubnetByNetworkAddress(host
- .getNetworkAddress());
+ subnet = switchManager.getSubnetByNetworkAddress(host.getNetworkAddress());
}
if (subnet == null) {
log.debug("can't find subnet matching {}", host.getNetworkAddress());
return;
}
- if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL){
+ if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL) {
log.trace("Send a ucast ARP req. to: {}", host);
sendUcastARPRequest(host, subnet);
} else {
}
/**
- * An IP packet is punted to the controller, this means that the
- * destination host is not known to the controller.
- * Need to discover it by sending a Broadcast ARP Request
+ * An IP packet is punted to the controller, this means that the destination
+ * host is not known to the controller. Need to discover it by sending a
+ * Broadcast ARP Request
*
* @param pkt
* @param p
InetAddress dIP = NetUtils.getInetAddress(pkt.getDestinationAddress());
if (dIP == null) {
- return;
+ return;
}
// try to find a matching subnet
}
// see if we know about the host
- HostNodeConnector host = hostTracker.hostFind(dIP);
+ // Hosttracker hosts db key implementation
+ IHostId id = HostIdFactory.create(dIP, null);
+ HostNodeConnector host = hostTracker.hostFind(id);
if (host == null) {
// if we don't, know about the host, try to find it
- log.trace("Punted IP pkt to {}, sending bcast ARP event...",
- dIP);
+ 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
+ } 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.
*
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
+ /*
+ * 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 */
+ * host for now
+ */
NodeConnector nc = host.getnodeConnector();
// re-encode the Ethernet packet (the parent of the IPv4 packet)
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 {} because there is no route from {}", dIP, p);
}
}
allocateCaches();
retrieveCaches();
+
}
@SuppressWarnings({ "unchecked" })
private void retrieveCaches() {
- ConcurrentMap<?,?> map;
+ ConcurrentMap<?, ?> map;
- if (this.clusterContainerService == null){
+ if (this.clusterContainerService == null) {
log.error("Cluster service unavailable, can't retieve ARPHandler caches!");
return;
}
map = clusterContainerService.getCache(ARP_EVENT_CACHE_NAME);
- if (map != null){
+ if (map != null) {
this.arpRequestReplyEvent = (ConcurrentMap<ARPEvent, Boolean>) map;
} else {
log.error("Cache allocation failed for {}", ARP_EVENT_CACHE_NAME);
}
private void allocateCaches() {
- if (clusterContainerService == null){
+ if (clusterContainerService == null) {
nonClusterObjectCreate();
log.error("Clustering service unavailable. Allocated non-cluster caches for ARPHandler.");
return;
}
- try{
+ try {
clusterContainerService.createCache(ARP_EVENT_CACHE_NAME,
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- } catch (CacheConfigException e){
+ } catch (CacheConfigException e) {
log.error("ARPHandler cache configuration invalid!");
- } catch (CacheExistException e){
+ } catch (CacheExistException e) {
log.debug("ARPHandler cache exists, skipped allocation.");
}
}
- private void nonClusterObjectCreate(){
+ private void nonClusterObjectCreate() {
arpRequestReplyEvent = new ConcurrentHashMap<ARPEvent, Boolean>();
}
+
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
*
*/
void destroy() {
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
*
*/
void start() {
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
*
*/
- void stop(){
+ void stop() {
}
void stopping() {
handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector());
} else if (nextPak instanceof ARP) {
log.trace("Handle ARP packet: {}", formattedPak);
- handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt
- .getIncomingNodeConnector());
+ handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt.getIncomingNodeConnector());
}
}
return PacketResult.IGNORED;
}
- private ARP createARP(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress, byte[] targetIP) {
- ARP arp = new ARP();
- arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
- arp.setProtocolType(EtherTypes.IPv4.shortValue());
- arp.setHardwareAddressLength((byte) 6);
- arp.setProtocolAddressLength((byte) 4);
- arp.setOpCode(opCode);
- arp.setSenderHardwareAddress(senderMacAddress) ;
- arp.setSenderProtocolAddress(senderIP);
- arp.setTargetHardwareAddress(targetMacAddress);
- arp.setTargetProtocolAddress(targetIP);
- return arp;
+ private ARP createARP(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress,
+ byte[] targetIP) {
+ ARP arp = new ARP();
+ arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
+ arp.setProtocolType(EtherTypes.IPv4.shortValue());
+ arp.setHardwareAddressLength((byte) 6);
+ arp.setProtocolAddressLength((byte) 4);
+ arp.setOpCode(opCode);
+ arp.setSenderHardwareAddress(senderMacAddress);
+ arp.setSenderProtocolAddress(senderIP);
+ arp.setTargetHardwareAddress(targetMacAddress);
+ arp.setTargetProtocolAddress(targetIP);
+ return arp;
}
private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp) {
// Clean up ARP event cache
try {
- if (clusterContainerService.amICoordinator() && ! arpRequestReplyEvent.isEmpty()){
+ if (clusterContainerService.amICoordinator() && !arpRequestReplyEvent.isEmpty()) {
arpRequestReplyEvent.clear();
}
- } catch (Exception e){
+ } catch (Exception e) {
log.warn("ARPHandler: A cluster member failed to clear event cache.");
}
}
private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC) {
if (log.isTraceEnabled()) {
log.trace("generateAndSendReply called with params sourceIP:{} sourceMAC:{}", sourceIP,
- HexEncode.bytesToHexString(sourceMAC));
+ HexEncode.bytesToHexString(sourceMAC));
}
Set<HostNodeConnector> hosts = arpRequestors.remove(sourceIP);
if ((hosts == null) || hosts.isEmpty()) {
countDownTimers.remove(sourceIP);
for (HostNodeConnector host : hosts) {
if (log.isTraceEnabled()) {
- log.trace("Sending ARP Reply with src {}/{}, target {}/{}",
- new Object[] {
- HexEncode.bytesToHexString(sourceMAC),
- sourceIP,
- HexEncode.bytesToHexString(host.getDataLayerAddressBytes()),
- host.getNetworkAddress() });
+ log.trace(
+ "Sending ARP Reply with src {}/{}, target {}/{}",
+ new Object[] { HexEncode.bytesToHexString(sourceMAC), sourceIP,
+ HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host.getNetworkAddress() });
}
- if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL){
- sendARPReply(host.getnodeConnector(),
- sourceMAC,
- sourceIP,
- host.getDataLayerAddressBytes(),
+ if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL) {
+ sendARPReply(host.getnodeConnector(), sourceMAC, sourceIP, host.getDataLayerAddressBytes(),
host.getNetworkAddress());
} else {
/*
- * In the remote event a requestor moved to another
- * controller it may turn out it now we need to send
- * the ARP reply from a different controller, this
- * cover the case
+ * In the remote event a requestor moved to another controller
+ * it may turn out it now we need to send the ARP reply from a
+ * different controller, this cover the case
*/
arpRequestReplyEvent.put(
- new ARPReply(
- host.getnodeConnector(),
- sourceIP,
- sourceMAC,
- host.getNetworkAddress(),
- host.getDataLayerAddressBytes()), false);
+ new ARPReply(host.getnodeConnector(), sourceIP, sourceMAC, host.getNetworkAddress(), host
+ .getDataLayerAddressBytes()), false);
}
}
}
-
@Override
public void entryUpdated(ARPEvent key, Boolean new_value, String cacheName, boolean originLocal) {
log.trace("Got and entryUpdated for cacheName {} key {} isNew {}", cacheName, key, new_value);
public void entryCreated(ARPEvent key, String cacheName, boolean originLocal) {
// nothing to do
}
+
@Override
public void entryDeleted(ARPEvent key, String cacheName, boolean originLocal) {
// nothing to do
}
- private void enqueueARPCacheEvent (ARPEvent event, boolean new_value) {
+ private void enqueueARPCacheEvent(ARPEvent event, boolean new_value) {
try {
ARPCacheEvent cacheEvent = new ARPCacheEvent(event, new_value);
if (!ARPCacheEvents.contains(cacheEvent)) {
}
/*
- * this thread monitors the connectionEvent queue for new incoming events from
+ * this thread monitors the connectionEvent queue for new incoming events
+ * from
*/
private class ARPCacheEventHandler implements Runnable {
@Override
log.trace("Trigger and ARP Broadcast Request upon receipt of {}", req);
sendBcastARPRequest(req.getTargetIP(), req.getSubnet());
- //If unicast and local, send reply
+ // If unicast and local, send reply
} else if (connectionManager.getLocalityStatus(req.getHost().getnodeconnectorNode()) == ConnectionLocality.LOCAL) {
log.trace("ARPCacheEventHandler - sendUcatARPRequest upon receipt of {}", req);
sendUcastARPRequest(req.getHost(), req.getSubnet());
}
} else if (event instanceof ARPReply) {
ARPReply rep = (ARPReply) event;
- // New reply received by controller, notify all awaiting requestors across the cluster
+ // New reply received by controller, notify all awaiting
+ // requestors across the cluster
if (ev.isNewReply()) {
log.trace("Trigger a generateAndSendReply in response to {}", rep);
generateAndSendReply(rep.getTargetIP(), rep.getTargetMac());
- // Otherwise, a specific reply. If local, send out.
+ // Otherwise, a specific reply. If local, send out.
} else if (connectionManager.getLocalityStatus(rep.getPort().getNode()) == ConnectionLocality.LOCAL) {
log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep);
- sendARPReply(rep.getPort(),
- rep.getSourceMac(),
- rep.getSourceIP(),
- rep.getTargetMac(),
+ sendARPReply(rep.getPort(), rep.getSourceMac(), rep.getSourceIP(), rep.getTargetMac(),
rep.getTargetIP());
}
}
<yangtools.binding.version>0.6.0-SNAPSHOT</yangtools.binding.version>
<!--versions for bits of the controller -->
<controller.version>0.4.1-SNAPSHOT</controller.version>
+ <hosttracker.version>0.5.1-SNAPSHOT</hosttracker.version>
+ <arphandler.version>0.5.1-SNAPSHOT</arphandler.version>
+ <forwarding.staticrouting>0.5.1-SNAPSHOT</forwarding.staticrouting>
+ <samples.loadbalancer>0.5.1-SNAPSHOT</samples.loadbalancer>
<config.version>0.2.3-SNAPSHOT</config.version>
<netconf.version>0.2.3-SNAPSHOT</netconf.version>
<mdsal.version>1.0-SNAPSHOT</mdsal.version>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting</artifactId>
- <version>${controller.version}</version>
+ <version>${forwarding.staticrouting}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>arphandler</artifactId>
- <version>${controller.version}</version>
+ <version>${arphandler.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>${controller.version}</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.implementation</artifactId>
- <version>${controller.version}</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.loadbalancer</artifactId>
- <version>${controller.version}</version>
+ <version>${samples.loadbalancer}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
# Logging configuration for Tomcat-JUL logging
java.util.logging.config.file=configuration/tomcat-logging.properties
+
+#Hosttracker hostsdb key scheme setting
+hosttracker.keyscheme=IP
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.opendaylight</artifactId>
- <version>1.4.1-SNAPSHOT</version>
- <relativePath>../../commons/opendaylight</relativePath>
- </parent>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
- <tag>HEAD</tag>
- </scm>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.1-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
- <artifactId>forwarding.staticrouting</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
+ <artifactId>forwarding.staticrouting</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Import-Package>
- org.opendaylight.controller.sal.utils,
- org.opendaylight.controller.sal.core,
- org.opendaylight.controller.configuration,
- org.opendaylight.controller.forwardingrulesmanager,
- org.opendaylight.controller.hosttracker,
- org.opendaylight.controller.hosttracker.hostAware,
- org.opendaylight.controller.clustering.services,
- org.opendaylight.controller.sal.packet,
- org.opendaylight.controller.sal.routing,
- org.opendaylight.controller.topologymanager,
- org.eclipse.osgi.framework.console,
- org.osgi.framework,
- org.slf4j,
- org.apache.felix.dm,
- org.apache.commons.lang3.builder
- </Import-Package>
- <Export-Package>
- org.opendaylight.controller.forwarding.staticrouting
- </Export-Package>
- <Bundle-Activator>
- org.opendaylight.controller.forwarding.staticrouting.internal.Activator
- </Bundle-Activator>
- </instructions>
- <manifestLocation>${project.basedir}/META-INF</manifestLocation>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>topologymanager</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwardingrulesmanager</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>configuration</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.controller.sal.packet.address,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.configuration,
+ org.opendaylight.controller.forwardingrulesmanager,
+ org.opendaylight.controller.hosttracker,
+ org.opendaylight.controller.hosttracker.hostAware,
+ org.opendaylight.controller.clustering.services,
+ org.opendaylight.controller.sal.packet,
+ org.opendaylight.controller.sal.routing,
+ org.opendaylight.controller.topologymanager,
+ org.eclipse.osgi.framework.console,
+ org.osgi.framework,
+ org.slf4j,
+ org.apache.felix.dm,
+ org.apache.commons.lang3.builder
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.forwarding.staticrouting
+ </Export-Package>
+ <Bundle-Activator>
+ org.opendaylight.controller.forwarding.staticrouting.internal.Activator
+ </Bundle-Activator>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwardingrulesmanager</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker</artifactId>
+ <version>${hosttracker.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
</project>
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.opendaylight.controller.forwarding.staticrouting.IStaticRoutingAware;
import org.opendaylight.controller.forwarding.staticrouting.StaticRoute;
import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
+import org.opendaylight.controller.hosttracker.HostIdFactory;
+import org.opendaylight.controller.hosttracker.IHostId;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.IfNewHostNotify;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
/**
* Static Routing feature provides the bridge between SDN and Non-SDN networks.
*/
-public class StaticRoutingImplementation implements IfNewHostNotify,
- IForwardingStaticRouting, IObjectReader, IConfigurationContainerAware {
- private static Logger log = LoggerFactory
- .getLogger(StaticRoutingImplementation.class);
+public class StaticRoutingImplementation implements IfNewHostNotify, IForwardingStaticRouting, IObjectReader,
+ IConfigurationContainerAware {
+ private static Logger log = LoggerFactory.getLogger(StaticRoutingImplementation.class);
private static String ROOT = GlobalConstants.STARTUPHOME.toString();
ConcurrentMap<String, StaticRoute> staticRoutes;
ConcurrentMap<String, StaticRouteConfig> staticRouteConfigs;
}
@Override
- public Object readObject(ObjectInputStream ois)
- throws FileNotFoundException, IOException, ClassNotFoundException {
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
// Perform the class deserialization locally, from inside the package
// where the class is defined
return ois.readObject();
@SuppressWarnings("unchecked")
private void loadConfiguration() {
ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, StaticRouteConfig> confList = (ConcurrentMap<String, StaticRouteConfig>) objReader
- .read(this, staticRoutesFileName);
+ ConcurrentMap<String, StaticRouteConfig> confList = (ConcurrentMap<String, StaticRouteConfig>) objReader.read(
+ this, staticRoutesFileName);
if (confList == null) {
return;
}
}
-
private Status saveConfig() {
return saveConfigInternal();
}
Status status;
ObjectWriter objWriter = new ObjectWriter();
- status = objWriter.write(
- new ConcurrentHashMap<String, StaticRouteConfig>(
- staticRouteConfigs), staticRoutesFileName);
+ status = objWriter.write(new ConcurrentHashMap<String, StaticRouteConfig>(staticRouteConfigs),
+ staticRoutesFileName);
if (status.isSuccess()) {
return status;
}
@SuppressWarnings("deprecation")
- private void allocateCaches() {
+ private void allocateCaches() {
if (this.clusterContainerService == null) {
- log
- .info("un-initialized clusterContainerService, can't create cache");
+ log.info("un-initialized clusterContainerService, can't create cache");
return;
}
try {
- clusterContainerService.createCache(
- "forwarding.staticrouting.routes", EnumSet
- .of(IClusterServices.cacheMode.TRANSACTIONAL));
- clusterContainerService.createCache(
- "forwarding.staticrouting.configs", EnumSet
- .of(IClusterServices.cacheMode.TRANSACTIONAL));
+ clusterContainerService.createCache("forwarding.staticrouting.routes",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ clusterContainerService.createCache("forwarding.staticrouting.configs",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
} catch (CacheExistException cee) {
- log
- .error("\nCache already exists - destroy and recreate if needed");
+ log.error("\nCache already exists - destroy and recreate if needed");
} catch (CacheConfigException cce) {
log.error("\nCache configuration invalid - check cache mode");
}
@SuppressWarnings({ "unchecked", "deprecation" })
private void retrieveCaches() {
if (this.clusterContainerService == null) {
- log
- .info("un-initialized clusterContainerService, can't retrieve cache");
+ log.info("un-initialized clusterContainerService, can't retrieve cache");
return;
}
try {
ra.staticRouteUpdate(s, update);
} catch (Exception e) {
- log.error("",e);
+ log.error("", e);
}
}
}
@Override
public Object call() throws Exception {
- if (!added
- || (staticRoute.getType() == StaticRoute.NextHopType.SWITCHPORT)) {
+ if (!added || (staticRoute.getType() == StaticRoute.NextHopType.SWITCHPORT)) {
notifyStaticRouteUpdate(staticRoute, added);
} else {
InetAddress nh = staticRoute.getNextHopAddress();
- HostNodeConnector host = hostTracker.hostQuery(nh);
+ // HostTracker hosts db key scheme implementation
+ IHostId id = HostIdFactory.create(nh, null);
+ HostNodeConnector host = hostTracker.hostQuery(id);
if (host == null) {
log.debug("Next hop {} is not present, try to discover it", nh.getHostAddress());
- Future<HostNodeConnector> future = hostTracker.discoverHost(nh);
+ Future<HostNodeConnector> future = hostTracker.discoverHost(id);
if (future != null) {
try {
host = future.get();
public StaticRoute getBestMatchStaticRoute(InetAddress ipAddress) {
ByteBuffer bblongestPrefix = null;
try {
- bblongestPrefix = ByteBuffer.wrap(InetAddress.getByName("0.0.0.0")
- .getAddress());
+ bblongestPrefix = ByteBuffer.wrap(InetAddress.getByName("0.0.0.0").getAddress());
} catch (Exception e) {
return null;
}
return status;
}
if (staticRouteConfigs.get(config.getName()) != null) {
- return new Status(StatusCode.CONFLICT,
- "A valid Static Route configuration with this name " +
- "already exists. Please use a different name");
+ return new Status(StatusCode.CONFLICT, "A valid Static Route configuration with this name "
+ + "already exists. Please use a different name");
}
// Update database
for (Map.Entry<String, StaticRoute> entry : staticRoutes.entrySet()) {
if (entry.getValue().compareTo(sRoute) == 0) {
- return new Status(StatusCode.CONFLICT,
- "This conflicts with an existing Static Route " +
- "Configuration. Please check the configuration " +
- "and try again");
+ return new Status(StatusCode.CONFLICT, "This conflicts with an existing Static Route "
+ + "Configuration. Please check the configuration " + "and try again");
}
}
staticRoutes.put(config.getName(), sRoute);
checkAndUpdateListeners(name, sRoute, false);
return new Status(StatusCode.SUCCESS, null);
}
- return new Status(StatusCode.NOTFOUND,
- "Static Route with name " + name + " is not found");
+ return new Status(StatusCode.NOTFOUND, "Static Route with name " + name + " is not found");
}
void setClusterContainerService(IClusterContainerServices s) {
containerName = "";
}
- staticRoutesFileName = ROOT + "staticRouting_" + containerName
- + ".conf";
+ staticRoutesFileName = ROOT + "staticRouting_" + containerName + ".conf";
- log.debug("forwarding.staticrouting starting on container {}",
- containerName);
+ log.debug("forwarding.staticrouting starting on container {}", containerName);
allocateCaches();
retrieveCaches();
this.executor = Executors.newFixedThreadPool(1);
}
/*
- * Slow probe to identify any gateway that might have silently appeared
- * after the Static Routing Configuration.
+ * Slow probe to identify any gateway that might have silently appeared
+ * after the Static Routing Configuration.
*/
gatewayProbeTimer = new Timer();
gatewayProbeTimer.schedule(new TimerTask() {
public void run() {
for (Map.Entry<String, StaticRoute> s : staticRoutes.entrySet()) {
StaticRoute route = s.getValue();
- if ((route.getType() == StaticRoute.NextHopType.IPADDRESS)
- && route.getHost() == null) {
+ if ((route.getType() == StaticRoute.NextHopType.IPADDRESS) && route.getHost() == null) {
checkAndUpdateListeners(s.getKey(), route, true);
}
}
}
}, 60 * 1000, 60 * 1000);
+
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
*
*/
void destroy() {
- log.debug("Destroy all the Static Routing Rules given we are "
- + "shutting down");
+ log.debug("Destroy all the Static Routing Rules given we are " + "shutting down");
gatewayProbeTimer.cancel();
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
*
*/
void start() {
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
*
*/
void stop() {
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.opendaylight</artifactId>
- <version>1.4.1-SNAPSHOT</version>
- <relativePath>../../commons/opendaylight</relativePath>
- </parent>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
- <tag>HEAD</tag>
- </scm>
- <artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.1-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <artifactId>hosttracker</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Export-Package>
- org.opendaylight.controller.hosttracker,
- org.opendaylight.controller.hosttracker.hostAware
- </Export-Package>
- <Import-Package>
- org.opendaylight.controller.sal.core,
- org.opendaylight.controller.sal.utils,
- org.opendaylight.controller.topologymanager,
- org.opendaylight.controller.sal.packet.address,
- org.opendaylight.controller.switchmanager,
- org.opendaylight.controller.clustering.services,
- javax.xml.bind.annotation,
- javax.xml.bind,
- org.apache.felix.dm,
- org.apache.commons.lang3.builder,
- org.osgi.service.component,
- org.slf4j,
- org.eclipse.osgi.framework.console,
- org.osgi.framework
- </Import-Package>
- </instructions>
- <manifestLocation>${project.basedir}/META-INF</manifestLocation>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>topologymanager</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>switchmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.controller.hosttracker,
+ org.opendaylight.controller.hosttracker.hostAware
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.topologymanager,
+ org.opendaylight.controller.sal.packet.address,
+ org.opendaylight.controller.switchmanager,
+ org.opendaylight.controller.clustering.services,
+ javax.xml.bind.annotation,
+ javax.xml.bind,
+ org.apache.felix.dm,
+ org.apache.commons.lang3.builder,
+ org.osgi.service.component,
+ org.slf4j,
+ org.eclipse.osgi.framework.console,
+ org.osgi.framework
+ </Import-Package>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
</project>
+
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.hosttracker;
+
+import java.net.InetAddress;
+
+import org.opendaylight.controller.sal.packet.address.DataLinkAddress;
+
+/*
+ * Class used to generate a key based on the scheme choosen for hostsdb storage in hosttracker.
+ * @author Deepak Udapudi
+ */
+public class HostIdFactory {
+ public static final String DEFAULT_IP_KEY_SCHEME = "IP";
+ public static final String IP_MAC_KEY_SCHEME = "IP+MAC";
+ private static String scheme = null;
+ static {
+ scheme = System.getProperty("hosttracker.keyscheme");
+ }
+
+ public static String getScheme() {
+ return scheme;
+ }
+
+ public static IHostId create(InetAddress ip, DataLinkAddress mac) {
+ IHostId ipHostId = new IPHostId(ip);
+ if (scheme != null) {
+ switch (scheme) {
+
+ case DEFAULT_IP_KEY_SCHEME:
+ return ipHostId;
+ case IP_MAC_KEY_SCHEME:
+ IHostId ipMacHostId = new IPMacHostId(ip, mac);
+ return ipMacHostId;
+ default:
+ return ipHostId;
+
+ }
+ }
+ return ipHostId;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.hosttracker;
+
+import java.io.Serializable;
+
+/*
+ * Marker interface used by the key classes for their implementation
+ * @author Deepak Udapudi
+ */
+
+public interface IHostId extends Serializable {
+
+}
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.hosttracker;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+
+/*
+ * IP only key class implementation using the marker interface IHostId
+ * @author Deepak Udapudi
+ */
+
+public class IPHostId implements IHostId, Serializable {
+ private static final long serialVersionUID = 1L;
+ private InetAddress ipAddress;
+
+ public InetAddress getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(InetAddress ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public IPHostId(InetAddress ipAddress) {
+ super();
+ this.ipAddress = ipAddress;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((ipAddress == null) ? 0 : ipAddress.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ IPHostId other = (IPHostId) obj;
+ if (ipAddress == null) {
+ if (other.ipAddress != null)
+ return false;
+ } else if (!ipAddress.equals(other.ipAddress))
+ return false;
+ return true;
+ }
+
+ public static IHostId fromIP(InetAddress addr) {
+ return new IPHostId(addr);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.hosttracker;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+
+/*
+ * IP + Mac key class implementation using the marker interface IHostId
+ * @author Deepak Udapudi
+ */
+
+import org.opendaylight.controller.sal.packet.address.DataLinkAddress;
+
+public class IPMacHostId implements IHostId, Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private InetAddress ipAddress;
+ private DataLinkAddress macAddr;
+
+ public IPMacHostId(InetAddress ipAddress, DataLinkAddress macAddr) {
+ super();
+ this.ipAddress = ipAddress;
+ this.macAddr = macAddr;
+ }
+
+ public InetAddress getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(InetAddress ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public DataLinkAddress getMacAddr() {
+ return macAddr;
+ }
+
+ public void setMacAddr(DataLinkAddress macAddr) {
+ this.macAddr = macAddr;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((ipAddress == null) ? 0 : ipAddress.hashCode());
+ result = prime * result + ((macAddr == null) ? 0 : macAddr.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ IPMacHostId other = (IPMacHostId) obj;
+ if (ipAddress == null) {
+ if (other.ipAddress != null)
+ return false;
+ } else if (!ipAddress.equals(other.ipAddress))
+ return false;
+ if (macAddr == null) {
+ if (other.macAddr != null)
+ return false;
+ } else if (!macAddr.equals(other.macAddr))
+ return false;
+ return true;
+ }
+
+ public static IHostId fromIPAndMac(InetAddress ip, DataLinkAddress mac) {
+ return new IPMacHostId(ip, mac);
+ }
+
+}
* statically through Northbound APIs. If a binding is unknown, then an ARP
* request is initiated immediately to discover the host.
*
- * @param networkAddress
- * IP Address of the Host encapsulated in class InetAddress
+ * @param id
+ * IP address and Mac Address combination encapsulated in IHostId
+ * interface
* @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}
* Class that contains the Host info such as its MAC address, Switch
* ID, port, VLAN. If Host is not found, returns NULL
*/
- public HostNodeConnector hostFind(InetAddress networkAddress);
+ public HostNodeConnector hostFind(IHostId id);
+
+ /**
+ * Applications call this interface methods to determine IP address to MAC
+ * binding and its connectivity to an OpenFlow switch in term of Node, Port,
+ * and VLAN. These bindings are learned dynamically as well as can be added
+ * statically through Northbound APIs. If a binding is unknown, then an ARP
+ * request is initiated immediately to discover the host.
+ *
+ * @param addr
+ * IP address of the host
+ * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}
+ * Class that contains the Host info such as its MAC address, Switch
+ * ID, port, VLAN. If Host is not found, returns NULL
+ */
+ public HostNodeConnector hostFind(InetAddress addr);
/**
* Checks the local Host Database to see if a Host has been learned for a
- * given IP address.
+ * given IP address and Mac combination using the HostId.
*
- * @param networkAddress
- * IP Address of the Host encapsulated in class InetAddress
+ * @param id
+ * IP address and Mac Address combination encapsulated in IHostId
+ * interface
+ * @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}
+ * Class that contains the Host info such as its MAC address, Switch
+ * ID, port, VLAN. If Host is not found, returns NULL
+ *
+ */
+ public HostNodeConnector hostQuery(IHostId id);
+
+ /**
+ * Checks the local Host Database to see if a Host has been learned for a
+ * given IP address and Mac combination using the HostId.
+ *
+ * @param addr
+ * IP address of the Host
* @return {@link org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector}
* Class that contains the Host info such as its MAC address, Switch
* ID, port, VLAN. If Host is not found, returns NULL
*
*/
- public HostNodeConnector hostQuery(InetAddress networkAddress);
+ public HostNodeConnector hostQuery(InetAddress addr);
/**
- * Initiates an immediate discovery of the Host for a given IP address. This
+ * Initiates an immediate discovery of the Host for a given Host id. This
* provides for the calling applications to block on the host discovery.
*
- * @param networkAddress
- * IP address encapsulated in InetAddress class
+ * @param id
+ * IP address and Mac Address combination encapsulated in IHostId
+ * interface
+ * @return Future
+ * {@link org.opendaylight.controller.hosttracker.HostTrackerCallable}
+ */
+ public Future<HostNodeConnector> discoverHost(IHostId id);
+
+ /**
+ * Initiates an immediate discovery of the Host for a given Host id. This
+ * provides for the calling applications to block on the host discovery.
+ *
+ * @param addr
+ * IP address of the host
* @return Future
* {@link org.opendaylight.controller.hosttracker.HostTrackerCallable}
*/
- public Future<HostNodeConnector> discoverHost(InetAddress networkAddress);
+ public Future<HostNodeConnector> discoverHost(InetAddress addr);
/**
* Returns the Network Hierarchy for a given Host. This API is typically
* used by applications like Hadoop for Rack Awareness functionality.
*
- * @param IP
- * address of the Host encapsulated in InetAddress class
+ * @param id
+ * IP address and Mac Address combination encapsulated in IHostId
+ * interface
* @return List of String ArrayList containing the Hierarchies.
*/
- public List<List<String>> getHostNetworkHierarchy(InetAddress hostAddress);
+ public List<List<String>> getHostNetworkHierarchy(IHostId id);
+
+ /**
+ * Returns the Network Hierarchy for a given Host. This API is typically
+ * used by applications like Hadoop for Rack Awareness functionality.
+ *
+ * @param addr
+ * IP address of the host
+ * @return List of String ArrayList containing the Hierarchies.
+ */
+ public List<List<String>> getHostNetworkHierarchy(InetAddress addr);
/**
* Returns all the the Hosts either learned dynamically or added statically
* @return The status object as described in {@code Status} indicating the
* result of this action.
*/
- public Status addStaticHost(String networkAddress, String dataLayerAddress,
- NodeConnector nc, String vlan);
+ public Status addStaticHost(String networkAddress, String dataLayerAddress, NodeConnector nc, String vlan);
/**
* Allows the deletion of statically learned Host
* result of this action.
*/
public Status removeStaticHost(String networkAddress);
+
+ /**
+ * Allows the deletion of statically learned Host
+ *
+ * @param networkAddress
+ * @param macAddress
+ * @return The status object as described in {@code Status} indicating the
+ * result of this action.
+ */
+ public Status removeStaticHostUsingIPAndMac(String networkAddress, String macAddress);
}
<relativePath>../../commons/opendaylight</relativePath>
</parent>
<artifactId>hosttracker.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.hosttracker.HostIdFactory;
+import org.opendaylight.controller.hosttracker.IHostId;
+import org.opendaylight.controller.hosttracker.IPHostId;
+import org.opendaylight.controller.hosttracker.IPMacHostId;
import org.opendaylight.controller.hosttracker.IfHostListener;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.IfNewHostNotify;
* removed the database
*/
+/***
+ *
+ * HostTracker db key scheme implementation support. Support has been added for
+ * IP only or IP + MAC scheme as of now. User can use either of the schemes
+ * based on the configuration done in config.ini file. By default IP only key
+ * scheme is choosen. The attribute to be set in config.ini is
+ * hosttracker.keyscheme. It could have a value of 0 or 1 as of now. 0 is for IP
+ * only scheme. 1 is for IP + MAC scheme.
+ *
+ *
+ */
+
public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAware, IInventoryListener,
- ITopologyManagerAware, ICacheUpdateAware<InetAddress, HostNodeConnector>, CommandProvider {
+ ITopologyManagerAware, ICacheUpdateAware<IHostId, HostNodeConnector>, CommandProvider {
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 ConcurrentMap<InetAddress, HostNodeConnector> hostsDB;
+ protected ConcurrentMap<IHostId, HostNodeConnector> hostsDB;
/*
* Following is a list of hosts which have been requested by NB APIs to be
* added, but either the switch or the port is not sup, so they will be
protected boolean stopping;
private static boolean hostRefresh = true;
private static int hostRetryCount = 5;
+ private String keyScheme = null;
+
private static class ARPPending {
- protected InetAddress hostIP;
+ protected IHostId hostId;
protected short sent_count;
protected HostTrackerCallable hostTrackerCallable;
- public InetAddress getHostIP() {
- return hostIP;
+ public IHostId getHostId() {
+ return hostId;
}
public short getSent_count() {
return hostTrackerCallable;
}
- public void setHostIP(InetAddress networkAddr) {
- this.hostIP = networkAddr;
+ public void setHostId(IHostId id) {
+ this.hostId = id;
}
public void setSent_count(short count) {
// This list contains the hosts for which ARP requests are being sent
// periodically
- ConcurrentMap<InetAddress, ARPPending> ARPPendingList;
+ ConcurrentMap<IHostId, ARPPending> ARPPendingList;
/*
* This list below contains the hosts which were initially in ARPPendingList
* above, but ARP response didn't come from there hosts after multiple
*
* We can't recover from condition 3 above
*/
- ConcurrentMap<InetAddress, ARPPending> failedARPReqList;
+ ConcurrentMap<IHostId, ARPPending> failedARPReqList;
public HostTracker() {
}
/* ARP Refresh Timer to go off every 5 seconds to implement ARP aging */
arpRefreshTimer = new Timer();
arpRefreshTimer.schedule(new ARPRefreshHandler(), 5000, 5000);
+ keyScheme = HostIdFactory.getScheme();
logger.debug("startUp: Caches created, timers started");
}
return;
}
logger.debug("Retrieving cache for HostTrackerAH");
- hostsDB = (ConcurrentMap<InetAddress, HostNodeConnector>) this.clusterContainerService
- .getCache(ACTIVE_HOST_CACHE);
+ hostsDB = (ConcurrentMap<IHostId, HostNodeConnector>) this.clusterContainerService.getCache(ACTIVE_HOST_CACHE);
if (hostsDB == null) {
logger.error("Cache couldn't be retrieved for HostTracker");
}
}
public void nonClusterObjectCreate() {
- hostsDB = new ConcurrentHashMap<InetAddress, HostNodeConnector>();
+ hostsDB = new ConcurrentHashMap<IHostId, HostNodeConnector>();
inactiveStaticHosts = new ConcurrentHashMap<NodeConnector, HostNodeConnector>();
- ARPPendingList = new ConcurrentHashMap<InetAddress, ARPPending>();
- failedARPReqList = new ConcurrentHashMap<InetAddress, ARPPending>();
+ ARPPendingList = new ConcurrentHashMap<IHostId, ARPPending>();
+ failedARPReqList = new ConcurrentHashMap<IHostId, ARPPending>();
}
public void shutDown() {
}
private boolean hostExists(HostNodeConnector host) {
- HostNodeConnector lhost = hostsDB.get(host.getNetworkAddress());
+ IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress());
+ HostNodeConnector lhost = hostsDB.get(id);
return host.equals(lhost);
}
- private HostNodeConnector getHostFromOnActiveDB(InetAddress networkAddress) {
- return hostsDB.get(networkAddress);
+ private HostNodeConnector getHostFromOnActiveDB(IHostId id) {
+ return hostsDB.get(id);
}
- private Entry<NodeConnector, HostNodeConnector> getHostFromInactiveDB(InetAddress networkAddress) {
+ private Entry<NodeConnector, HostNodeConnector> getHostFromInactiveDB(IHostId id) {
for (Entry<NodeConnector, HostNodeConnector> entry : inactiveStaticHosts.entrySet()) {
- if (entry.getValue().equalsByIP(networkAddress)) {
- logger.debug("getHostFromInactiveDB(): Inactive Host found for IP:{} ", networkAddress.getHostAddress());
+ HostNodeConnector hnc = entry.getValue();
+ IHostId cmpId = HostIdFactory.create(hnc.getNetworkAddress(), hnc.getDataLayerAddress());
+ if (cmpId.equals(id)) {
+ logger.debug("getHostFromInactiveDB(): Inactive Host found for ID:{} ", decodeIPFromId(id));
return entry;
}
}
- logger.debug("getHostFromInactiveDB() Inactive Host Not found for IP: {}", networkAddress.getHostAddress());
+ logger.debug("getHostFromInactiveDB() Inactive Host Not found for ID: {}", decodeIPFromId(id));
return null;
}
- private void removeHostFromInactiveDB(InetAddress networkAddress) {
+ private void removeHostFromInactiveDB(IHostId id) {
NodeConnector nodeConnector = null;
for (Entry<NodeConnector, HostNodeConnector> entry : inactiveStaticHosts.entrySet()) {
- if (entry.getValue().equalsByIP(networkAddress)) {
+ HostNodeConnector hnc = entry.getValue();
+ IHostId cmpId = HostIdFactory.create(hnc.getNetworkAddress(), hnc.getDataLayerAddress());
+ if (cmpId.equals(id)) {
nodeConnector = entry.getKey();
break;
}
}
if (nodeConnector != null) {
inactiveStaticHosts.remove(nodeConnector);
- logger.debug("removeHostFromInactiveDB(): Host Removed for IP: {}", networkAddress.getHostAddress());
+ logger.debug("removeHostFromInactiveDB(): Host Removed for IP: {}", decodeIPFromId(id));
return;
}
- logger.debug("removeHostFromInactiveDB(): Host Not found for IP: {}", networkAddress.getHostAddress());
+ logger.debug("removeHostFromInactiveDB(): Host Not found for IP: {}", decodeIPFromId(id));
}
protected boolean hostMoved(HostNodeConnector host) {
- if (hostQuery(host.getNetworkAddress()) != null) {
+ IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress());
+ if (hostQuery(id) != null) {
return true;
}
return false;
}
@Override
- public HostNodeConnector hostQuery(InetAddress networkAddress) {
- return hostsDB.get(networkAddress);
+ public HostNodeConnector hostQuery(IHostId id) {
+ return hostsDB.get(id);
}
@Override
- public Future<HostNodeConnector> discoverHost(InetAddress networkAddress) {
+ public Future<HostNodeConnector> discoverHost(IHostId id) {
if (executor == null) {
logger.debug("discoverHost: Null executor");
return null;
}
- Callable<HostNodeConnector> worker = new HostTrackerCallable(this, networkAddress);
+ Callable<HostNodeConnector> worker = new HostTrackerCallable(this, id);
Future<HostNodeConnector> submit = executor.submit(worker);
return submit;
}
@Override
- public HostNodeConnector hostFind(InetAddress networkAddress) {
+ public HostNodeConnector hostFind(IHostId id) {
/*
* Sometimes at boot with containers configured in the startup we hit
* this path (from TIF) when hostFinder has not been set yet Caller
return null;
}
- HostNodeConnector host = hostQuery(networkAddress);
+ HostNodeConnector host = hostQuery(id);
if (host != null) {
- logger.debug("hostFind(): Host found for IP: {}", networkAddress.getHostAddress());
+ logger.debug("hostFind(): Host found for IP: {}", id);
return host;
}
/* Add this host to ARPPending List for any potential retries */
- addToARPPendingList(networkAddress);
- logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...",
- networkAddress.getHostAddress());
+ addToARPPendingList(id);
+ logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...", id);
/* host is not found, initiate a discovery */
for (IHostFinder hf : hostFinder) {
- hf.find(networkAddress);
+ InetAddress addr = decodeIPFromId(id);
+ hf.find(addr);
}
return null;
}
@Override
public Set<HostNodeConnector> getActiveStaticHosts() {
Set<HostNodeConnector> list = new HashSet<HostNodeConnector>();
- for (Entry<InetAddress, HostNodeConnector> entry : hostsDB.entrySet()) {
+ for (Entry<IHostId, HostNodeConnector> entry : hostsDB.entrySet()) {
HostNodeConnector host = entry.getValue();
if (host.isStaticHost()) {
list.add(host);
return list;
}
- private void addToARPPendingList(InetAddress networkAddr) {
+ private void addToARPPendingList(IHostId id) {
ARPPending arphost = new ARPPending();
- arphost.setHostIP(networkAddr);
+ arphost.setHostId(id);
arphost.setSent_count((short) 1);
- ARPPendingList.put(networkAddr, arphost);
- logger.debug("Host Added to ARPPending List, IP: {}", networkAddr);
+ ARPPendingList.put(id, arphost);
+ logger.debug("Host Added to ARPPending List, IP: {}", decodeIPFromId(id));
+
}
- public void setCallableOnPendingARP(InetAddress networkAddr, HostTrackerCallable callable) {
+ public void setCallableOnPendingARP(IHostId id, HostTrackerCallable callable) {
ARPPending arphost;
- for (Entry<InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+ for (Entry<IHostId, ARPPending> entry : ARPPendingList.entrySet()) {
arphost = entry.getValue();
- if (arphost.getHostIP().equals(networkAddr)) {
+ if (arphost.getHostId().equals(id)) {
arphost.setHostTrackerCallable(callable);
}
}
}
- private void processPendingARPReqs(InetAddress networkAddr) {
+ private void processPendingARPReqs(IHostId id) {
ARPPending arphost;
- if ((arphost = ARPPendingList.remove(networkAddr)) != null) {
+ if ((arphost = ARPPendingList.remove(id)) != null) {
// Remove the arphost from ARPPendingList as it has been learned now
- logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr);
+ logger.debug("Host Removed from ARPPending List, IP: {}", id);
HostTrackerCallable htCallable = arphost.getHostTrackerCallable();
if (htCallable != null) {
htCallable.wakeup();
* It could have been a host from the FailedARPReqList
*/
- if (failedARPReqList.containsKey(networkAddr)) {
- failedARPReqList.remove(networkAddr);
- logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr);
+ if (failedARPReqList.containsKey(id)) {
+ failedARPReqList.remove(id);
+ logger.debug("Host Removed from FailedARPReqList List, IP: {}", decodeIPFromId(id));
}
}
// Learn a new Host
private void learnNewHost(HostNodeConnector host) {
+ IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress());
host.initArpSendCountDown();
- HostNodeConnector rHost = hostsDB.putIfAbsent(host.getNetworkAddress(), host);
+ HostNodeConnector rHost = hostsDB.putIfAbsent(id, host);
if (rHost != null) {
// Another host is already learned for this IP address, replace it
- replaceHost(host.getNetworkAddress(), rHost, host);
+ replaceHost(id, rHost, host);
} else {
logger.debug("New Host Learned: MAC: {} IP: {}", HexEncode.bytesToHexString(host
.getDataLayerAddressBytes()), host.getNetworkAddress().getHostAddress());
}
}
- private void replaceHost(InetAddress networkAddr, HostNodeConnector removedHost, HostNodeConnector newHost) {
+ private void replaceHost(IHostId id, HostNodeConnector removedHost, HostNodeConnector newHost) {
// Ignore ARP messages from internal nodes
NodeConnector newHostNc = newHost.getnodeConnector();
boolean newHostIsInternal = topologyManager.isInternal(newHostNc);
newHost.initArpSendCountDown();
- if (hostsDB.replace(networkAddr, removedHost, newHost)) {
+ if (hostsDB.replace(id, removedHost, newHost)) {
logger.debug("Host move occurred: Old Host IP:{}, New Host IP: {}", removedHost.getNetworkAddress()
.getHostAddress(), newHost.getNetworkAddress().getHostAddress());
logger.debug("Old Host MAC: {}, New Host MAC: {}",
/*
* Host replacement has failed, do the recovery
*/
- hostsDB.put(networkAddr, newHost);
+ hostsDB.put(id, newHost);
logger.error("Host replacement failed. Overwrite the host. Repalced Host: {}, New Host: {}", removedHost,
newHost);
}
notifyHostLearnedOrRemoved(removedHost, false);
notifyHostLearnedOrRemoved(newHost, true);
if (!newHost.isStaticHost()) {
- processPendingARPReqs(networkAddr);
+ processPendingARPReqs(id);
}
}
// Remove known Host
- private void removeKnownHost(InetAddress key) {
+ private void removeKnownHost(IHostId key) {
HostNodeConnector host = hostsDB.get(key);
if (host != null) {
logger.debug("Removing Host: IP:{}", host.getNetworkAddress().getHostAddress());
hostsDB.remove(key);
} else {
- logger.error("removeKnownHost(): Host for IP address {} not found in hostsDB", key.getHostAddress());
+ logger.error("removeKnownHost(): Host for IP address {} not found in hostsDB", decodeIPFromId(key));
}
}
public void run() {
HostNodeConnector removedHost = null;
InetAddress networkAddr = host.getNetworkAddress();
-
+ IHostId id = HostIdFactory.create(networkAddr, host.getDataLayerAddress());
/* Check for Host Move case */
if (hostMoved(host)) {
/*
* location parameters with new information, and notify the
* applications listening to host move.
*/
- removedHost = hostsDB.get(networkAddr);
+
+ removedHost = hostsDB.get(id);
if (removedHost != null) {
- replaceHost(networkAddr, removedHost, host);
+ replaceHost(id, removedHost, host);
return;
} else {
logger.error("Host to be removed not found in hostsDB");
learnNewHost(host);
/* check if there is an outstanding request for this host */
- processPendingARPReqs(networkAddr);
+ processPendingARPReqs(id);
notifyHostLearnedOrRemoved(host, true);
}
}
logger.debug("Received for Host: IP {}, MAC {}, {}", host.getNetworkAddress().getHostAddress(),
HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host);
if (hostExists(host)) {
- HostNodeConnector existinghost = hostsDB.get(host.getNetworkAddress());
+ IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress());
+ HostNodeConnector existinghost = hostsDB.get(id);
existinghost.initArpSendCountDown();
// Update the host
- hostsDB.put(host.getNetworkAddress(), existinghost);
+
+ hostsDB.put(id, existinghost);
+ logger.debug("hostListener returned without adding the host");
return;
}
new NotifyHostThread(host).start();
* Switch-Ids as String).
*/
@Override
- public List<List<String>> getHostNetworkHierarchy(InetAddress hostAddress) {
- HostNodeConnector host = hostQuery(hostAddress);
+ public List<List<String>> getHostNetworkHierarchy(IHostId id) {
+ HostNodeConnector host = hostQuery(id);
if (host == null) {
return null;
}
public void subnetNotify(Subnet sub, boolean add) {
logger.debug("Received subnet notification: {} add={}", sub, add);
if (add) {
- for (Entry<InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
+ 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");
continue;
}
- logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
+ logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", decodeIPFromId(arphost.getHostId()));
for (IHostFinder hf : hostFinder) {
- hf.find(arphost.getHostIP());
+ hf.find(decodeIPFromId(arphost.getHostId()));
}
}
}
/* This routine runs every 4 seconds */
logger.trace("Number of Entries in ARP Pending/Failed Lists: ARPPendingList = {}, failedARPReqList = {}",
ARPPendingList.size(), failedARPReqList.size());
- for (Entry<InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+ for (Entry<IHostId, ARPPending> entry : ARPPendingList.entrySet()) {
arphost = entry.getValue();
- if (hostsDB.containsKey(arphost.getHostIP())) {
+ if (hostsDB.containsKey(arphost.getHostId())) {
// this host is already learned, shouldn't be in
// ARPPendingList
// Remove it and continue
- logger.warn("Learned Host {} found in ARPPendingList", arphost.getHostIP());
+ logger.warn("Learned Host {} found in ARPPendingList", decodeIPFromId(arphost.getHostId()));
ARPPendingList.remove(entry.getKey());
continue;
}
continue;
}
for (IHostFinder hf : hostFinder) {
- hf.find(arphost.getHostIP());
+ hf.find(decodeIPFromId(arphost.getHostId()));
}
arphost.sent_count++;
- logger.debug("ARP Sent from ARPPending List, IP: {}", arphost.getHostIP().getHostAddress());
+ logger.debug("ARP Sent from ARPPending List, IP: {}", decodeIPFromId(arphost.getHostId()));
} else if (arphost.getSent_count() >= hostRetryCount) {
/*
* ARP requests have been sent without receiving a reply,
*/
ARPPendingList.remove(entry.getKey());
logger.debug("ARP reply not received after multiple attempts, removing from Pending List IP: {}",
- arphost.getHostIP().getHostAddress());
+ decodeIPFromId(arphost.getHostId()));
/*
* Add this host to a different list which will be processed
* on link up events
*/
- logger.debug("Adding the host to FailedARPReqList IP: {}", arphost.getHostIP().getHostAddress());
+ logger.debug("Adding the host to FailedARPReqList IP: {}", decodeIPFromId(arphost.getHostId()));
failedARPReqList.put(entry.getKey(), arphost);
} else {
logger.error("ARPRefreshHandler(): hostsDB is not allocated yet:");
return;
}
- for (Entry<InetAddress, HostNodeConnector> entry : hostsDB.entrySet()) {
+ for (Entry<IHostId, HostNodeConnector> entry : hostsDB.entrySet()) {
HostNodeConnector host = entry.getValue();
if (host.isStaticHost()) {
/* this host was learned via API3, don't age it out */
HostNodeConnector host = null;
try {
host = new HostNodeConnector(dataLayerAddress, networkAddr, nc, vlan);
+ IHostId id = HostIdFactory.create(networkAddr, new EthernetAddress(dataLayerAddress));
if (hostExists(host)) {
// This host is already learned either via ARP or through a
// northbound request
return new Status(StatusCode.SUCCESS);
}
- if (hostsDB.get(networkAddr) != null) {
+ if (hostsDB.get(id) != null) {
// There is already a host with this IP address (but behind
// a different (switch, port, vlan) tuple. Return an error
return new Status(StatusCode.CONFLICT, "Host with this IP already exists.");
*/
if (switchManager.isNodeConnectorEnabled(nc)) {
learnNewHost(host);
- processPendingARPReqs(networkAddr);
+ processPendingARPReqs(id);
notifyHostLearnedOrRemoved(host, true);
} else {
inactiveStaticHosts.put(nc, host);
return new Status(StatusCode.BADREQUEST, "Host already exists");
}
+ IHostId id = HostIdFactory.create(networkAddr, new EthernetAddress(dataLayerAddress));
+
if ((tobeUpdatedHost = hostsDB.get(networkAddr)) != null) {
- if (hostsDB.replace(networkAddr, tobeUpdatedHost, host)) {
+ if (hostsDB.replace(id, tobeUpdatedHost, host)) {
logger.debug("Host replaced from hostsDB. Old host: {} New Host: {}", tobeUpdatedHost, host);
notifyHostLearnedOrRemoved(tobeUpdatedHost, false);
notifyHostLearnedOrRemoved(host, true);
* otherwise
*/
- public Status removeStaticHostReq(InetAddress networkAddress) {
+ public Status removeStaticHostReq(InetAddress networkAddress, DataLinkAddress mac) {
// Check if host is in active hosts database
- HostNodeConnector host = getHostFromOnActiveDB(networkAddress);
+ IHostId id = HostIdFactory.create(networkAddress, mac);
+ HostNodeConnector host = getHostFromOnActiveDB(id);
if (host != null) {
// Validation check
if (!host.isStaticHost()) {
}
// Remove and notify
notifyHostLearnedOrRemoved(host, false);
- removeKnownHost(networkAddress);
+ removeKnownHost(id);
return new Status(StatusCode.SUCCESS, null);
}
// Check if host is in inactive hosts database
- Entry<NodeConnector, HostNodeConnector> entry = getHostFromInactiveDB(networkAddress);
+ Entry<NodeConnector, HostNodeConnector> entry = getHostFromInactiveDB(id);
if (entry != null) {
host = entry.getValue();
// Validation check
if (!host.isStaticHost()) {
return new Status(StatusCode.FORBIDDEN, "Host " + networkAddress.getHostName() + " is not static");
}
- this.removeHostFromInactiveDB(networkAddress);
+ this.removeHostFromInactiveDB(id);
return new Status(StatusCode.SUCCESS, null);
}
switch (type) {
case REMOVED:
logger.debug("Received removed node {}", node);
- for (Entry<InetAddress, HostNodeConnector> entry : hostsDB.entrySet()) {
+ for (Entry<IHostId, HostNodeConnector> entry : hostsDB.entrySet()) {
HostNodeConnector host = entry.getValue();
if (host.getnodeconnectorNode().equals(node)) {
logger.debug("Node: {} is down, remove from Hosts_DB", node);
@Override
public Status removeStaticHost(String networkAddress) {
try {
+ if ((keyScheme != null) && (!keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) {
+ return new Status(StatusCode.NOTALLOWED, "Host DB Key scheme used is not IP only scheme.");
+ }
InetAddress address = InetAddress.getByName(networkAddress);
- return removeStaticHostReq(address);
+ return removeStaticHostReq(address, null);
} catch (UnknownHostException e) {
logger.debug("Invalid IP Address when trying to remove host", e);
return new Status(StatusCode.BADREQUEST, "Invalid IP Address when trying to remove host");
}
}
+ @Override
+ public Status removeStaticHostUsingIPAndMac(String networkAddress, String macAddress) {
+ try {
+ if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) {
+ return new Status(StatusCode.NOTALLOWED, "Host DB Key scheme used is not IP only scheme.");
+ }
+ InetAddress address = InetAddress.getByName(networkAddress);
+ DataLinkAddress mac = new EthernetAddress(HexEncode.bytesFromHexString(macAddress));
+ return removeStaticHostReq(address, mac);
+ } catch (UnknownHostException e) {
+ logger.debug("Invalid IP Address when trying to remove host", e);
+ return new Status(StatusCode.BADREQUEST, "Invalid IP Address when trying to remove host");
+ } catch (ConstructionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return new Status(StatusCode.BADREQUEST, "Invalid Input parameters have been passed.");
+ }
+ }
+
+ private InetAddress decodeIPFromId(IHostId id) {
+ if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) {
+ IPHostId ipId = (IPHostId) id;
+ return (ipId.getIpAddress());
+ } else if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.IP_MAC_KEY_SCHEME))) {
+ IPMacHostId ipMacId = (IPMacHostId) id;
+ return (ipMacId.getIpAddress());
+ }
+ return null;
+ }
+
+ private DataLinkAddress decodeMacFromId(IHostId id) {
+ if ((keyScheme != null) && (!keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) {
+ IPMacHostId ipMacId = (IPMacHostId) id;
+ return (ipMacId.getMacAddr());
+ }
+
+ return null;
+ }
+
private void handleNodeConnectorStatusUp(NodeConnector nodeConnector) {
ARPPending arphost;
HostNodeConnector host = null;
logger.trace("handleNodeConnectorStatusUp {}", nodeConnector);
- for (Entry<InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
+ for (Entry<IHostId, ARPPending> entry : failedARPReqList.entrySet()) {
arphost = entry.getValue();
- logger.trace("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
+ logger.trace("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostId());
if (hostFinder == null) {
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",
// Use hostFinder's "probe" method
try {
byte[] dataLayerAddress = NetUtils.getBroadcastMACAddr();
- host = new HostNodeConnector(dataLayerAddress, arphost.getHostIP(), nodeConnector, (short) 0);
+ host = new HostNodeConnector(dataLayerAddress, decodeIPFromId(arphost.getHostId()), nodeConnector,
+ (short) 0);
for (IHostFinder hf : hostFinder) {
hf.probe(host);
}
} catch (ConstructionException e) {
logger.debug("HostNodeConnector couldn't be created for Host: {}, NodeConnector: {}",
- arphost.getHostIP(), nodeConnector);
+ arphost.getHostId(), nodeConnector);
logger.error("", e);
}
}
if (host != null) {
inactiveStaticHosts.remove(nodeConnector);
learnNewHost(host);
- processPendingARPReqs(host.getNetworkAddress());
+ IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress());
+ processPendingARPReqs(id);
notifyHostLearnedOrRemoved(host, true);
}
}
private void handleNodeConnectorStatusDown(NodeConnector nodeConnector) {
logger.trace("handleNodeConnectorStatusDown {}", nodeConnector);
- for (Entry<InetAddress, HostNodeConnector> entry : hostsDB.entrySet()) {
+ for (Entry<IHostId, HostNodeConnector> entry : hostsDB.entrySet()) {
HostNodeConnector host = entry.getValue();
if (host.getnodeConnector().equals(nodeConnector)) {
logger.debug(" NodeConnector: {} is down, remove from Hosts_DB", nodeConnector);
this.containerName = "";
}
startUp();
+
+ logger.debug("key Scheme in hosttracker is {}", keyScheme);
}
/**
}
@Override
- public void entryCreated(InetAddress key, String cacheName, boolean originLocal) {
+ public void entryCreated(IHostId key, String cacheName, boolean originLocal) {
if (originLocal) {
return;
}
}
@Override
- public void entryUpdated(InetAddress key, HostNodeConnector new_value, String cacheName, boolean originLocal) {
+ public void entryUpdated(IHostId key, HostNodeConnector new_value, String cacheName, boolean originLocal) {
}
@Override
- public void entryDeleted(InetAddress key, String cacheName, boolean originLocal) {
+ public void entryDeleted(IHostId key, String cacheName, boolean originLocal) {
}
private void registerWithOSGIConsole() {
public void _dumpPendingARPReqList(CommandInterpreter ci) {
ARPPending arphost;
- for (Entry<InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+ for (Entry<IHostId, ARPPending> entry : ARPPendingList.entrySet()) {
arphost = entry.getValue();
- ci.println(arphost.getHostIP().toString());
+ ci.println(arphost.getHostId().toString());
}
}
public void _dumpFailedARPReqList(CommandInterpreter ci) {
ARPPending arphost;
- for (Entry<InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
+ for (Entry<IHostId, ARPPending> entry : failedARPReqList.entrySet()) {
arphost = entry.getValue();
- ci.println(arphost.getHostIP().toString());
+ ci.println(arphost.getHostId().toString());
}
}
+
+ @Override
+ public HostNodeConnector hostFind(InetAddress addr) {
+ IHostId id = HostIdFactory.create(addr, null);
+ return (hostFind(id));
+ }
+
+ @Override
+ public HostNodeConnector hostQuery(InetAddress addr) {
+ IHostId id = HostIdFactory.create(addr, null);
+ return (hostQuery(id));
+ }
+
+ @Override
+ public Future<HostNodeConnector> discoverHost(InetAddress addr) {
+ IHostId id = HostIdFactory.create(addr, null);
+ return discoverHost(id);
+ }
+
+ @Override
+ public List<List<String>> getHostNetworkHierarchy(InetAddress addr) {
+ IHostId id = HostIdFactory.create(addr, null);
+ return getHostNetworkHierarchy(id);
+ }
}
* find a host in HostTracker's database and want to discover the host
* in the same thread without being called by a callback function.
*/
-import java.net.InetAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import org.opendaylight.controller.hosttracker.IHostId;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+/**
+ *
+ *
+ */
public class HostTrackerCallable implements Callable<HostNodeConnector> {
- InetAddress trackedHost;
+ //host id which could be ip or a combination of ip + mac based on the scheme chosen.
+ IHostId trackedHost;
HostTracker hostTracker;
protected CountDownLatch latch;
- public HostTrackerCallable(HostTracker tracker, InetAddress inet) {
+ public HostTrackerCallable(HostTracker tracker, IHostId inet) {
trackedHost = inet;
hostTracker = tracker;
latch = new CountDownLatch(1);
\r
import java.net.InetAddress;\r
import java.net.UnknownHostException;\r
+\r
import junit.framework.TestCase;\r
\r
import org.junit.Assert;\r
import org.junit.Test;\r
+import org.opendaylight.controller.hosttracker.IHostId;\r
+import org.opendaylight.controller.hosttracker.IPHostId;\r
\r
public class HostTrackerTest extends TestCase {\r
\r
Assert.assertFalse(hostTracker == null);\r
\r
InetAddress hostIP = InetAddress.getByName("192.168.0.8");\r
+ IHostId id = IPHostId.fromIP(hostIP);\r
\r
HostTrackerCallable htCallable = new HostTrackerCallable(hostTracker,\r
- hostIP);\r
- Assert.assertTrue(htCallable.trackedHost.equals(hostIP));\r
+ id);\r
+ Assert.assertTrue(htCallable.trackedHost.equals(id));\r
Assert.assertTrue(htCallable.hostTracker.equals(hostTracker));\r
\r
long count = htCallable.latch.getCount();\r
Assert.assertFalse(hostTracker == null);\r
\r
InetAddress hostIP_1 = InetAddress.getByName("192.168.0.8");\r
+ IHostId id1 = IPHostId.fromIP(hostIP_1);\r
InetAddress hostIP_2 = InetAddress.getByName("192.168.0.18");\r
- hostTracker.discoverHost(hostIP_1);\r
- hostTracker.discoverHost(hostIP_2);\r
+ IHostId id2 = IPHostId.fromIP(hostIP_2);\r
+ hostTracker.discoverHost(id1);\r
+ hostTracker.discoverHost(id2);\r
hostTracker.nonClusterObjectCreate();\r
}\r
\r
</scm>
<artifactId>hosttracker.integrationtest</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>arphandler</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${arphandler.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.opendaylight.controller.hosttracker.IHostId;
+import org.opendaylight.controller.hosttracker.IPHostId;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
import org.opendaylight.controller.sal.core.Node;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
//import org.opendaylight.controller.hosttracker.*;
@RunWith(PaxExam.class)
private IfIptoHost hosttracker = null;
private IInventoryListener invtoryListener = null;
+
// Configure the OSGi container
@Configuration
public Option[] config() {
st = this.hosttracker.addStaticHost("192.168.0.13", "11:22:33:44:55:77", nc1_2, "0");
Assert.assertFalse(st.isSuccess());
-
this.invtoryListener.notifyNodeConnector(nc1_1, UpdateType.ADDED, null);
// check all host list
Status st = this.hosttracker.addStaticHost("192.168.0.8", "11:22:33:44:55:66", nc1_1, null);
st = this.hosttracker.addStaticHost("192.168.0.13", "11:22:33:44:55:77", nc1_2, "");
- HostNodeConnector hnc_1 = this.hosttracker.hostFind(InetAddress.getByName("192.168.0.8"));
+ IHostId id1 = IPHostId.fromIP(InetAddress.getByName("192.168.0.8"));
+ HostNodeConnector hnc_1 = this.hosttracker.hostFind(id1);
assertNull(hnc_1);
this.invtoryListener.notifyNodeConnector(nc1_1, UpdateType.ADDED, null);
- hnc_1 = this.hosttracker.hostFind(InetAddress.getByName("192.168.0.8"));
+ IHostId id2 = IPHostId.fromIP(InetAddress.getByName("192.168.0.8"));
+ hnc_1 = this.hosttracker.hostFind(id2);
+
assertNotNull(hnc_1);
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${forwarding.staticrouting}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>arphandler</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${arphandler.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${forwarding.staticrouting}</version>
</dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
</scm>
<artifactId>samples.loadbalancer</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<build>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import org.apache.felix.dm.Component;
import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+import org.opendaylight.controller.hosttracker.HostIdFactory;
+import org.opendaylight.controller.hosttracker.IHostId;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
import org.opendaylight.controller.sal.action.Action;
import org.slf4j.LoggerFactory;
/**
- * This class is the main class that represents the load balancer service.
- * This is a sample load balancer application that balances traffic to backend servers
- * based on the source address and source port on each incoming packet. The service
- * reactively installs OpenFlow rules to direct all packets with a specific source address
- * and source port to one of the appropriate backend servers. The servers may be chosen
- * using a round robin policy or a random policy. This service can be configured via a
- * REST APIs which are similar to the OpenStack Quantum LBaaS (Load-balancer-as-a-Service)
- * v1.0 API proposal (http://wiki.openstack.org/Quantum/LBaaS)
+ * This class is the main class that represents the load balancer service. This
+ * is a sample load balancer application that balances traffic to backend
+ * servers based on the source address and source port on each incoming packet.
+ * The service reactively installs OpenFlow rules to direct all packets with a
+ * specific source address and source port to one of the appropriate backend
+ * servers. The servers may be chosen using a round robin policy or a random
+ * policy. This service can be configured via a REST APIs which are similar to
+ * the OpenStack Quantum LBaaS (Load-balancer-as-a-Service) v1.0 API proposal
+ * (http://wiki.openstack.org/Quantum/LBaaS)
*
- * To use this service, a virtual IP (or VIP) should be exposed to the clients of this service
- * and used as the destination address. A VIP is a entity that comprises of a virtual IP, port
- * and protocol (TCP or UDP).
- * Assumptions:
- * 1. One or more VIPs may be mapped to the same server pool. All VIPs that share the same
- * pool must also share the same load balancing policy (random or round robin).
+ * To use this service, a virtual IP (or VIP) should be exposed to the clients
+ * of this service and used as the destination address. A VIP is a entity that
+ * comprises of a virtual IP, port and protocol (TCP or UDP). Assumptions: 1.
+ * One or more VIPs may be mapped to the same server pool. All VIPs that share
+ * the same pool must also share the same load balancing policy (random or round
+ * robin).
*
- * 2. Only one server pool can be be assigned to a VIP.
+ * 2. Only one server pool can be be assigned to a VIP.
*
- * 3. All flow rules are installed with an idle timeout of 5 seconds.
+ * 3. All flow rules are installed with an idle timeout of 5 seconds.
*
- * 4. Packets to a VIP must leave the OpenFlow cluster from the same switch from where
- * it entered it.
+ * 4. Packets to a VIP must leave the OpenFlow cluster from the same switch from
+ * where it entered it.
*
- * 5. When you delete a VIP or a server pool or a server from a pool, the service does not
- * delete the flow rules it has already installed. The flow rules should automatically
- * time out after the idle timeout of 5 seconds.
+ * 5. When you delete a VIP or a server pool or a server from a pool, the
+ * service does not delete the flow rules it has already installed. The flow
+ * rules should automatically time out after the idle timeout of 5 seconds.
*
*/
-public class LoadBalancerService implements IListenDataPacket, IConfigManager{
+public class LoadBalancerService implements IListenDataPacket, IConfigManager {
/*
* Logger instance
private static Logger lbsLogger = LoggerFactory.getLogger(LoadBalancerService.class);
/*
- * Single instance of the configuration manager. Application passes this reference to all
- * the new policies implemented for load balancing.
+ * Single instance of the configuration manager. Application passes this
+ * reference to all the new policies implemented for load balancing.
*/
private static ConfigManager configManager = new ConfigManager();
* Round robing policy instance. Need to implement factory patterns to get
* policy instance.
*/
- private static RoundRobinLBPolicy rrLBMethod= new RoundRobinLBPolicy(configManager);
+ private static RoundRobinLBPolicy rrLBMethod = new RoundRobinLBPolicy(configManager);
/*
* Random policy instance.
*/
- private static RandomLBPolicy ranLBMethod= new RandomLBPolicy(configManager);
+ private static RandomLBPolicy ranLBMethod = new RandomLBPolicy(configManager);
/*
* Reference to the data packet service
private String containerName = null;
/*
- * Set/unset methods for the service instance that load balancer
- * service requires
+ * Set/unset methods for the service instance that load balancer service
+ * requires
*/
public String getContainerName() {
if (containerName == null)
}
}
- public void setForwardingRulesManager(
- IForwardingRulesManager forwardingRulesManager) {
+ public void setForwardingRulesManager(IForwardingRulesManager forwardingRulesManager) {
lbsLogger.debug("Setting ForwardingRulesManager");
this.ruleManager = forwardingRulesManager;
}
- public void unsetForwardingRulesManager(
- IForwardingRulesManager forwardingRulesManager) {
+ public void unsetForwardingRulesManager(IForwardingRulesManager forwardingRulesManager) {
if (this.ruleManager == forwardingRulesManager) {
this.ruleManager = null;
}
}
/**
- * This method receives first packet of flows for which there is no
- * matching flow rule installed on the switch. IP addresses used for VIPs
- * are not supposed to be used by any real/virtual host in the network.
- * Hence, any forwarding/routing service will not install any flows rules matching
- * these VIPs. This ensures that all the flows destined for VIPs will not find a match
- * in the switch and will be forwarded to the load balancing service.
- * Service will decide where to route this traffic based on the load balancing
- * policy of the VIP's attached pool and will install appropriate flow rules
- * in a reactive manner.
+ * This method receives first packet of flows for which there is no matching
+ * flow rule installed on the switch. IP addresses used for VIPs are not
+ * supposed to be used by any real/virtual host in the network. Hence, any
+ * forwarding/routing service will not install any flows rules matching
+ * these VIPs. This ensures that all the flows destined for VIPs will not
+ * find a match in the switch and will be forwarded to the load balancing
+ * service. Service will decide where to route this traffic based on the
+ * load balancing policy of the VIP's attached pool and will install
+ * appropriate flow rules in a reactive manner.
*/
@Override
- public PacketResult receiveDataPacket(RawPacket inPkt){
+ public PacketResult receiveDataPacket(RawPacket inPkt) {
if (inPkt == null) {
return PacketResult.IGNORED;
if (ipPkt instanceof IPv4) {
- lbsLogger.debug("Packet recieved from switch : {}",inPkt.getIncomingNodeConnector().getNode().toString());
- IPv4 ipv4Pkt = (IPv4)ipPkt;
- if(IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.TCP.toString())
- || IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.UDP.toString())){
+ lbsLogger.debug("Packet recieved from switch : {}", inPkt.getIncomingNodeConnector().getNode()
+ .toString());
+ IPv4 ipv4Pkt = (IPv4) ipPkt;
+ if (IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.TCP.toString())
+ || IPProtocols.getProtocolName(ipv4Pkt.getProtocol()).equals(IPProtocols.UDP.toString())) {
- lbsLogger.debug("Packet protocol : {}",IPProtocols.getProtocolName(ipv4Pkt.getProtocol()));
+ lbsLogger.debug("Packet protocol : {}", IPProtocols.getProtocolName(ipv4Pkt.getProtocol()));
Client client = new LBUtil().getClientFromPacket(ipv4Pkt);
VIP vip = new LBUtil().getVIPFromPacket(ipv4Pkt);
- if(configManager.vipExists(vip)){
+ if (configManager.vipExists(vip)) {
VIP vipWithPoolName = configManager.getVIPWithPoolName(vip);
String poolMemberIp = null;
- if(vipWithPoolName.getPoolName() == null){
- lbsLogger.error("No pool attached. Please attach pool with the VIP -- {}",vip);
+ if (vipWithPoolName.getPoolName() == null) {
+ lbsLogger.error("No pool attached. Please attach pool with the VIP -- {}", vip);
return PacketResult.IGNORED;
}
- if(configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod().equalsIgnoreCase(LBConst.ROUND_ROBIN_LB_METHOD)){
+ if (configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod()
+ .equalsIgnoreCase(LBConst.ROUND_ROBIN_LB_METHOD)) {
- poolMemberIp = rrLBMethod.getPoolMemberForClient(client,vipWithPoolName);
+ poolMemberIp = rrLBMethod.getPoolMemberForClient(client, vipWithPoolName);
}
- if(configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod().equalsIgnoreCase(LBConst.RANDOM_LB_METHOD)){
- poolMemberIp = ranLBMethod.getPoolMemberForClient(client,vipWithPoolName);
+ if (configManager.getPool(vipWithPoolName.getPoolName()).getLbMethod()
+ .equalsIgnoreCase(LBConst.RANDOM_LB_METHOD)) {
+ poolMemberIp = ranLBMethod.getPoolMemberForClient(client, vipWithPoolName);
}
try {
Node clientNode = inPkt.getIncomingNodeConnector().getNode();
- HostNodeConnector hnConnector = this.hostTracker.hostFind(InetAddress.getByName(poolMemberIp));
+ // HostTracker hosts db key scheme implementation
+ IHostId id = HostIdFactory.create(InetAddress.getByName(poolMemberIp), null);
+ HostNodeConnector hnConnector = this.hostTracker.hostFind(id);
Node destNode = hnConnector.getnodeconnectorNode();
- lbsLogger.debug("Client is connected to switch : {}",clientNode.toString());
- lbsLogger.debug("Destination pool machine is connected to switch : {}",destNode.toString());
+ lbsLogger.debug("Client is connected to switch : {}", clientNode.toString());
+ lbsLogger
+ .debug("Destination pool machine is connected to switch : {}", destNode.toString());
- //Get path between both the nodes
+ // Get path between both the nodes
NodeConnector forwardPort = null;
- if(clientNode.getNodeIDString().equals(destNode.getNodeIDString())){
+ if (clientNode.getNodeIDString().equals(destNode.getNodeIDString())) {
forwardPort = hnConnector.getnodeConnector();
- lbsLogger.info("Both source (client) and destination pool machine is connected to same switch nodes. Respective ports are - {},{}",forwardPort,inPkt.getIncomingNodeConnector());
+ lbsLogger
+ .info("Both source (client) and destination pool machine is connected to same switch nodes. Respective ports are - {},{}",
+ forwardPort, inPkt.getIncomingNodeConnector());
- }else{
+ } else {
Path route = this.routing.getRoute(clientNode, destNode);
- lbsLogger.info("Path between source (client) and destination switch nodes : {}",route.toString());
+ lbsLogger.info("Path between source (client) and destination switch nodes : {}",
+ route.toString());
forwardPort = route.getEdges().get(0).getTailNodeConnector();
}
- if(installLoadBalancerFlow(client,
- vip,
- clientNode,
- poolMemberIp,
- hnConnector.getDataLayerAddressBytes(),
- forwardPort,
- LBConst.FORWARD_DIRECTION_LB_FLOW)){
- lbsLogger.info("Traffic from client : {} will be routed " +
- "to pool machine : {}",client,poolMemberIp);
- }else{
- lbsLogger.error("Not able to route traffic from client : {}",client );
+ if (installLoadBalancerFlow(client, vip, clientNode, poolMemberIp,
+ hnConnector.getDataLayerAddressBytes(), forwardPort,
+ LBConst.FORWARD_DIRECTION_LB_FLOW)) {
+ lbsLogger.info("Traffic from client : {} will be routed " + "to pool machine : {}",
+ client, poolMemberIp);
+ } else {
+ lbsLogger.error("Not able to route traffic from client : {}", client);
}
- if(installLoadBalancerFlow(client,
- vip,
- clientNode,
- poolMemberIp,
- vipMacAddr,
- inPkt.getIncomingNodeConnector(),
- LBConst.REVERSE_DIRECTION_LB_FLOW)){
- lbsLogger.info("Flow rule installed to change the source ip/mac from " +
- "pool machine ip {} to VIP {} for traffic coming pool machine",poolMemberIp,vip);
- }else{
- lbsLogger.error("Not able to route traffic from client : {}",client );
+ if (installLoadBalancerFlow(client, vip, clientNode, poolMemberIp, vipMacAddr,
+ inPkt.getIncomingNodeConnector(), LBConst.REVERSE_DIRECTION_LB_FLOW)) {
+ lbsLogger.info("Flow rule installed to change the source ip/mac from "
+ + "pool machine ip {} to VIP {} for traffic coming pool machine", poolMemberIp,
+ vip);
+ } else {
+ lbsLogger.error("Not able to route traffic from client : {}", client);
}
- }catch (UnknownHostException e) {
- lbsLogger.error("Pool member not found in the network : {}",e.getMessage());
- lbsLogger.error("",e);
+ } catch (UnknownHostException e) {
+ lbsLogger.error("Pool member not found in the network : {}", e.getMessage());
+ lbsLogger.error("", e);
}
}
}
}
/*
- * This method installs the flow rule for routing the traffic between two hosts.
- * @param source Traffic is sent by this source
- * @param dest Traffic is destined to this destination (VIP)
- * @param sourceSwitch Switch from where controller received the packet
- * @param destMachineIp IP address of the pool member where traffic needs to be routed
- * @param destMachineMac MAC address of the pool member where traffic needs to be routed
- * @param outport Use this port to send out traffic
- * @param flowDirection FORWARD_DIRECTION_LB_FLOW or REVERSE_DIRECTION_LB_FLOW
- * @return true If flow installation was successful
- * false else
- * @throws UnknownHostException
+ * This method installs the flow rule for routing the traffic between two
+ * hosts.
+ *
+ * @param source Traffic is sent by this source
+ *
+ * @param dest Traffic is destined to this destination (VIP)
+ *
+ * @param sourceSwitch Switch from where controller received the packet
+ *
+ * @param destMachineIp IP address of the pool member where traffic needs to
+ * be routed
+ *
+ * @param destMachineMac MAC address of the pool member where traffic needs
+ * to be routed
+ *
+ * @param outport Use this port to send out traffic
+ *
+ * @param flowDirection FORWARD_DIRECTION_LB_FLOW or
+ * REVERSE_DIRECTION_LB_FLOW
+ *
+ * @return true If flow installation was successful false else
+ *
+ * @throws UnknownHostException
*/
- private boolean installLoadBalancerFlow(Client source,
- VIP dest,
- Node sourceSwitch,
- String destMachineIp,
- byte[] destMachineMac,
- NodeConnector outport,
- int flowDirection) throws UnknownHostException{
+ private boolean installLoadBalancerFlow(Client source, VIP dest, Node sourceSwitch, String destMachineIp,
+ byte[] destMachineMac, NodeConnector outport, int flowDirection) throws UnknownHostException {
Match match = new Match();
List<Action> actions = new ArrayList<Action>();
- if(flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW){
+ if (flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW) {
match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());
match.setField(MatchType.NW_SRC, InetAddress.getByName(source.getIp()));
match.setField(MatchType.NW_DST, InetAddress.getByName(dest.getIp()));
actions.add(new SetDlDst(destMachineMac));
}
- if(flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW){
+ if (flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW) {
match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());
match.setField(MatchType.NW_SRC, InetAddress.getByName(destMachineIp));
match.setField(MatchType.NW_DST, InetAddress.getByName(source.getIp()));
match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(source.getProtocol()));
match.setField(MatchType.TP_SRC, dest.getPort());
- match.setField(MatchType.TP_DST,source.getPort());
+ match.setField(MatchType.TP_DST, source.getPort());
actions.add(new SetNwSrc(InetAddress.getByName(dest.getIp())));
actions.add(new SetDlSrc(destMachineMac));
flow.setHardTimeout((short) 0);
flow.setPriority(LB_IPSWITCH_PRIORITY);
- String policyName = source.getIp()+":"+source.getProtocol()+":"+source.getPort();
- String flowName =null;
+ String policyName = source.getIp() + ":" + source.getProtocol() + ":" + source.getPort();
+ String flowName = null;
- if(flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW){
- flowName = "["+policyName+":"+source.getIp() + ":"+dest.getIp()+"]";
+ if (flowDirection == LBConst.FORWARD_DIRECTION_LB_FLOW) {
+ flowName = "[" + policyName + ":" + source.getIp() + ":" + dest.getIp() + "]";
}
- if(flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW){
+ if (flowDirection == LBConst.REVERSE_DIRECTION_LB_FLOW) {
- flowName = "["+policyName+":"+dest.getIp() + ":"+source.getIp()+"]";
+ flowName = "[" + policyName + ":" + dest.getIp() + ":" + source.getIp() + "]";
}
FlowEntry fEntry = new FlowEntry(policyName, flowName, flow, sourceSwitch);
- lbsLogger.info("Install flow entry {} on node {}",fEntry.toString(),sourceSwitch.toString());
+ lbsLogger.info("Install flow entry {} on node {}", fEntry.toString(), sourceSwitch.toString());
- if(!this.ruleManager.checkFlowEntryConflict(fEntry)){
- if(this.ruleManager.installFlowEntry(fEntry).isSuccess()){
+ if (!this.ruleManager.checkFlowEntryConflict(fEntry)) {
+ if (this.ruleManager.installFlowEntry(fEntry).isSuccess()) {
return true;
- }else{
- lbsLogger.error("Error in installing flow entry to node : {}",sourceSwitch);
+ } else {
+ lbsLogger.error("Error in installing flow entry to node : {}", sourceSwitch);
}
- }else{
- lbsLogger.error("Conflicting flow entry exists : {}",fEntry.toString());
+ } else {
+ lbsLogger.error("Conflicting flow entry exists : {}", fEntry.toString());
}
return false;
}
this.containerName = (String) props.get("containerName");
lbsLogger.info("Running container name:" + this.containerName);
- }else {
+ } else {
// In the Global instance case the containerName is empty
this.containerName = "";
}
lbsLogger.info(configManager.toString());
+
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
*
*/
void destroy() {
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
*
*/
void start() {
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
*
*/
void stop() {
}
/*
- * All the methods below are just proxy methods to direct the REST API requests to configuration
- * manager. We need this redirection as currently, opendaylight supports only one
- * implementation of the service.
+ * All the methods below are just proxy methods to direct the REST API
+ * requests to configuration manager. We need this redirection as currently,
+ * opendaylight supports only one implementation of the service.
*/
@Override
public Set<VIP> getAllVIPs() {
}
@Override
- public boolean vipExists(String name, String ip, String protocol,
- short protocolPort, String poolName) {
+ public boolean vipExists(String name, String ip, String protocol, short protocolPort, String poolName) {
return configManager.vipExists(name, ip, protocol, protocolPort, poolName);
}
}
@Override
- public VIP createVIP(String name, String ip, String protocol,
- short protocolPort, String poolName) {
+ public VIP createVIP(String name, String ip, String protocol, short protocolPort, String poolName) {
return configManager.createVIP(name, ip, protocol, protocolPort, poolName);
}
}
@Override
- public PoolMember addPoolMember(String name,
- String memberIP,
- String poolName) {
+ public PoolMember addPoolMember(String name, String memberIP, String poolName) {
return configManager.addPoolMember(name, memberIP, poolName);
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.loadbalancer</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${samples.loadbalancer}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
- <version>0.4.0-SNAPSHOT</version>
+ <version>${hosttracker.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>${forwarding.staticrouting}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>