Bug 868: Remove AD-SAL components which were deprecated in Lithium
[controller.git] / opendaylight / adsal / samples / simpleforwarding / src / main / java / org / opendaylight / controller / samples / simpleforwarding / internal / SimpleForwardingImpl.java
diff --git a/opendaylight/adsal/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java b/opendaylight/adsal/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java
deleted file mode 100644 (file)
index a48d331..0000000
+++ /dev/null
@@ -1,1145 +0,0 @@
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.samples.simpleforwarding.internal;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.hosttracker.IfIptoHost;
-import org.opendaylight.controller.hosttracker.IfNewHostNotify;
-import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
-import org.opendaylight.controller.sal.action.Action;
-import org.opendaylight.controller.sal.action.Output;
-import org.opendaylight.controller.sal.action.PopVlan;
-import org.opendaylight.controller.sal.action.SetDlDst;
-import org.opendaylight.controller.sal.action.SetVlanId;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
-import org.opendaylight.controller.sal.core.Path;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.State;
-import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.flowprogrammer.Flow;
-import org.opendaylight.controller.sal.match.Match;
-import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.controller.sal.packet.Ethernet;
-import org.opendaylight.controller.sal.packet.IDataPacketService;
-import org.opendaylight.controller.sal.packet.IListenDataPacket;
-import org.opendaylight.controller.sal.packet.IPv4;
-import org.opendaylight.controller.sal.packet.Packet;
-import org.opendaylight.controller.sal.packet.PacketResult;
-import org.opendaylight.controller.sal.packet.RawPacket;
-import org.opendaylight.controller.sal.routing.IListenRoutingUpdates;
-import org.opendaylight.controller.sal.routing.IRouting;
-import org.opendaylight.controller.sal.utils.EtherTypes;
-import org.opendaylight.controller.sal.utils.NetUtils;
-import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.samples.simpleforwarding.HostNodePair;
-import org.opendaylight.controller.switchmanager.IInventoryListener;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class implements basic L3 forwarding within the managed devices.
- * Forwarding is only done within configured subnets.</br>
- * <br/>
- * The basic flow is that the module listens for new hosts from the
- * {@link org.opendaylight.controller.hosttracker.IfIptoHost HostTracker}
- * service and on discovering a new host it first calls
- * <tt>preparePerHostRules()</tt> to create a set of new rules that must be
- * installed in the network. This is done by repeatedly calling
- * <tt>updatePerHostRuleInSW()</tt> for each switch in the network. Then it
- * installs those rules using <tt>installPerHostRules()</tt>.
- */
-public class SimpleForwardingImpl implements IfNewHostNotify,
-        IListenRoutingUpdates, IInventoryListener, IListenDataPacket {
-    private static Logger log = LoggerFactory.getLogger(SimpleForwardingImpl.class);
-    private static short DEFAULT_IPSWITCH_PRIORITY = 1;
-    static final String FORWARDING_RULES_CACHE_NAME = "forwarding.ipswitch.rules";
-    private IfIptoHost hostTracker;
-    private IForwardingRulesManager frm;
-    private ITopologyManager topologyManager;
-    private IRouting routing;
-
-    /**
-     * The set of all forwarding rules: (host) -> (switch -> flowmod). Note that
-     * the host includes an attachment point and that while the switch appears
-     * to be a switch's port, in actuality it is a special port which just
-     * represents the switch.
-     */
-    private ConcurrentMap<HostNodePair, HashMap<NodeConnector, FlowEntry>> rulesDB;
-    private Map<Node, List<FlowEntry>> tobePrunedPos = new HashMap<Node, List<FlowEntry>>();
-    private IClusterContainerServices clusterContainerService = null;
-    private ISwitchManager switchManager;
-    private IDataPacketService dataPacketService;
-
-    /**
-     * Ip packets that are punted may not have their destination known by hostTracker at the time it
-     * is presented to SimpleForwardingImpl. Instead of dropping the packet, we will keep it around
-     * for a 'little' while, to accommodate any transients. See bug 590 for more details.
-     */
-    private class PendingPacketData {
-        private final static byte MAX_AGE = 2;
-
-        public final IPv4 pkt;
-        public final NodeConnector incomingNodeConnector;
-        private byte age;
-
-        public PendingPacketData(IPv4 pkt, NodeConnector incomingNodeConnector) {
-            this.pkt = pkt;
-            this.incomingNodeConnector = incomingNodeConnector;
-            this.age = 0;
-        }
-        boolean bumpAgeAndCheckIfTooOld() { return ++age > MAX_AGE; }
-    }
-    private static final int MAX_PENDING_PACKET_DESTINATIONS = 64;
-    private ConcurrentMap<InetAddress, PendingPacketData> pendingPacketDestinations;
-    private Timer pendingPacketsAgerTimer;
-
-    private class PendingPacketsAgerTimerHandler extends TimerTask {
-        @Override
-        public void run() {
-            if (pendingPacketDestinations == null) {
-                return;
-            }
-            try {
-                Iterator<ConcurrentMap.Entry<InetAddress, PendingPacketData>> iterator =
-                        pendingPacketDestinations.entrySet().iterator();
-                while (iterator.hasNext()) {
-                    ConcurrentHashMap.Entry<InetAddress, PendingPacketData> entry = iterator.next();
-                    InetAddress dIP = entry.getKey();
-                    PendingPacketData pendingPacketData = entry.getValue();
-
-                    if (pendingPacketData.bumpAgeAndCheckIfTooOld()) {
-                        iterator.remove(); // safe to remove while iterating...
-                        log.debug("Pending packet for {} has been aged out", dIP);
-                    } else {
-                        /** Replace the entry for a key only if currently mapped to some value.
-                         * This will protect the concurrent map against a race where this thread
-                         * would be re-adding an entry that just got taken out.
-                         */
-                        pendingPacketDestinations.replace(dIP, pendingPacketData);
-                    }
-                }
-            } catch (IllegalStateException e) {
-                log.warn("IllegalStateException Received by PendingPacketsAgerTimerHandler from: {}",
-                        e.getMessage());
-            }
-        }
-    }
-
-    /**
-     * Add punted packet to pendingPackets
-     */
-    private void addToPendingPackets(InetAddress dIP, IPv4 pkt, NodeConnector incomingNodeConnector) {
-        if (pendingPacketDestinations.size() >= MAX_PENDING_PACKET_DESTINATIONS) {
-            log.info("Will not pend packet for {}: Too many destinations", dIP);
-            return;
-        }
-
-        /** TODO: The current implementation allows for up to 1 pending packet per InetAddress.
-         * This limitation is done for sake of simplicity. A potential enhancement could be to use a
-         * ConcurrentMultiMap instead of ConcurrentMap.
-         */
-        if (pendingPacketDestinations.containsKey(dIP)) {
-            log.trace("Will not pend packet for {}: Already have a packet pending", dIP);
-            return;
-        }
-
-        PendingPacketData pendingPacketData = new PendingPacketData(pkt, incomingNodeConnector);
-        pendingPacketDestinations.put(dIP, pendingPacketData);
-        log.debug("Pending packet for {}", dIP);
-    }
-
-    /**
-     * Send punted packet to given destination. This is invoked when there is a certain level of
-     * hope that the destination is known by hostTracker.
-     */
-    private void sendPendingPacket(InetAddress dIP) {
-        PendingPacketData pendingPacketData = pendingPacketDestinations.get(dIP);
-        if (pendingPacketData != null) {
-            handlePuntedIPPacket(pendingPacketData.pkt, pendingPacketData.incomingNodeConnector, false);
-            log.trace("Packet for {} is no longer pending", dIP);
-            pendingPacketDestinations.remove(dIP);
-        }
-    }
-
-    /**
-     * Return codes from the programming of the perHost rules in HW
-     */
-    public enum RulesProgrammingReturnCode {
-        SUCCESS, FAILED_FEW_SWITCHES, FAILED_ALL_SWITCHES, FAILED_WRONG_PARAMS
-    }
-    public void setDataPacketService(IDataPacketService s) {
-        log.debug("Setting dataPacketService");
-        this.dataPacketService = s;
-    }
-
-    public void unsetDataPacketService(IDataPacketService s) {
-        if (this.dataPacketService == s) {
-            this.dataPacketService = null;
-        }
-    }
-
-    public void setRouting(IRouting routing) {
-        log.debug("Setting routing");
-        this.routing = routing;
-    }
-
-    public void unsetRouting(IRouting routing) {
-        if (this.routing == routing) {
-            this.routing = null;
-        }
-    }
-
-    public void setTopologyManager(ITopologyManager topologyManager) {
-        log.debug("Setting topologyManager");
-        this.topologyManager = topologyManager;
-    }
-
-    public void unsetTopologyManager(ITopologyManager topologyManager) {
-        if (this.topologyManager == topologyManager) {
-            this.topologyManager = null;
-        }
-    }
-
-    public void setHostTracker(IfIptoHost hostTracker) {
-        log.debug("Setting HostTracker");
-        this.hostTracker = hostTracker;
-    }
-
-    public void setForwardingRulesManager(
-            IForwardingRulesManager forwardingRulesManager) {
-        log.debug("Setting ForwardingRulesManager");
-        this.frm = forwardingRulesManager;
-    }
-
-    public void unsetHostTracker(IfIptoHost hostTracker) {
-        if (this.hostTracker == hostTracker) {
-            this.hostTracker = null;
-        }
-    }
-
-    public void unsetForwardingRulesManager(
-            IForwardingRulesManager forwardingRulesManager) {
-        if (this.frm == forwardingRulesManager) {
-            this.frm = null;
-        }
-    }
-
-    /**
-     * Function called when the bundle gets activated
-     *
-     */
-    public void startUp() {
-        allocateCaches();
-        retrieveCaches();
-        nonClusterObjectCreate();
-    }
-
-    public void nonClusterObjectCreate() {
-        pendingPacketDestinations = new ConcurrentHashMap<InetAddress, PendingPacketData>();
-
-        /* Pending Packets Ager Timer to go off every 6 seconds to implement pending packet aging */
-        pendingPacketsAgerTimer = new Timer();
-        pendingPacketsAgerTimer.schedule(new PendingPacketsAgerTimerHandler(), 6000, 6000);
-    }
-
-    /**
-     * Function called when the bundle gets stopped
-     *
-     */
-    public void shutDown() {
-        log.debug("Destroy all the host Rules given we are shutting down");
-        uninstallPerHostRules();
-        destroyCaches();
-    }
-
-    private void allocateCaches() {
-        if (this.clusterContainerService == null) {
-            log.trace("un-initialized clusterContainerService, can't create cache");
-            return;
-        }
-
-        try {
-            clusterContainerService.createCache(FORWARDING_RULES_CACHE_NAME,
-                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-        } catch (CacheExistException cee) {
-            log.error("\nCache already exists - destroy and recreate if needed");
-        } catch (CacheConfigException cce) {
-            log.error("\nCache configuration invalid - check cache mode");
-        }
-    }
-
-    @SuppressWarnings({ "unchecked" })
-    private void retrieveCaches() {
-        if (this.clusterContainerService == null) {
-            log.trace("un-initialized clusterContainerService, can't retrieve cache");
-            return;
-        }
-
-        rulesDB = (ConcurrentMap<HostNodePair, HashMap<NodeConnector, FlowEntry>>) clusterContainerService
-                .getCache(FORWARDING_RULES_CACHE_NAME);
-        if (rulesDB == null) {
-            log.error("\nFailed to get rulesDB handle");
-        }
-    }
-
-    private void destroyCaches() {
-        if (this.clusterContainerService == null) {
-            log.trace("un-initialized clusterContainerService, can't destroy cache");
-            return;
-        }
-
-        clusterContainerService.destroyCache(FORWARDING_RULES_CACHE_NAME);
-    }
-
-    /**
-     * Populates <tt>rulesDB</tt> with rules specifying how to reach
-     * <tt>host</tt> from <tt>currNode</tt> assuming that:
-     * <ul>
-     * <li><tt>host</tt> is attached to <tt>rootNode</tt>
-     * <li><tt>link</tt> is the next part of the path to reach <tt>rootNode</tt>
-     * from <tt>currNode</tt>
-     * <li><tt>rulesDB.get(key)</tt> represents the list of rules stored about
-     * <tt>host</tt> at <tt>currNode</tt>
-     * </ul>
-     *
-     * @param host
-     *            The host to be reached.
-     * @param currNode
-     *            The current node being processed.
-     * @param rootNode
-     *            The node to be reached. Really, the switch which host is
-     *            attached to.
-     * @param link
-     *            The link to follow from curNode to get to rootNode
-     * @param key
-     *            The key to store computed rules at in the rulesDB. For now,
-     *            this is a {@link HostNodePair} of host and currNode.
-     */
-    private void updatePerHostRuleInSW(HostNodeConnector host, Node currNode,
-            Node rootNode, Edge link, HostNodePair key) {
-
-        // only the link parameter is optional
-        if (host == null || key == null || currNode == null || rootNode == null) {
-            return;
-        }
-
-        Set<NodeConnector> ports = new HashSet<NodeConnector>();
-        // add a special port of type ALL and port 0 to represent the node
-        // without specifying a port on that node
-        ports.add(NodeConnectorCreator.createNodeConnector(
-                NodeConnectorIDType.ALL, NodeConnector.SPECIALNODECONNECTORID,
-                currNode));
-
-        HashMap<NodeConnector, FlowEntry> pos = this.rulesDB.get(key);
-        if (pos == null) {
-            pos = new HashMap<NodeConnector, FlowEntry>();
-        }
-
-        for (NodeConnector inPort : ports) {
-            // skip the port connected to the target host
-            if (currNode.equals(rootNode)
-                    && (host.getnodeConnector().equals(inPort))) {
-                continue;
-            }
-
-            // remove the current rule, if any
-            FlowEntry removed_po = pos.remove(inPort);
-            Match match = new Match();
-            List<Action> actions = new ArrayList<Action>();
-
-            // IP destination based forwarding on /32 entries only!
-            match.setField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue());
-            match.setField(MatchType.NW_DST, host.getNetworkAddress());
-
-            /* Action for the policy is to forward to a port except on the
-             * switch where the host sits, which is to rewrite also the MAC
-             * and to forward on the Host port */
-            NodeConnector outPort = null;
-
-            if (currNode.equals(rootNode)) {
-                /* If we're at the root node, then rewrite the DL addr and
-                 * possibly pop the VLAN tag. This allows for MAC rewriting
-                 * in the core of the network assuming we can uniquely ID
-                 * packets based on IP address. */
-
-                outPort = host.getnodeConnector();
-                if (inPort.equals(outPort)) {
-                    // TODO: isn't this code skipped already by the above continue?
-                    // skip the host port
-                    continue;
-                }
-                actions.add(new SetDlDst(host.getDataLayerAddressBytes()));
-
-                if (!inPort.getType().equals(NodeConnectorIDType.ALL)) {
-                    // Container mode: at the destination switch, we need to strip out the tag (VLAN)
-                    actions.add(new PopVlan());
-                }
-            } else {
-                // currNode is NOT the rootNode, find the next hop and create a rule
-                if (link != null) {
-                    outPort = link.getTailNodeConnector();
-                    if (inPort.equals(outPort)) {
-                        // skip the outgoing port
-                        continue;
-                    }
-
-                    // If outPort is network link, add VLAN tag
-                    if (topologyManager.isInternal(outPort)) {
-                        log.debug("outPort {}/{} is internal uplink port",
-                                currNode, outPort);
-                    } else {
-                        log.debug("outPort {}/{} is host facing port",
-                                currNode, outPort);
-                    }
-
-                    if ((!inPort.getType().equals(NodeConnectorIDType.ALL))
-                        && (topologyManager.isInternal(outPort))) {
-                        Node nextNode = link.getHeadNodeConnector()
-                                            .getNode();
-                        // TODO: Replace this with SAL equivalent
-                        //short tag = container.getTag((Long)nextNode.getNodeID());
-                        short tag = 0;
-                        if (tag != 0) {
-                            log.debug("adding SET_VLAN {} for traffic " +
-                                    "leaving {}/{} toward switch {}",
-                                    new Object[] { tag, currNode, outPort,
-                                    nextNode});
-                            actions.add(new SetVlanId(tag));
-                        } else {
-                            log.debug("No tag assigned to switch {}", nextNode);
-                        }
-                    }
-                }
-            }
-            if (outPort != null) {
-                actions.add(new Output(outPort));
-            }
-            if (!inPort.getType().equals(NodeConnectorIDType.ALL)) {
-                // include input port in the flow match field
-                match.setField(MatchType.IN_PORT, inPort);
-
-                if (topologyManager.isInternal(inPort)) {
-                    log.debug("inPort {}/{} is internal uplink port", currNode,
-                            inPort);
-                } else {
-                    log.debug("inPort {}/{} is host facing port", currNode,
-                            inPort);
-                }
-
-                // for incoming network link; if the VLAN tag is defined, include it for incoming flow matching
-                if (topologyManager.isInternal(inPort)) {
-                    // TODO: Replace this with SAL equivalent
-                    //short tag = container.getTag((Long)currNode.getNodeID());
-                    short tag = 0;
-                    if (tag != 0) {
-                        log.debug("adding MATCH VLAN {} for traffic entering" +
-                                "  {}/{}",
-                                new Object[] {tag, currNode, inPort});
-                        match.setField(MatchType.DL_VLAN, tag);
-                    } else {
-                        log.debug("No tag assigned to switch {}", currNode);
-                    }
-                }
-            }
-            // Make sure the priority for IP switch entries is
-            // set to a level just above default drop entries
-            Flow flow = new Flow(match, actions);
-            flow.setIdleTimeout((short) 0);
-            flow.setHardTimeout((short) 0);
-            flow.setPriority(DEFAULT_IPSWITCH_PRIORITY);
-
-            String policyName = host.getNetworkAddress().getHostAddress()
-                    + "/32";
-            String flowName = "["
-                    + (!inPort.getType().equals(NodeConnectorIDType.ALL) ?
-                       (inPort.getID()).toString()
-                       + "," : "")
-                    + host.getNetworkAddress().getHostAddress() + "/32 on N "
-                    + currNode + "]";
-            FlowEntry po = new FlowEntry(policyName, flowName, flow, currNode);
-
-            /* Now save the rule in the DB rule, so on updates from topology we
-             * can selectively */
-            pos.put(inPort, po);
-            this.rulesDB.put(key, pos);
-            if (!inPort.getType().equals(NodeConnectorIDType.ALL)) {
-                log.debug("Adding Match(inPort = {} , DIP = {})" +
-                        " Action(outPort= {}) to node {}",
-                        new Object[] { inPort,
-                        host.getNetworkAddress().getHostAddress(),
-                        outPort, currNode});
-                if ((removed_po != null)
-                        && (!po.getFlow().getMatch().equals(
-                                removed_po.getFlow().getMatch()))) {
-                    log.debug("Old Flow match: {}, New Flow match: {}",
-                            removed_po.getFlow().getMatch(), po.getFlow()
-                                    .getMatch());
-                    addTobePrunedPolicy(currNode, removed_po, po);
-                }
-
-            } else {
-                log.debug("Adding policyMatch(DIP = {}) Action(outPort= {}) " +
-                        "to node {}", new Object[] {
-                        host.getNetworkAddress().getHostAddress(), outPort,
-                        currNode});
-            }
-        }
-    }
-
-    /**
-     * Calculate the per-Host rules to be installed in the rulesDB,
-     * and that will later on be installed in HW, this routine will
-     * implicitly calculate the shortest path tree among the switch
-     * to which the host is attached and all the other switches in the
-     * network and will automatically create all the rules that allow
-     * a /32 destination IP based forwarding, as in traditional IP
-     * networks.
-     *
-     * @param host Host for which we are going to prepare the rules in the rulesDB
-     *
-     * @return A set of switches touched by the calculation
-     */
-    private Set<Node> preparePerHostRules(HostNodeConnector host) {
-        if (host == null) {
-            return null;
-        }
-
-        //TODO: race condition! unset* functions can make these null.
-        if (this.routing == null) {
-            return null;
-        }
-        if (this.switchManager == null) {
-            return null;
-        }
-        if (this.rulesDB == null) {
-            return null;
-        }
-
-        Node rootNode = host.getnodeconnectorNode();
-        Set<Node> nodes = this.switchManager.getNodes();
-        Set<Node> switchesToProgram = new HashSet<Node>();
-        HostNodePair key;
-        HashMap<NodeConnector, FlowEntry> pos;
-        FlowEntry po;
-
-        // for all nodes in the system
-        for (Node node : nodes) {
-            if (node.equals(rootNode)) {
-                // We skip it because for the node with host attached
-                // we will process in every case even if there are no
-                // routes
-                continue;
-            }
-            List<Edge> links;
-            Path res = this.routing.getRoute(node, rootNode);
-            if ((res == null) || ((links = res.getEdges()) == null)) {
-                // No route from node to rootNode can be found, back out any
-                // existing forwarding rules if they exist.
-                log.debug("NO Route/Path between SW[{}] --> SW[{}] cleaning " +
-                        "potentially existing entries", node, rootNode);
-                key = new HostNodePair(host, node);
-                pos = this.rulesDB.get(key);
-                if (pos != null) {
-                    for (Map.Entry<NodeConnector, FlowEntry> e : pos.entrySet()) {
-                        po = e.getValue();
-                        if (po != null) {
-                            // uninstall any existing rules we put in the
-                            // ForwardingRulesManager
-                            this.frm.uninstallFlowEntry(po);
-                        }
-                    }
-                    this.rulesDB.remove(key);
-                }
-                continue;
-            }
-
-            log.debug("Route between SW[{}] --> SW[{}]", node, rootNode);
-            Node currNode = node;
-            key = new HostNodePair(host, currNode);
-
-            // for each link in the route from here to there
-            for (Edge link : links) {
-                if (link == null) {
-                    log.error("Could not retrieve the Link");
-                    // TODO: should we keep going?
-                    continue;
-                }
-
-                log.debug(link.toString());
-
-                // Index all the switches to be programmed
-                updatePerHostRuleInSW(host, currNode, rootNode, link, key);
-                if ((this.rulesDB.get(key)) != null) {
-                    /* Calling updatePerHostRuleInSW() doesn't guarantee that
-                     * rules will be added in currNode (e.g, there is only one
-                     * link from currNode to rootNode This check makes sure that
-                     * there are some rules in the rulesDB for the given key
-                     * prior to adding switch to switchesToProgram
-                     */
-                    switchesToProgram.add(currNode);
-                }
-                currNode = link.getHeadNodeConnector().getNode();
-                key = new HostNodePair(host, currNode);
-            }
-        }
-
-        // This rule will be added no matter if any topology is built
-        // or no, it serve as a way to handle the case of a node with
-        // multiple hosts attached to it but not yet connected to the
-        // rest of the world
-        switchesToProgram.add(rootNode);
-        updatePerHostRuleInSW(host, rootNode, rootNode, null,
-                              new HostNodePair(host, rootNode));
-
-        //      log.debug("Getting out at the end!");
-        return switchesToProgram;
-    }
-
-    /**
-     * Calculate the per-Host rules to be installed in the rulesDB
-     * from a specific switch when a host facing port comes up.
-     * These rules will later on be installed in HW. This routine
-     * will implicitly calculate the shortest path from the switch
-     * where the port has come up to the switch where host is ,
-     * attached and will automatically create all the rules that allow
-     * a /32 destination IP based forwarding, as in traditional IP
-     * networks.
-     *
-     * @param host Host for which we are going to prepare the rules in the rulesDB
-     * @param swId Switch ID where the port has come up
-     *
-     * @return A set of switches touched by the calculation
-     */
-    private Set<Node> preparePerHostPerSwitchRules(HostNodeConnector host,
-            Node node, NodeConnector swport) {
-        if ((host == null) || (node == null)) {
-            return null;
-        }
-        if (this.routing == null) {
-            return null;
-        }
-        if (this.switchManager == null) {
-            return null;
-        }
-        if (this.rulesDB == null) {
-            return null;
-        }
-
-        Node rootNode = host.getnodeconnectorNode();
-        Set<Node> switchesToProgram = new HashSet<Node>();
-        HostNodePair key;
-        Map<NodeConnector, FlowEntry> pos;
-        FlowEntry po;
-        List<Edge> links;
-
-        Path res = this.routing.getRoute(node, rootNode);
-        if ((res == null) || ((links = res.getEdges()) == null)) {
-            // the routing service doesn't know how to get there from here
-            log.debug("NO Route/Path between SW[{}] --> SW[{}] cleaning " +
-                    "potentially existing entries", node, rootNode);
-            key = new HostNodePair(host, node);
-            pos = this.rulesDB.get(key);
-            if (pos != null) {
-                for (Map.Entry<NodeConnector, FlowEntry> e : pos.entrySet()) {
-                    po = e.getValue();
-                    if (po != null) {
-                        //Uninstall the policy
-                        this.frm.uninstallFlowEntry(po);
-                    }
-                }
-                this.rulesDB.remove(key);
-            }
-            return null;
-        }
-
-        log.debug("Route between SW[{}] --> SW[{}]", node, rootNode);
-        Integer curr;
-        Node currNode = node;
-        key = new HostNodePair(host, currNode);
-        Edge link;
-        for (curr = 0; curr < links.size(); curr++) {
-            link = links.get(curr);
-            if (link == null) {
-                log.error("Could not retrieve the Link");
-                continue;
-            }
-
-            log.debug("Link [{}/{}] --> [{}/{}]", new Object[] {
-                    currNode, link.getHeadNodeConnector(),
-                    link.getHeadNodeConnector().getNode(),
-                    link.getTailNodeConnector()});
-
-            // Index all the switches to be programmed
-            switchesToProgram.add(currNode);
-            updatePerHostRuleInSW(host, currNode, rootNode, link, key);
-            break; // come out of the loop for port up case, interested only in programming one switch
-        }
-
-        // This rule will be added no matter if any topology is built
-        // or no, it serve as a way to handle the case of a node with
-        // multiple hosts attached to it but not yet connected to the
-        // rest of the world
-        // switchesToProgram.add(rootNode);
-        //updatePerHostRuleInSW(host, rootNode,
-        //                                        rootNode, null,
-        //                                        new HostNodePair(host, rootNode),ports);
-
-        //      log.debug("Getting out at the end!");
-        return switchesToProgram;
-    }
-
-    /**
-     * Routine that fetch the per-Host rules from the rulesDB and
-     * install in HW, the one having the same match rules will be
-     * overwritten silently.
-     *
-     * @param host host for which we want to install in HW the per-Host rules
-     * @param switchesToProgram list of switches to be programmed in
-     * HW, usually are them all, but better to be explicit, that list
-     * may change with time based on new switch addition/removal
-     *
-     * @return a return code that convey the programming status of the HW
-     */
-    private RulesProgrammingReturnCode installPerHostRules(
-            HostNodeConnector host, Set<Node> switchesToProgram) {
-        RulesProgrammingReturnCode retCode = RulesProgrammingReturnCode.SUCCESS;
-        if (host == null || switchesToProgram == null) {
-            return RulesProgrammingReturnCode.FAILED_WRONG_PARAMS;
-        }
-        Map<NodeConnector, FlowEntry> pos;
-        FlowEntry po;
-        // Now program every single switch
-        log.debug("Inside installPerHostRules");
-        for (Node swId : switchesToProgram) {
-            HostNodePair key = new HostNodePair(host, swId);
-            pos = this.rulesDB.get(key);
-            if (pos == null) {
-                continue;
-            }
-            for (Map.Entry<NodeConnector, FlowEntry> e : pos.entrySet()) {
-                po = e.getValue();
-                if (po != null) {
-                    // Populate the Policy field now
-                    Status poStatus = this.frm.modifyOrAddFlowEntry(po);
-                    if (!poStatus.isSuccess()) {
-                        log.error("Failed to install policy: "
-                                + po.getGroupName() + " ("
-                                + poStatus.getDescription() + ")");
-
-                        retCode = RulesProgrammingReturnCode.FAILED_FEW_SWITCHES;
-                        // Remove the entry from the DB, it was not installed!
-                        this.rulesDB.remove(key);
-                    } else {
-                        log.debug("Successfully installed policy "
-                                + po.toString() + " on switch " + swId);
-                    }
-                } else {
-                    log.error("Cannot find a policy for SW:({}) Host: ({})",
-                              swId, host);
-                    /* // Now dump every single rule */
-                    /* for (HostNodePair dumpkey : this.rulesDB.keySet()) { */
-                    /*  po = this.rulesDB.get(dumpkey); */
-                    /*  log.debug("Dumping entry H{" + dumpkey.getHost() + "} S{" + dumpkey.getSwitchId() + "} = {" + (po == null ? "null policy" : po)); */
-                    /* } */
-                }
-            }
-        }
-        log.debug("Leaving installPerHostRules");
-        return retCode;
-    }
-
-    /**
-     * Cleanup all the host rules for a given host
-     *
-     * @param host Host for which the host rules need to be cleaned
-     * up, the host could be null in that case it match all the hosts
-     *
-     * @return a return code that convey the programming status of the HW
-     */
-    private RulesProgrammingReturnCode uninstallPerHostRules(HostNodeConnector host) {
-        RulesProgrammingReturnCode retCode = RulesProgrammingReturnCode.SUCCESS;
-        Map<NodeConnector, FlowEntry> pos;
-        FlowEntry po;
-        // Now program every single switch
-        for (HostNodePair key : this.rulesDB.keySet()) {
-            if (host == null || key.getHost().equals(host)) {
-                pos = this.rulesDB.get(key);
-                for (Map.Entry<NodeConnector, FlowEntry> e : pos.entrySet()) {
-                    po = e.getValue();
-                    if (po != null) {
-                        // Uninstall the policy
-                        this.frm.uninstallFlowEntry(po);
-                    }
-                }
-                this.rulesDB.remove(key);
-            }
-        }
-        return retCode;
-    }
-
-    /**
-     * Cleanup all the host rules for a given node, triggered when the
-     * switch disconnects, so there is no reason for Hw cleanup
-     * because it's disconnected anyhow
-     * TBD - Revisit above stmt in light of CSCus88743
-     * @param targetNode Node for which we want to do cleanup
-     *
-     */
-    private void uninstallPerNodeRules(Node targetNode) {
-        //RulesProgrammingReturnCode retCode = RulesProgrammingReturnCode.SUCCESS;
-        Map<NodeConnector, FlowEntry> pos;
-        FlowEntry po;
-
-        // Now program every single switch
-        for (HostNodePair key : this.rulesDB.keySet()) {
-            Node node = key.getNode();
-            if (targetNode == null || node.equals(targetNode)) {
-                log.debug("Work on {} host {}", node, key.getHost());
-                pos = this.rulesDB.get(key);
-                for (Map.Entry<NodeConnector, FlowEntry> e : pos.entrySet()) {
-                    po = e.getValue();
-                    if (po != null) {
-                        // Uninstall the policy
-                        this.frm.uninstallFlowEntry(po);
-                    }
-                }
-                log.debug("Remove {}", key);
-                this.rulesDB.remove(key);
-            }
-        }
-    }
-
-    /**
-     * Cleanup all the host rules currently present in the rulesDB
-     *
-     * @return a return code that convey the programming status of the HW
-     */
-    private RulesProgrammingReturnCode uninstallPerHostRules() {
-        return uninstallPerHostRules(null);
-    }
-
-    @Override
-    public void recalculateDone() {
-        if (this.hostTracker == null) {
-            //Not yet ready to process all the updates
-            //TODO: we should make sure that this call is executed eventually
-            return;
-        }
-        Set<HostNodeConnector> allHosts = this.hostTracker.getAllHosts();
-        for (HostNodeConnector host : allHosts) {
-            Set<Node> switches = preparePerHostRules(host);
-            if (switches != null) {
-                // This will refresh existing rules, by overwriting
-                // the previous ones
-                installPerHostRules(host, switches);
-                pruneExcessRules(switches);
-            }
-        }
-    }
-
-    void addTobePrunedPolicy(Node swId, FlowEntry po, FlowEntry new_po) {
-        List<FlowEntry> pl = tobePrunedPos.get(swId);
-        if (pl == null) {
-            pl = new LinkedList<FlowEntry>();
-            tobePrunedPos.put(swId, pl);
-        }
-        pl.add(po);
-        log.debug("Adding Pruned Policy for SwId: {}", swId);
-        log.debug("Old Policy: {}", po);
-        log.debug("New Policy: {}", new_po);
-    }
-
-    private void pruneExcessRules(Set<Node> switches) {
-        for (Node swId : switches) {
-            List<FlowEntry> pl = tobePrunedPos.get(swId);
-            if (pl != null) {
-                log.debug("Policies for Switch: {} in the list to be deleted: {}", swId, pl);
-                Iterator<FlowEntry> plIter = pl.iterator();
-                //for (Policy po: pl) {
-                while (plIter.hasNext()) {
-                    FlowEntry po = plIter.next();
-                    log.error("Removing Policy, Switch: {} Policy: {}", swId, po);
-                    this.frm.uninstallFlowEntry(po);
-                    plIter.remove();
-                }
-            }
-            // tobePrunedPos.remove(swId);
-        }
-    }
-
-    /**
-     * A Host facing port has come up in a container. Add rules on the switch where this
-     * port has come up for all the known hosts to the controller.
-     * @param swId switch id of the port where port came up
-     * @param swPort port which came up
-     */
-    private void updateRulesforHIFup(Node node, NodeConnector swPort) {
-        if (this.hostTracker == null) {
-            //Not yet ready to process all the updates
-            return;
-        }
-        log.debug("Host Facing Port in a container came up, install the rules for all hosts from this port !");
-        Set<HostNodeConnector> allHosts = this.hostTracker.getAllHosts();
-        for (HostNodeConnector host : allHosts) {
-            if (node.equals(host.getnodeconnectorNode())) {
-                /*
-                 * This host resides behind the same switch and port for which a port up
-                 * message is received. Ideally this should not happen, but if it does,
-                 * don't program any rules for this host
-                 */
-                continue;
-            }
-            Set<Node> switches = preparePerHostPerSwitchRules(host, node,
-                    swPort);
-            if (switches != null) {
-                // This will refresh existing rules, by overwriting
-                // the previous ones
-                installPerHostRules(host, switches);
-            }
-        }
-
-    }
-
-    @Override
-    public void notifyHTClient(HostNodeConnector host) {
-        if (host == null) {
-            return;
-        }
-        Set<Node> switches = preparePerHostRules(host);
-        if (switches != null) {
-            installPerHostRules(host, switches);
-
-            // Green light for sending pending packet to this host. Safe to call if there are none.
-            sendPendingPacket(host.getNetworkAddress());
-        }
-    }
-
-    @Override
-    public void notifyHTClientHostRemoved(HostNodeConnector host) {
-        if (host == null) {
-            return;
-        }
-        uninstallPerHostRules(host);
-    }
-
-    @Override
-    public void notifyNode(Node node, UpdateType type,
-            Map<String, Property> propMap) {
-        if (node == null) {
-            return;
-        }
-
-        switch (type) {
-        case REMOVED:
-            log.debug("Node {} gone, doing a cleanup", node);
-            uninstallPerNodeRules(node);
-            break;
-        default:
-            break;
-        }
-    }
-
-    @Override
-    public void notifyNodeConnector(NodeConnector nodeConnector,
-            UpdateType type, Map<String, Property> propMap) {
-        if (nodeConnector == null) {
-            return;
-        }
-
-        boolean up = false;
-        switch (type) {
-        case ADDED:
-            up = true;
-            break;
-        case REMOVED:
-            break;
-        case CHANGED:
-            State state = (State) propMap.get(State.StatePropName);
-            if ((state != null) && (state.getValue() == State.EDGE_UP)) {
-                up = true;
-            }
-            break;
-        default:
-            return;
-        }
-
-        if (up) {
-            handleNodeConnectorStatusUp(nodeConnector);
-        } else {
-            handleNodeConnectorStatusDown(nodeConnector);
-        }
-    }
-
-    private void handleNodeConnectorStatusUp(NodeConnector nodeConnector) {
-        if (topologyManager == null) {
-            log.debug("topologyManager is not set yet");
-            return;
-        }
-
-        if (topologyManager.isInternal(nodeConnector)) {
-            log.debug("{} is not a host facing link", nodeConnector);
-            return;
-        }
-
-        log.debug("{} is up", nodeConnector);
-        updateRulesforHIFup(nodeConnector.getNode(), nodeConnector);
-    }
-
-    private void handleNodeConnectorStatusDown(NodeConnector nodeConnector) {
-        log.debug("{} is down", nodeConnector);
-    }
-
-    void setClusterContainerService(IClusterContainerServices s) {
-        log.debug("Cluster Service set");
-        this.clusterContainerService = s;
-    }
-
-    void unsetClusterContainerService(IClusterContainerServices s) {
-        if (this.clusterContainerService == s) {
-            log.debug("Cluster Service removed!");
-            this.clusterContainerService = null;
-        }
-    }
-
-    /**
-     * Function called by the dependency manager when all the required
-     * dependencies are satisfied
-     *
-     */
-    void init() {
-        startUp();
-    }
-
-    /**
-     * 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
-     *
-     */
-    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
-     *
-     */
-    void stop() {
-        pendingPacketsAgerTimer.cancel();
-        pendingPacketDestinations.clear();
-    }
-
-    public void setSwitchManager(ISwitchManager switchManager) {
-        this.switchManager = switchManager;
-    }
-
-    public void unsetSwitchManager(ISwitchManager switchManager) {
-        if (this.switchManager == switchManager) {
-            this.switchManager = null;
-        }
-    }
-
-    @Override
-    public PacketResult receiveDataPacket(RawPacket inPkt) {
-        if (inPkt == null) {
-            return PacketResult.IGNORED;
-        }
-        log.trace("Received a frame of size: {}", inPkt.getPacketData().length);
-        Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
-        if (formattedPak instanceof Ethernet) {
-            Object nextPak = formattedPak.getPayload();
-            if (nextPak instanceof IPv4) {
-                log.trace("Handle punted IP packet: {}", formattedPak);
-                handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector(), true);
-            }
-        }
-        return PacketResult.IGNORED;
-
-    }
-
-    private void handlePuntedIPPacket(IPv4 pkt, NodeConnector incomingNodeConnector, boolean allowAddPending) {
-        InetAddress dIP = NetUtils.getInetAddress(pkt.getDestinationAddress());
-        if (dIP == null || hostTracker == null) {
-            log.debug("Invalid param(s) in handlePuntedIPPacket.. DestIP: {}. hostTracker: {}", dIP, hostTracker);
-            return;
-        }
-        HostNodeConnector destHost = hostTracker.hostFind(dIP);
-        /*
-         * In cases when incoming and outgoing connectors are in the same node, there is no need
-         * to verify that there is a route. Because of that, we will only need routing.getRoute()
-         * if we know that src and dst nodes are different.
-         */
-        if (destHost != null
-                && (incomingNodeConnector.getNode().equals(destHost.getnodeconnectorNode()) ||
-                    routing == null ||
-                    routing.getRoute(incomingNodeConnector.getNode(), destHost.getnodeconnectorNode()) != null)) {
-
-            log.trace("Host {} is at {}", dIP, destHost.getnodeConnector());
-
-            // If SimpleForwarding is aware of this host, it will try to install
-            // a path. Forward packet until it's done.
-            if (dataPacketService != null) {
-
-                /*
-                 * if we know where the host is and there's a path from where this
-                 * packet was punted to where the host is, then attempt best effort delivery to the host
-                 */
-                NodeConnector nc = destHost.getnodeConnector();
-                log.trace("Forwarding punted IP received at {} to {}", incomingNodeConnector, nc);
-                // re-encode the Ethernet packet (the parent of the IPv4 packet)
-                RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent());
-                rp.setOutgoingNodeConnector(nc);
-                this.dataPacketService.transmitDataPacket(rp);
-            }
-        } else if (allowAddPending) {
-            // If we made it here, let's hang on to the punted packet, with hopes that its destination
-            // will become available soon.
-            addToPendingPackets(dIP, pkt, incomingNodeConnector);
-        } else {
-            log.warn("Dropping punted IP packet received at {} to Host {}", incomingNodeConnector, dIP);
-        }
-    }
-}