ONOS-2740,ONOS-2741,from ONOS-3032 - to ONOS 3071 , OSPF Protocol Implementation

Change-Id: I592453c21440afa5240c74dc4e9e134f876c89b3
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfAreaImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfAreaImpl.java
new file mode 100755
index 0000000..2c33ed5
--- /dev/null
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfAreaImpl.java
@@ -0,0 +1,803 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ospf.controller.area;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.ospf.controller.LsaWrapper;
+import org.onosproject.ospf.controller.OspfArea;
+import org.onosproject.ospf.controller.OspfAreaAddressRange;
+import org.onosproject.ospf.controller.OspfInterface;
+import org.onosproject.ospf.controller.OspfLsa;
+import org.onosproject.ospf.controller.OspfLsaType;
+import org.onosproject.ospf.controller.OspfLsdb;
+import org.onosproject.ospf.controller.OspfNbr;
+import org.onosproject.ospf.controller.OspfNeighborState;
+import org.onosproject.ospf.controller.impl.OspfNbrImpl;
+import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
+import org.onosproject.ospf.protocol.lsa.LsaHeader;
+import org.onosproject.ospf.protocol.lsa.subtypes.OspfLsaLink;
+import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
+import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
+import org.onosproject.ospf.protocol.util.ChecksumCalculator;
+import org.onosproject.ospf.protocol.util.OspfInterfaceState;
+import org.onosproject.ospf.protocol.util.OspfParameters;
+import org.onosproject.ospf.protocol.util.OspfUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representation an OSPF area and related information.
+ */
+public class OspfAreaImpl implements OspfArea {
+    private static final Logger log = LoggerFactory.getLogger(OspfAreaImpl.class);
+    /**
+     * Address ranges in order to aggregate routing information at area.
+     * boundaries. Each address range is specified by an [address,mask] pair and
+     * a status indication of either Advertise or DoNotAdvertise
+     */
+    private List<OspfAreaAddressRange> addressRanges;
+    /**
+     * This parameter indicates whether the area can carry data traffic that.
+     * neither originates nor terminates in the area itself.
+     */
+    private boolean transitCapability;
+    /**
+     * Whether AS-external-LSAs will be flooded into/throughout the area.
+     */
+    private boolean externalRoutingCapability;
+    /**
+     * Indicates the cost of the default summary-LSA.
+     */
+    private int stubCost;
+    /**
+     * Represents a list of all router's interfaces associated with this area.
+     */
+    private List<OspfInterface> interfacesLst;
+    /**
+     * The LS Database for this area. It includes router-LSAs, network-LSAs and.
+     * summary-LSAs. AS-external-LSAs are hold in the OSPF class itself.
+     */
+    private OspfLsdbImpl database;
+    /**
+     * A 32-bit number identifying the area.
+     */
+    private Ip4Address areaId;
+    /**
+     * Router ID.
+     */
+    private Ip4Address routerId;
+    /**
+     * Represents Options like external, opaque capabilities.
+     */
+    private int options;
+    /**
+     * Represents Opaque Enable or not.
+     */
+    private boolean isOpaqueEnable;
+
+    /**
+     * Creates an instance of area implementation.
+     */
+    public OspfAreaImpl() {
+        database = new OspfLsdbImpl(this);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        OspfAreaImpl that = (OspfAreaImpl) o;
+        return Objects.equal(areaId, that.areaId) &&
+                Objects.equal(routerId, that.routerId) &&
+                Objects.equal(addressRanges.size(), that.addressRanges.size()) &&
+                Objects.equal(transitCapability, that.transitCapability) &&
+                Objects.equal(externalRoutingCapability, that.externalRoutingCapability) &&
+                Objects.equal(stubCost, that.stubCost) &&
+                Objects.equal(interfacesLst.size(), that.interfacesLst.size()) &&
+                Objects.equal(database, that.database);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(areaId, routerId, addressRanges, transitCapability, externalRoutingCapability,
+                                stubCost, interfacesLst, database);
+    }
+
+    /**
+     * Gets the router id.
+     *
+     * @return router id
+     */
+    public Ip4Address routerId() {
+        return routerId;
+    }
+
+    /**
+     * Sets the router id.
+     *
+     * @param routerId router id
+     */
+    @JsonProperty("routerId")
+    public void setRouterId(Ip4Address routerId) {
+        this.routerId = routerId;
+    }
+
+    /**
+     * Sets opaque enabled to true or false.
+     *
+     * @param isOpaqueEnable true if opaque enabled else false
+     */
+    @JsonProperty("isOpaqueEnable")
+    public void setIsOpaqueEnabled(boolean isOpaqueEnable) {
+        this.isOpaqueEnable = isOpaqueEnable;
+    }
+
+    /**
+     * Gets is opaque enabled or not.
+     *
+     * @return true if opaque enabled else false
+     */
+    public boolean isOpaqueEnabled() {
+        return this.isOpaqueEnable;
+    }
+
+    /**
+     * Initializes link state database.
+     */
+    public void initializeDb() {
+
+        database.initializeDb();
+    }
+
+    /**
+     * Refreshes the OSPF area information .
+     * Gets called as soon as the interface is down or neighbor full Router LSA is updated.
+     *
+     * @param ospfInterface OSPF interface instance
+     */
+    @Override
+    public void refreshArea(OspfInterface ospfInterface) {
+        OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
+        log.debug("Inside refreshArea...!!!");
+        //If interface state is DR build network LSA.
+        if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
+            if (ospfInterface.listOfNeighbors().size() > 0) {
+                //Get the NetworkLsa
+                NetworkLsa networkLsa = null;
+                try {
+                    networkLsa = buildNetworkLsa(ospfInterface.ipAddress(), ospfInterface.ipNetworkMask());
+                } catch (Exception e) {
+                    log.debug("Error while building NetworkLsa {}", e.getMessage());
+                }
+                //Add the NetworkLsa to lsdb
+                database.addLsa(networkLsa, true, ospfInterface);
+                addToOtherNeighborLsaTxList(networkLsa);
+            } else {
+                log.debug("No Neighbors hence not creating  NetworkLSA...!!!");
+            }
+        }
+        //Get the router LSA
+        RouterLsa routerLsa = null;
+        try {
+            routerLsa = buildRouterLsa(ospfInterface);
+        } catch (Exception e) {
+            log.debug("Error while building RouterLsa {}", e.getMessage());
+        }
+        //Add the RouterLSA to lsdb
+        database.addLsa(routerLsa, true, ospfInterface);
+        addToOtherNeighborLsaTxList(routerLsa);
+    }
+
+    /**
+     * Builds a network LSA.
+     *
+     * @param interfaceIp interface IP address
+     * @param mask        interface network mask
+     * @return NetworkLsa instance
+     * @throws Exception might throws exception
+     */
+    public NetworkLsa buildNetworkLsa(Ip4Address interfaceIp, Ip4Address mask) throws Exception {
+        // generate the Router-LSA for this Area.
+        NetworkLsa networkLsa = new NetworkLsa();
+        networkLsa.setAdvertisingRouter(routerId);
+        networkLsa.setLinkStateId(interfaceIp.toString());
+        networkLsa.setLsType(OspfLsaType.NETWORK.value());
+        networkLsa.setAge(1);
+        networkLsa.setOptions(2);
+        networkLsa.setNetworkMask(mask);
+        //Adding our own router.
+        networkLsa.addAttachedRouter(routerId());
+        Iterator iter = interfacesLst.iterator();
+        OspfInterfaceImpl ospfInterface = null;
+        while (iter.hasNext()) {
+            ospfInterface = (OspfInterfaceImpl) iter.next();
+            if (ospfInterface.ipAddress().equals(interfaceIp)) {
+                break;
+            }
+        }
+        if (ospfInterface != null) {
+            List<OspfNbr> neighborsInFullState = getNeighborsInFullState(ospfInterface);
+            if (neighborsInFullState != null) {
+                for (OspfNbr ospfnbr : neighborsInFullState) {
+                    networkLsa.addAttachedRouter(ospfnbr.neighborId());
+                    log.debug("Adding attached neighbor:: {}", ospfnbr.neighborId());
+                }
+            }
+        }
+        networkLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.NETWORK));
+        //Find the byte length and add it in lsa object
+        ChecksumCalculator checksum = new ChecksumCalculator();
+        byte[] lsaBytes = networkLsa.asBytes();
+        networkLsa.setLsPacketLen(lsaBytes.length);
+        //Convert lsa object to byte again to reflect the packet length which we added.
+        lsaBytes = networkLsa.asBytes();
+        //find the checksum
+        byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
+                                                               OspfUtil.LSAPACKET_CHECKSUM_POS1,
+                                                               OspfUtil.LSAPACKET_CHECKSUM_POS2);
+        int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
+        networkLsa.setLsCheckSum(checkSumVal);
+        return networkLsa;
+    }
+
+    /**
+     * Builds Router LSA.
+     *
+     * @param ospfInterface Interface instance
+     * @return routerLsa Router LSA instance
+     * @throws Exception might throws exception
+     */
+    public RouterLsa buildRouterLsa(OspfInterface ospfInterface) throws Exception {
+        // generate the Router-LSA for this Area.
+        RouterLsa routerLsa = new RouterLsa();
+        routerLsa.setAdvertisingRouter(routerId);
+        routerLsa.setLinkStateId(routerId.toString());
+        routerLsa.setLsType(OspfLsaType.ROUTER.value());
+        routerLsa.setAge(1);
+        routerLsa.setOptions(options);
+        routerLsa.setAreaBorderRouter(false);
+        routerLsa.setAsBoundaryRouter(false);
+        routerLsa.setVirtualEndPoint(false);
+        buildLinkForRouterLsa(routerLsa, ospfInterface);
+        routerLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.ROUTER));
+        //Find the byte length and add it in lsa object
+        ChecksumCalculator checksum = new ChecksumCalculator();
+        byte[] lsaBytes = routerLsa.asBytes();
+        routerLsa.setLsPacketLen(lsaBytes.length);
+        //Convert lsa object to byte again to reflect the packet length whic we added.
+        lsaBytes = routerLsa.asBytes();
+        //find the checksum
+        byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
+                                                               OspfUtil.LSAPACKET_CHECKSUM_POS1,
+                                                               OspfUtil.LSAPACKET_CHECKSUM_POS2);
+        int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
+        routerLsa.setLsCheckSum(checkSumVal);
+        return routerLsa;
+    }
+
+    /**
+     * Builds LSA link for router LSA.
+     *
+     * @param routerLsa     router LSA instance
+     * @param ospfInterface interface instance
+     */
+    private void buildLinkForRouterLsa(RouterLsa routerLsa, OspfInterface ospfInterface) {
+        OspfInterfaceImpl nextInterface;
+        Iterator interfaces = interfacesLst.iterator();
+        while (interfaces.hasNext()) {
+            nextInterface = (OspfInterfaceImpl) interfaces.next();
+            if (nextInterface.state() == OspfInterfaceState.DOWN) {
+                continue;
+            } else if (nextInterface.state() == OspfInterfaceState.LOOPBACK) {
+                OspfLsaLink link = new OspfLsaLink();
+                link.setLinkData("-1");
+                link.setLinkId(nextInterface.ipAddress().toString());
+                link.setLinkType(3);
+                link.setMetric(0);
+                link.setTos(0);
+                routerLsa.addRouterLink(link);
+                routerLsa.incrementLinkNo();
+            } else if (nextInterface.state() == OspfInterfaceState.POINT2POINT) {
+                // adding all neighbour routers
+                List<OspfNbr> neighborsInFullState = getNeighborsInFullState(nextInterface);
+                if (neighborsInFullState != null) {
+                    log.debug("Adding OspfLsaLink ::neighborsInFullState {}, InterfaceIP: {}",
+                              neighborsInFullState.size(), nextInterface.ipAddress());
+                    for (OspfNbr ospfnbr : neighborsInFullState) {
+                        OspfLsaLink link = new OspfLsaLink();
+                        link.setLinkData(nextInterface.ipAddress().toString());
+                        link.setLinkId(ospfnbr.neighborId().toString());
+                        link.setLinkType(1);
+                        link.setMetric(0);
+                        link.setTos(0);
+                        routerLsa.addRouterLink(link);
+                        routerLsa.incrementLinkNo();
+                        log.debug("Added OspfLsaLink :: {}, neighborIP: {}, routerLinks: {}",
+                                  ospfnbr.neighborId(), ospfnbr.neighborIpAddr(), routerLsa.noLink());
+                    }
+                }
+                // adding the self address
+                OspfLsaLink link = new OspfLsaLink();
+                link.setLinkData(nextInterface.ipNetworkMask().toString());
+                link.setLinkId(nextInterface.ipAddress().toString());
+                link.setLinkType(3);
+                link.setMetric(0);
+                link.setTos(0);
+                routerLsa.addRouterLink(link);
+                routerLsa.incrementLinkNo();
+            } else {
+                buildLinkForRouterLsaBroadcast(routerLsa, nextInterface);
+            }
+        }
+    }
+
+    /**
+     * Builds LSA link for router LSA.
+     *
+     * @param routerLsa     router LSA instance
+     * @param ospfInterface interface instance
+     */
+    private void buildLinkForRouterLsaBroadcast(RouterLsa routerLsa, OspfInterface ospfInterface) {
+        OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
+        if (ospfInterfaceImpl.state() == OspfInterfaceState.WAITING) {
+            OspfLsaLink link = new OspfLsaLink();
+            link.setLinkData(ospfInterface.ipNetworkMask().toString());
+            //Link id should be set to ip network number
+            link.setLinkId(ospfInterface.ipAddress().toString());
+            link.setLinkType(3);
+            link.setMetric(0);
+            link.setTos(0);
+            routerLsa.addRouterLink(link);
+            routerLsa.incrementLinkNo();
+        } else if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
+            OspfLsaLink link = new OspfLsaLink();
+            link.setLinkData(ospfInterface.ipAddress().toString());
+            link.setLinkId(ospfInterface.ipAddress().toString());
+            link.setLinkType(2);
+            link.setMetric(0);
+            link.setTos(0);
+            routerLsa.addRouterLink(link);
+            routerLsa.incrementLinkNo();
+        } else if (ospfInterfaceImpl.state() == OspfInterfaceState.BDR ||
+                ospfInterfaceImpl.state() == OspfInterfaceState.DROTHER) {
+            OspfLsaLink link = new OspfLsaLink();
+            link.setLinkData(ospfInterface.ipAddress().toString());
+            link.setLinkId(ospfInterface.dr().toString());
+            link.setLinkType(2);
+            link.setMetric(0);
+            link.setTos(0);
+            routerLsa.addRouterLink(link);
+            routerLsa.incrementLinkNo();
+        }
+    }
+
+    /**
+     * Gets the area id.
+     *
+     * @return area id
+     */
+    public Ip4Address areaId() {
+        return areaId;
+    }
+
+    /**
+     * Sets the area id.
+     *
+     * @param areaId area id
+     */
+    @JsonProperty("areaId")
+    public void setAreaId(Ip4Address areaId) {
+        this.areaId = areaId;
+    }
+
+    /**
+     * Gets address range.
+     *
+     * @return list of area address ranges
+     */
+    public List<OspfAreaAddressRange> addressRanges() {
+        return addressRanges;
+    }
+
+    /**
+     * Sets the area address ranges.
+     *
+     * @param addressRanges list of area address range
+     */
+    @JsonProperty("addressRange")
+    public void setAddressRanges(List<OspfAreaAddressRange> addressRanges) {
+        this.addressRanges = addressRanges;
+    }
+
+    /**
+     * Gets is transit capable or not.
+     *
+     * @return true if transit capable, else false
+     */
+    public boolean isTransitCapability() {
+        return transitCapability;
+    }
+
+    /**
+     * Sets transit capability.
+     *
+     * @param transitCapability true if transit capable, else false
+     */
+    @JsonProperty("transitCapability")
+    public void setTransitCapability(boolean transitCapability) {
+        this.transitCapability = transitCapability;
+    }
+
+    /**
+     * Gets external routing capability.
+     *
+     * @return true if external routing capable, else false
+     */
+    public boolean isExternalRoutingCapability() {
+        return externalRoutingCapability;
+    }
+
+    /**
+     * Sets external routing capability.
+     *
+     * @param externalRoutingCapability true if external routing capable, else false
+     */
+    @JsonProperty("externalRoutingCapability")
+    public void setExternalRoutingCapability(boolean externalRoutingCapability) {
+        this.externalRoutingCapability = externalRoutingCapability;
+    }
+
+    /**
+     * Gets the stub cost.
+     *
+     * @return stub cost
+     */
+    public int stubCost() {
+        return stubCost;
+    }
+
+    /**
+     * Sets the stub cost.
+     *
+     * @param stubCost stub cost
+     */
+    @JsonProperty("stubCost")
+    public void setStubCost(int stubCost) {
+        this.stubCost = stubCost;
+    }
+
+    /**
+     * Gets the list of interfaces in this area.
+     *
+     * @return list of interfaces
+     */
+    public List<OspfInterface> getInterfacesLst() {
+        return interfacesLst;
+    }
+
+    /**
+     * Sets the list of interfaces attached to the area.
+     *
+     * @param interfacesLst list of OspfInterface instances
+     */
+    @JsonProperty("interface")
+    public void setInterfacesLst(List<OspfInterface> interfacesLst) {
+        this.interfacesLst = interfacesLst;
+    }
+
+    /**
+     * Checks all neighbors belonging to this area whether they are in state EXCHANGE or LOADING.
+     * Return false if there is at least one, else return true. This Method is used by
+     * "processReceivedLsa()" in the neighbor class.
+     *
+     * @return boolean indicating that there is no Neighbor in Database Exchange
+     */
+    public boolean noNeighborInLsaExchangeProcess() {
+        OspfInterfaceImpl nextInterface;
+        OspfNeighborState nextNeighborState;
+        Iterator interfaces = interfacesLst.iterator();
+        while (interfaces.hasNext()) {
+            nextInterface = (OspfInterfaceImpl) interfaces.next();
+            Iterator neighbors = nextInterface.listOfNeighbors().values().iterator();
+            while (neighbors.hasNext()) {
+                nextNeighborState = ((OspfNbrImpl) neighbors.next()).getState();
+                if (nextNeighborState == OspfNeighborState.EXCHANGE ||
+                        nextNeighborState == OspfNeighborState.LOADING) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Gets header of all types of LSAs.
+     *
+     * @param excludeMaxAgeLsa need to include(true) or exclude(false) maxage lsa's
+     * @param isOpaquecapable  need to include(true) or exclude(false) Type 10 Opaque lsa's
+     * @return list of lsa header in the lsdb
+     */
+    public List getLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaquecapable) {
+        return database.getAllLsaHeaders(excludeMaxAgeLsa, isOpaquecapable);
+    }
+
+    /**
+     * Gets the LSA from LSDB based on the input.
+     *
+     * @param lsType            type of lsa to form the key
+     * @param linkStateID       link state id to form the key
+     * @param advertisingRouter advertising router to form the key
+     * @return lsa wrapper instance which contains the Lsa
+     * @throws Exception might throws exception
+     */
+    public LsaWrapper getLsa(int lsType, String linkStateID, String advertisingRouter) throws Exception {
+        String lsaKey = lsType + "-" + linkStateID + "-" + advertisingRouter;
+        if (lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA || lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
+                lsType == OspfParameters.AS_OPAQUE_LSA) {
+            byte[] linkStateAsBytes = InetAddress.getByName(linkStateID).getAddress();
+            int opaqueType = linkStateAsBytes[0];
+            int opaqueId = OspfUtil.byteToInteger(Arrays.copyOfRange(linkStateAsBytes, 1,
+                                                                     linkStateAsBytes.length));
+            lsaKey = lsType + "-" + opaqueType + opaqueId + "-" + advertisingRouter;
+        }
+        return database.findLsa(lsType, lsaKey);
+    }
+
+
+    /**
+     * Checks whether an instance of the given LSA exists in the database belonging to this area.
+     * If so return true else false.
+     *
+     * @param lookupLsa ospf LSA instance to lookup
+     * @return LSA wrapper instance which contains the Lsa
+     */
+    public LsaWrapper lsaLookup(OspfLsa lookupLsa) {
+        return database.lsaLookup((LsaHeader) lookupLsa);
+    }
+
+    /**
+     * Checks whether an instance of the given LSA exists in the database belonging to this area.
+     * If so return true else false.
+     *
+     * @param lsa1 OSPF LSA instance to compare
+     * @param lsa2 OSPF LSA instance to compare
+     * @return "same" if both instances are same, "latest" if lsa1 is latest, or "old" if lsa1 is old
+     */
+    public String isNewerOrSameLsa(OspfLsa lsa1, OspfLsa lsa2) {
+        return database.isNewerOrSameLsa((LsaHeader) lsa1, (LsaHeader) lsa2);
+    }
+
+    /**
+     * Methods gets called from ChannelHandler to add the received LSA to LSDB.
+     *
+     * @param ospfLsa       OSPF LSA instance
+     * @param ospfInterface OSPF interface instance
+     */
+    public void addLsa(OspfLsa ospfLsa, OspfInterface ospfInterface) throws Exception {
+        //second param is false as lsa from network
+        database.addLsa((LsaHeader) ospfLsa, false, ospfInterface);
+    }
+
+    /**
+     * Methods gets called from ChannelHandler to add the received LSA to LSDB.
+     *
+     * @param ospfLsa          OSPF LSA instance
+     * @param isSelfOriginated true if the LSA is self originated. Else false
+     * @param ospfInterface    OSPF interface instance
+     */
+    public void addLsa(OspfLsa ospfLsa, boolean isSelfOriginated, OspfInterface ospfInterface)
+            throws Exception {
+        database.addLsa((LsaHeader) ospfLsa, isSelfOriginated, ospfInterface);
+    }
+
+    /**
+     * Adds the LSA to maxAge bin.
+     *
+     * @param key     key to add it to LSDB
+     * @param wrapper LSA wrapper instance
+     */
+    public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
+        database.addLsaToMaxAgeBin(key, wrapper);
+    }
+
+    /**
+     * Sets router sequence number for router LSA.
+     *
+     * @param newSequenceNumber sequence number
+     */
+    public void setDbRouterSequenceNumber(long newSequenceNumber) {
+        database.setRouterLsaSeqNo(newSequenceNumber);
+    }
+
+    /**
+     * Methods gets called from ChannelHandler to delete the LSA.
+     *
+     * @param ospfLsa the LSA instance to delete
+     */
+    public void deleteLsa(LsaHeader ospfLsa) {
+        database.deleteLsa(ospfLsa);
+    }
+
+    /**
+     * Removes LSA from bin.
+     *
+     * @param lsaWrapper the LSA wrapper instance to delete
+     */
+    public void removeLsaFromBin(LsaWrapper lsaWrapper) {
+        database.removeLsaFromBin(lsaWrapper);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .omitNullValues()
+                .add("areaID", areaId)
+                .add("stubCost", stubCost)
+                .add("addressRanges", addressRanges)
+                .add("interfacesLst", interfacesLst)
+                .add("transitCapability", transitCapability)
+                .add("externalRoutingCapability", externalRoutingCapability)
+                .toString();
+    }
+
+    /**
+     * Checks all Neighbors belonging to this Area whether they are in state lesser than the EXCHANGE.
+     * <p>
+     * Creates list of such neighbors
+     * <p>
+     * Returns list of neighbors who satisfy the conditions
+     *
+     * @param ospfInterface OSPF interface instance
+     * @return List of interfaces having state lesser than exchange
+     */
+    public List<OspfNbr> getNeighborsInFullState(OspfInterface ospfInterface) {
+
+        List<OspfNbr> listEligibleNeighbors = null;
+        OspfNbrImpl ospfNeighbor = null;
+        OspfNeighborState nextNeighborState;
+        Iterator nbrInterface = ospfInterface.listOfNeighbors().values().iterator();
+        while (nbrInterface.hasNext()) {
+            ospfNeighbor = (OspfNbrImpl) nbrInterface.next();
+            nextNeighborState = ospfNeighbor.getState();
+            if (nextNeighborState.getValue() == OspfNeighborState.FULL.getValue()) {
+                if (listEligibleNeighbors == null) {
+                    listEligibleNeighbors = new ArrayList<OspfNbr>();
+                    listEligibleNeighbors.add(ospfNeighbor);
+                } else {
+                    listEligibleNeighbors.add(ospfNeighbor);
+                }
+            }
+        }
+        return listEligibleNeighbors;
+    }
+
+    /**
+     * Gets the LSDB LSA key from LSA header.
+     *
+     * @param lsaHeader LSA header instance
+     * @return key LSA key
+     */
+    public String getLsaKey(LsaHeader lsaHeader) {
+        return database.getLsaKey(lsaHeader);
+    }
+
+    /**
+     * Adds the received LSA in other neighbors tx list.
+     *
+     * @param recLsa LSA Header instance
+     */
+    public void addToOtherNeighborLsaTxList(LsaHeader recLsa) {
+        //Add the received LSA in other neighbors retransmission list.
+        log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList");
+        List<OspfInterface> ospfInterfaces = getInterfacesLst();
+        for (OspfInterface ospfInterfaceFromArea : ospfInterfaces) {
+            Map neighbors = ospfInterfaceFromArea.listOfNeighbors();
+            for (Object neighborIP : neighbors.keySet()) {
+                OspfNbrImpl nbr = (OspfNbrImpl) neighbors.get(neighborIP);
+                if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
+                    continue;
+                }
+                String key = database.getLsaKey(recLsa);
+                if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING) {
+                    if (nbr.getLsReqList().containsKey(key)) {
+                        LsaWrapper lsWrapper = lsaLookup(recLsa);
+                        if (lsWrapper != null) {
+                            LsaHeader ownLSA = (LsaHeader) lsWrapper.ospfLsa();
+                            String status = isNewerOrSameLsa(recLsa, ownLSA);
+                            if (status.equals("old")) {
+                                continue;
+                            } else if (status.equals("same")) {
+                                log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
+                                                  "Removing lsa from reTxtList {}", key);
+                                nbr.getLsReqList().remove(key);
+                                continue;
+                            } else {
+                                log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
+                                                  "Removing lsa from reTxtList {}", key);
+                                nbr.getLsReqList().remove(key);
+                            }
+                        }
+                    }
+                }
+                if (recLsa.advertisingRouter().equals((String) neighborIP)) {
+                    continue;
+                }
+                if ((recLsa.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
+                        recLsa.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA)) {
+                    if (nbr.isOpaqueCapable()) {
+                        log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
+                                  recLsa);
+                        nbr.getReTxList().put(key, recLsa);
+                    }
+                } else {
+                    log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
+                              recLsa);
+                    nbr.getReTxList().put(key, recLsa);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the options value.
+     *
+     * @return options value
+     */
+    public int options() {
+        return options;
+    }
+
+    /**
+     * Sets the options value.
+     *
+     * @param options options value
+     */
+    public void setOptions(int options) {
+        this.options = options;
+    }
+
+    /**
+     * Gets the opaque enabled options value.
+     *
+     * @return opaque enabled options value
+     */
+    public int opaqueEnabledOptions() {
+        return Integer.parseInt(OspfParameters.OPAQUE_ENABLED_OPTION_VALUE, 2);
+    }
+
+    /**
+     * Gets the lsdb instance for this area.
+     *
+     * @return lsdb instance
+     */
+    public OspfLsdb database() {
+        return database;
+    }
+}
\ No newline at end of file
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java
new file mode 100755
index 0000000..0d284bf
--- /dev/null
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java
@@ -0,0 +1,1871 @@
+/*
+* Copyright 2016 Open Networking Laboratory
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.onosproject.ospf.controller.impl;
+
+import org.jboss.netty.channel.Channel;
+import org.onlab.packet.Ip4Address;
+import org.onlab.util.Bandwidth;
+import org.onosproject.ospf.controller.DeviceInformation;
+import org.onosproject.ospf.controller.LinkInformation;
+import org.onosproject.ospf.controller.LsaWrapper;
+import org.onosproject.ospf.controller.OspfArea;
+import org.onosproject.ospf.controller.OspfDeviceTed;
+import org.onosproject.ospf.controller.OspfInterface;
+import org.onosproject.ospf.controller.OspfLinkTed;
+import org.onosproject.ospf.controller.OspfLsa;
+import org.onosproject.ospf.controller.OspfLsaType;
+import org.onosproject.ospf.controller.OspfLsdb;
+import org.onosproject.ospf.controller.OspfNbr;
+import org.onosproject.ospf.controller.OspfNeighborState;
+import org.onosproject.ospf.controller.OspfRouter;
+import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
+import org.onosproject.ospf.controller.area.OspfAreaImpl;
+import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
+import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
+import org.onosproject.ospf.controller.util.OspfInterfaceType;
+import org.onosproject.ospf.protocol.lsa.LsaHeader;
+import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
+import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10;
+import org.onosproject.ospf.protocol.lsa.types.TopLevelTlv;
+import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
+import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
+import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
+import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
+import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
+import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
+import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
+import org.onosproject.ospf.protocol.util.ChecksumCalculator;
+import org.onosproject.ospf.protocol.util.OspfInterfaceState;
+import org.onosproject.ospf.protocol.util.OspfPacketType;
+import org.onosproject.ospf.protocol.util.OspfParameters;
+import org.onosproject.ospf.protocol.util.OspfUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Represents an OSPF neighbor.
+ * The first thing an OSPF router must do is find its neighbors and form adjacency.
+ * Each neighbor that the router finds will be represented by this class.
+ */
+public class OspfNbrImpl implements OspfNbr {
+    private static final Logger log = LoggerFactory.getLogger(OspfNbrImpl.class);
+    private OspfNeighborState state;
+    private InternalRxmtDdPacket rxmtDdPacketTask;
+    private InternalInactivityTimeCheck inActivityTimeCheckTask;
+    private InternalFloodingTask floodingTask;
+    private InternalRxmtLsrPacket rxmtLsrPacketTask;
+    private ScheduledExecutorService exServiceRxmtLsr;
+    private ScheduledExecutorService exServiceFlooding;
+    private ScheduledExecutorService exServiceRxmtDDPacket;
+    private ScheduledExecutorService exServiceInActivity;
+
+    private boolean floodingTimerScheduled = false;
+    private boolean rxmtLsrTimerScheduled = false;
+    private boolean rxmtDdPacketTimerScheduled = false;
+    private boolean inActivityTimerScheduled = false;
+
+    /**
+     * When the two neighbors are exchanging databases, they form a master/slave relationship.
+     * The master sends the first Database Description Packet
+     */
+    private int isMaster;
+
+    /**
+     * The DD Sequence Number of the DD packet that is currently being sent to the neighbor.
+     */
+    private long ddSeqNum;
+
+    /**
+     * Another data structure for keeping information of the last received DD packet.
+     */
+    private DdPacket lastDdPacket;
+
+    /**
+     * Another data structure for keeping information of the last Sent DD packet.
+     */
+    private DdPacket lastSentDdPacket;
+
+    /**
+     * Another data structure for keeping information of the last Sent LSrequest packet.
+     */
+    private LsRequest lastSentLsrPacket;
+
+    /**
+     * The router ID of the Neighbor Router.
+     */
+    private Ip4Address neighborId;
+
+    /**
+     * The IP address of the neighboring router's interface to the attached network.
+     */
+    private Ip4Address neighborIpAddr;
+
+    /**
+     * The neighbor's IDEA of the designated router.
+     */
+    private Ip4Address neighborDr;
+
+    /**
+     * The neighbor's IDEA of the backup designated router.
+     */
+    private Ip4Address neighborBdr;
+
+    private int routerPriority;
+    private int routerDeadInterval;
+
+    /**
+     * The list of LSAs that have to be flooded.
+     */
+    private Map<String, OspfLsa> reTxList = new LinkedHashMap();
+
+    /**
+     * The list of LSAs that have been flooded but not yet acknowledged on this adjacency.
+     */
+    private Map<String, OspfLsa> pendingReTxList = new LinkedHashMap();
+
+    /**
+     * List of LSAs which are failed to received ACK.
+     */
+    private Map failedTxList = new HashMap();
+
+    /**
+     * The complete list of LSAs that make up the area link-state database, at the moment the.
+     * neighbor goes into Database Exchange state (EXCHANGE).
+     */
+    private List<LsaHeader> ddSummaryList = new CopyOnWriteArrayList();
+
+    /**
+     * LSA Request List from Neighbor.
+     */
+    private Hashtable lsReqList = new Hashtable();
+
+    /**
+     * The optional OSPF capabilities supported by the neighbor.
+     */
+    private int options;
+    private boolean isOpaqueCapable;
+
+    /**
+     * A link to the OSPF-Interface this Neighbor belongs to.
+     */
+    private OspfInterface ospfInterface;
+
+    /**
+     * A link to the OSPF-Area this Neighbor Data Structure belongs to.
+     */
+    private OspfArea ospfArea;
+    private OspfInterfaceChannelHandler handler;
+    private List<TopLevelTlv> topLevelTlvs = new ArrayList<>();
+    private List<DeviceInformation> deviceInformationList = new ArrayList<>();
+
+    private TopologyForDeviceAndLink topologyForDeviceAndLink;
+
+    /**
+     * Creates an instance of Neighbor.
+     *
+     * @param paramOspfArea                  OSPF Area instance
+     * @param paramOspfInterface             OSPF interface instance
+     * @param ipAddr                         IP address
+     * @param routerId                       router id
+     * @param options                        options
+     * @param handler                        channel handler instance
+     * @param topologyForDeviceAndLinkCommon topology for device and link instance
+     */
+    public OspfNbrImpl(OspfArea paramOspfArea, OspfInterface paramOspfInterface,
+                       Ip4Address ipAddr, Ip4Address routerId, int options,
+                       OspfInterfaceChannelHandler handler, TopologyForDeviceAndLink topologyForDeviceAndLinkCommon) {
+        this.ospfArea = paramOspfArea;
+        this.ospfInterface = paramOspfInterface;
+        state = OspfNeighborState.DOWN;
+        isMaster = OspfUtil.NOT_MASTER;
+        ddSeqNum = OspfUtil.createRandomNumber();
+        neighborIpAddr = ipAddr;
+        neighborId = routerId;
+        this.options = options;
+        lastDdPacket = new DdPacket();
+        routerDeadInterval = paramOspfInterface.routerDeadIntervalTime();
+        this.handler = handler;
+        this.topologyForDeviceAndLink = topologyForDeviceAndLinkCommon;
+    }
+
+    /**
+     * Gets the IP address of this neighbor.
+     *
+     * @return the IP address of this neighbor
+     */
+    public Ip4Address neighborIpAddr() {
+        return neighborIpAddr;
+    }
+
+    /**
+     * Gets the neighbor is opaque enabled or not.
+     *
+     * @return true if the neighbor is opaque enabled else false.
+     */
+    public boolean isOpaqueCapable() {
+        return isOpaqueCapable;
+    }
+
+    /**
+     * Sets the neighbor is opaque enabled or not.
+     *
+     * @param isOpaqueCapable true if the neighbor is opaque enabledelse false
+     */
+    public void setIsOpaqueCapable(boolean isOpaqueCapable) {
+        this.isOpaqueCapable = isOpaqueCapable;
+    }
+
+    /**
+     * Have seen a Neighbor, but the Neighbor doesn't know about me.
+     *
+     * @param ospfHello Hello Packet instance
+     * @param channel   netty channel instance
+     */
+    public void oneWayReceived(OspfMessage ospfHello, Channel channel) {
+        log.debug("OSPFNbr::oneWayReceived...!!!");
+        stopInactivityTimeCheck();
+        startInactivityTimeCheck();
+
+        if (state == OspfNeighborState.ATTEMPT) {
+            state = OspfNeighborState.INIT;
+        } else if (state == OspfNeighborState.DOWN) {
+            state = OspfNeighborState.INIT;
+        }
+
+        if (state.getValue() >= OspfNeighborState.TWOWAY.getValue()) {
+            state = OspfNeighborState.INIT;
+            failedTxList.clear();
+            ddSummaryList.clear();
+            lsReqList.clear();
+        }
+    }
+
+    /**
+     * Called when a DD OSPFMessage is received while state was INIT.
+     *
+     * @param ospfMessage ospf message instance
+     * @param channel     netty channel instance
+     * @throws Exception might throws exception
+     */
+    public void twoWayReceived(OspfMessage ospfMessage, Channel channel) throws Exception {
+        log.debug("OSPFNbr::twoWayReceived...!!!");
+        stopInactivityTimeCheck();
+        startInactivityTimeCheck();
+        startFloodingTimer(channel);
+
+        OspfPacketHeader packet = (OspfPacketHeader) ospfMessage;
+        if (state.getValue() <= OspfNeighborState.TWOWAY.getValue()) {
+            if (formAdjacencyOrNot()) {
+                state = OspfNeighborState.EXSTART;
+
+                ddSeqNum++;
+                DdPacket ddPacket = new DdPacket();
+                // seting OSPF Header
+                ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+                ddPacket.setOspftype(OspfPacketType.DD.value());
+                ddPacket.setRouterId(ospfArea.routerId());
+                ddPacket.setAreaId(ospfArea.areaId());
+                ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+                ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+                boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+                if (isOpaqueEnabled) {
+                    ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+                } else {
+                    ddPacket.setOptions(ospfArea.options());
+                }
+                ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
+                ddPacket.setIsMore(OspfUtil.MORE_SET);
+                ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+                ddPacket.setImtu(ospfInterface.mtu());
+                ddPacket.setSequenceNo(ddSeqNum);
+
+                setLastSentDdPacket(ddPacket);
+                rxmtDdPacketTask = new InternalRxmtDdPacket(channel);
+                startRxMtDdTimer(channel);
+                //setting destination ip
+                ddPacket.setDestinationIp(packet.sourceIp());
+                channel.write(ddPacket);
+            } else {
+                state = OspfNeighborState.TWOWAY;
+            }
+        }
+    }
+
+    /**
+     * Checks whether to form adjacency or not.
+     *
+     * @return true indicates form adjacency, else false
+     */
+    private boolean formAdjacencyOrNot() {
+        boolean formAdjacency = false;
+
+        if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
+            formAdjacency = true;
+        } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
+            if (ospfInterface.ipAddress().equals(this.neighborDr) ||
+                    ospfInterface.ipAddress().equals(this.neighborBdr)) {
+                formAdjacency = true;
+            } else if (neighborBdr.equals(neighborIpAddr) ||
+                    neighborDr.equals(neighborIpAddr)) {
+                formAdjacency = true;
+            }
+        }
+
+        log.debug("FormAdjacencyOrNot - neighborDR: {}, neighborBDR: {}, neighborIPAddr: {}, formAdjacencyOrNot {}",
+                  neighborDr, neighborBdr, neighborIpAddr, formAdjacency);
+
+        return formAdjacency;
+    }
+
+    /**
+     * At this point Master/Slave relationship is definitely established.
+     * DD sequence numbers have been exchanged.
+     * This is the begin of sending/receiving of DD OSPFMessages.
+     *
+     * @param ospfMessage      OSPF message instance
+     * @param neighborIsMaster neighbor is master or slave
+     * @param payload          contains the LSAs to add in Dd Packet
+     * @param ch               netty channel instance
+     * @throws Exception might throws exception
+     */
+    public void negotiationDone(OspfMessage ospfMessage,
+                                boolean neighborIsMaster, List payload, Channel ch) throws Exception {
+        stopRxMtDdTimer();
+        OspfPacketHeader packet = (OspfPacketHeader) ospfMessage;
+        DdPacket ddPacketForCheck = (DdPacket) packet;
+        if (ddPacketForCheck.isOpaqueCapable()) {
+            OspfLsdb database = ospfArea.database();
+            List opaqueLsas = database.getAllLsaHeaders(true, true);
+            Iterator iterator = opaqueLsas.iterator();
+            while (iterator.hasNext()) {
+                OspfLsa ospfLsa = (OspfLsa) iterator.next();
+                if (ospfLsa.getOspfLsaType() == OspfLsaType.AREA_LOCAL_OPAQUE_LSA) {
+                    OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa;
+                    topLevelTlvs = opaqueLsa10.topLevelValues();
+                }
+            }
+        }
+        if (state == OspfNeighborState.EXSTART) {
+            state = OspfNeighborState.EXCHANGE;
+            boolean excludeMaxAgeLsa = true;
+            //list of contents of area wise LSA
+            ddSummaryList = (CopyOnWriteArrayList) ospfArea.getLsaHeaders(excludeMaxAgeLsa, isOpaqueCapable);
+
+            if (neighborIsMaster) {
+                processLsas(payload);
+                // ...construct new DD Packet...
+                DdPacket ddPacket = new DdPacket();
+                // setting OSPF Header
+                ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+                ddPacket.setOspftype(OspfPacketType.DD.value());
+                ddPacket.setRouterId(ospfArea.routerId());
+                ddPacket.setAreaId(ospfArea.areaId());
+                ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+                ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+                boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+                if (isOpaqueEnabled && isOpaqueCapable) {
+                    ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+                } else {
+                    ddPacket.setOptions(ospfArea.options());
+                }
+                ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
+                ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
+                ddPacket.setIsMaster(OspfUtil.NOT_MASTER);
+                ddPacket.setImtu(ospfInterface.mtu());
+                ddPacket.setSequenceNo(ddSeqNum);
+                //setting the destination
+                ddPacket.setDestinationIp(packet.sourceIp());
+                setLastSentDdPacket(ddPacket);
+                getIsMoreBit();
+
+                ch.write(lastSentDdPacket());
+            } else {
+                // process LSA Vector's List, Add it to LSRequestList.
+                processLsas(payload);
+                DdPacket ddPacket = new DdPacket();
+                // setting OSPF Header
+                ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+                ddPacket.setOspftype(OspfPacketType.DD.value());
+                ddPacket.setRouterId(ospfArea.routerId());
+                ddPacket.setAreaId(ospfArea.areaId());
+                ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+                ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+                boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+                if (isOpaqueEnabled && isOpaqueCapable) {
+                    ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+                } else {
+                    ddPacket.setOptions(ospfArea.options());
+                }
+                ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
+                ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
+                ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+                ddPacket.setImtu(ospfInterface.mtu());
+                ddPacket.setSequenceNo(ddSeqNum);
+                setLastSentDdPacket(ddPacket);
+                getIsMoreBit();
+                ddPacket.setDestinationIp(packet.sourceIp());
+                ch.write(lastSentDdPacket());
+                startRxMtDdTimer(ch);
+            }
+        }
+    }
+
+    /**
+     * Process the LSA Headers received in the last received Database Description OSPFMessage.
+     *
+     * @param ddPayload LSA headers to process
+     * @throws Exception might throws exception
+     */
+    public void processLsas(List ddPayload) throws Exception {
+        log.debug("OSPFNbr::processLsas...!!!");
+        OspfLsa nextLsa;
+        Iterator lsas = ddPayload.iterator();
+        while (lsas.hasNext()) {
+            nextLsa = (OspfLsa) lsas.next();
+            // check LSA Type.
+            if (((nextLsa.getOspfLsaType().value() > OspfLsaType.EXTERNAL_LSA.value()) &&
+                    (nextLsa.getOspfLsaType().value() < OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
+                    (nextLsa.getOspfLsaType().value() > OspfLsaType.AS_OPAQUE_LSA.value())) {
+                // unknown lsType found!
+                seqNumMismatch("LS Type found was unknown.");
+                return;
+            }
+
+            if ((nextLsa.getOspfLsaType() == OspfLsaType.EXTERNAL_LSA) &&
+                    !ospfArea.isExternalRoutingCapability()) {
+                // LSA is external and the Area has no external lsa capability
+                seqNumMismatch("External LSA found although area is stub.");
+                return;
+            }
+
+            LsaWrapper lsaHasInstance = ospfArea.lsaLookup(nextLsa);
+            if (lsaHasInstance == null) {
+                lsReqList.put(((OspfAreaImpl) ospfArea).getLsaKey((LsaHeader) nextLsa), nextLsa);
+            } else {
+                String isNew = ((OspfAreaImpl) ospfArea).isNewerOrSameLsa(nextLsa,
+                                                                          lsaHasInstance.ospfLsa());
+                if (isNew.equals("latest")) {
+                    lsReqList.put(((OspfAreaImpl) ospfArea).getLsaKey((LsaHeader) nextLsa), nextLsa);
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles sequence number mis match event.
+     *
+     * @param reason a string represents the mismatch reason
+     * @return OSPF message instance
+     * @throws Exception might throws exception
+     */
+    public OspfMessage seqNumMismatch(String reason) throws Exception {
+        log.debug("OSPFNbr::seqNumMismatch...{} ", reason);
+        stopRxMtDdTimer();
+
+        if (state.getValue() >= OspfNeighborState.EXCHANGE.getValue()) {
+           /* if (state == OspfNeighborState.FULL) {
+                ospfArea.refreshArea(ospfInterface);
+            }*/
+
+            state = OspfNeighborState.EXSTART;
+            lsReqList.clear();
+            ddSummaryList.clear();
+            //increment the dd sequence number
+            ddSeqNum++;
+
+            DdPacket ddPacket = new DdPacket();
+            // seting OSPF Header
+            ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+            ddPacket.setOspftype(OspfPacketType.DD.value());
+            ddPacket.setRouterId(ospfArea.routerId());
+            ddPacket.setAreaId(ospfArea.areaId());
+            ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+            ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+            boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+            if (isOpaqueEnabled) {
+                ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+            } else {
+                ddPacket.setOptions(ospfArea.options());
+            }
+            ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
+            ddPacket.setIsMore(OspfUtil.MORE_SET);
+            ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+            ddPacket.setImtu(ospfInterface.mtu());
+            ddPacket.setSequenceNo(ddSeqNum);
+
+            setLastSentDdPacket(ddPacket);
+            //setting destination ip
+            ddPacket.setDestinationIp(neighborIpAddr());
+            setLastSentDdPacket(ddPacket);
+
+            return ddPacket;
+        }
+
+        return null;
+    }
+
+    /**
+     * Called if a LS Request has been received for an LSA which is not contained in the database.
+     * This indicates an error in the Database Exchange process.
+     * Actions to be performed are the same as in seqNumMismatch.
+     * In addition, stop the possibly activated re transmission timer.
+     *
+     * @param ch netty channel instance
+     */
+    public void badLSReq(Channel ch) throws Exception {
+        log.debug("OSPFNbr::badLSReq...!!!");
+
+        if (state.getValue() >= OspfNeighborState.EXCHANGE.getValue()) {
+            if (state == OspfNeighborState.FULL) {
+                ospfArea.refreshArea(ospfInterface);
+            }
+
+            stopRxMtDdTimer();
+            state = OspfNeighborState.EXSTART;
+
+            lsReqList.clear();
+            ddSummaryList.clear();
+            reTxList.clear();
+            //increment the dd sequence number
+            isMaster = OspfUtil.IS_MASTER;
+            ddSeqNum++;
+            DdPacket ddPacket = new DdPacket();
+            // seting OSPF Header
+            ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+            ddPacket.setOspftype(OspfPacketType.DD.value());
+            ddPacket.setRouterId(ospfArea.routerId());
+            ddPacket.setAreaId(ospfArea.areaId());
+            ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+            ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+
+            // setting DD Body
+            boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+            if (isOpaqueEnabled && this.isOpaqueCapable) {
+                ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+            } else {
+                ddPacket.setOptions(ospfArea.options());
+            }
+            ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
+            ddPacket.setIsMore(OspfUtil.MORE_SET);
+            ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+            ddPacket.setImtu(ospfInterface.mtu());
+            ddPacket.setSequenceNo(ddSeqNum);
+
+            rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
+            startRxMtDdTimer(ch);
+
+            //setting destination ip
+            ddPacket.setDestinationIp(neighborIpAddr());
+            setLastSentDdPacket(ddPacket);
+            ch.write(ddPacket);
+        }
+    }
+
+    /**
+     * Called if state is EXCHANGE. This method is executed every time a DD Packets arrives.
+     * When the last Packet arrives, it transfers the state into LOADING or FULL
+     *
+     * @param neighborIsMaster true if neighbor is master else false
+     * @param dataDescPkt      DdPacket instance
+     * @param ch               netty channel instance
+     * @throws Exception might throws exception
+     */
+    public void processDdPacket(boolean neighborIsMaster, DdPacket dataDescPkt,
+                                Channel ch) throws Exception {
+        log.debug("OSPFNbr::neighborIsMaster.{}", neighborIsMaster);
+
+        if (!neighborIsMaster) {
+            stopRxMtDdTimer();
+            ddSeqNum++;
+            processLsas(dataDescPkt.getLsaHeaderList());
+            if ((ddSummaryList.isEmpty()) &&
+                    (dataDescPkt.isMore() == OspfUtil.MORE_NOTSET)) {
+                log.debug(
+                        "OSPFNbr::ddSummaryList is empty and dataDescPkt.isMore is zero..!!!");
+                // generate the neighbor event ExchangeDone.
+                exchangeDone(dataDescPkt, ch);
+            } else {
+                log.debug("OSPFNbr::ddSummaryList is present...!!!");
+                // send a new Database Description Packet to the slave.
+                DdPacket ddPacket = new DdPacket();
+                // seting OSPF Header
+                ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+                ddPacket.setOspftype(OspfPacketType.DD.value());
+                ddPacket.setRouterId(ospfArea.routerId());
+                ddPacket.setAreaId(ospfArea.areaId());
+                ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+                ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+                // setting DD Body
+                boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+                if (isOpaqueEnabled && isOpaqueCapable) {
+                    ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+                } else {
+                    ddPacket.setOptions(ospfArea.options());
+                }
+                ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
+                ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
+                ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+                ddPacket.setImtu(ospfInterface.mtu());
+                ddPacket.setSequenceNo(ddSeqNum);
+
+                setLastSentDdPacket(ddPacket);
+                getIsMoreBit();
+                //Set the destination IP Address
+                ddPacket.setDestinationIp(dataDescPkt.sourceIp());
+                ch.write(lastSentDdPacket());
+
+                startRxMtDdTimer(ch);
+            }
+        } else {
+            log.debug("OSPFNbr::neighborIsMaster is master...!!!");
+            ddSeqNum = dataDescPkt.sequenceNo();
+            processLsas(dataDescPkt.getLsaHeaderList());
+
+            DdPacket ddPacket = new DdPacket();
+            // seting OSPF Header
+            ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+            ddPacket.setOspftype(OspfPacketType.DD.value());
+            ddPacket.setRouterId(ospfArea.routerId());
+            ddPacket.setAreaId(ospfArea.areaId());
+            ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+            ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+            ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+            // setting DD Body
+            boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+            if (isOpaqueEnabled && this.isOpaqueCapable) {
+                ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+            } else {
+                ddPacket.setOptions(ospfArea.options());
+            }
+            ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
+            ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
+            ddPacket.setIsMaster(OspfUtil.NOT_MASTER);
+            ddPacket.setImtu(ospfInterface.mtu());
+            ddPacket.setSequenceNo(ddSeqNum);
+            setLastSentDdPacket(ddPacket);
+            getIsMoreBit();
+
+            if ((ddPacket.isMore() == OspfUtil.MORE_NOTSET) &&
+                    (dataDescPkt.isMore() == OspfUtil.MORE_NOTSET)) {
+                // generate the neighbor event ExchangeDone.
+                exchangeDone(dataDescPkt, ch);
+            }
+
+            ddPacket.setDestinationIp(dataDescPkt.sourceIp());
+            ch.write(ddPacket);
+        }
+    }
+
+    /**
+     * Sets the more bit in stored, last sent DdPacket.
+     */
+    private void getIsMoreBit() {
+        DdPacket ddPacket = lastSentDdPacket();
+        int count = ddSummaryList.size();
+
+        if (!ddSummaryList.isEmpty()) {
+            Iterator itr = ddSummaryList.iterator();
+            int currentLength = OspfUtil.DD_HEADER_LENGTH;
+            int maxSize = ospfInterface.mtu() - OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
+            while (itr.hasNext()) {
+                if ((currentLength + OspfUtil.LSA_HEADER_LENGTH) > maxSize) {
+                    break;
+                }
+
+                LsaHeader lsaHeader = (LsaHeader) itr.next();
+                ddPacket.addLsaHeader(lsaHeader);
+                currentLength = currentLength + OspfUtil.LSA_HEADER_LENGTH;
+                ddSummaryList.remove(lsaHeader);
+                count--;
+            }
+
+            if (count > 0) {
+                ddPacket.setIsMore(OspfUtil.MORE_SET);
+            } else {
+                ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
+            }
+        }
+
+        setLastSentDdPacket(ddPacket);
+    }
+
+    /**
+     * At this point, the router has sent and received an entire sequence of DD packets.
+     * Now it must be determined whether the new state is FULL, or LS Request packets
+     * have to be send.
+     *
+     * @param message OSPF message instance
+     * @param ch      netty channel handler
+     */
+    public void exchangeDone(OspfMessage message, Channel ch) {
+        log.debug("OSPFNbr::exchangeDone...!!!");
+        stopRxMtDdTimer();
+
+        OspfPacketHeader header = (OspfPacketHeader) message;
+
+        if (state == OspfNeighborState.EXCHANGE) {
+            if (lsReqList.isEmpty()) {
+                state = OspfNeighborState.FULL;
+                //handler.addDeviceInformation(this);
+                //handler.addLinkInformation(this, topLevelTlvs);
+            } else {
+                state = OspfNeighborState.LOADING;
+                LsRequest lsRequest = buildLsRequest();
+                //Setting the destination address
+                lsRequest.setDestinationIp(header.sourceIp());
+                ch.write(lsRequest);
+
+                setLastSentLsrPacket(lsRequest);
+                startRxMtLsrTimer(ch);
+            }
+        }
+    }
+
+    /**
+     * Builds LS Request.
+     *
+     * @return ls request instance
+     */
+    private LsRequest buildLsRequest() {
+        //send link state request packet to neighbor
+        //for recent lsa's which are not received in exchange state
+        LsRequest lsRequest = new LsRequest();
+        lsRequest.setOspfVer(OspfUtil.OSPF_VERSION);
+        lsRequest.setOspftype(OspfPacketType.LSREQUEST.value());
+        lsRequest.setRouterId(ospfArea.routerId());
+        lsRequest.setAreaId(ospfArea.areaId());
+        lsRequest.setAuthType(OspfUtil.NOT_ASSIGNED);
+        lsRequest.setAuthentication(OspfUtil.NOT_ASSIGNED);
+        lsRequest.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+        lsRequest.setChecksum(OspfUtil.NOT_ASSIGNED);
+
+        Set lsaKeys = lsReqList.keySet();
+        Iterator itr = lsaKeys.iterator();
+
+        int currentLength = OspfUtil.OSPF_HEADER_LENGTH;
+        int maxSize = ospfInterface.mtu() -
+                OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
+
+        while (itr.hasNext()) {
+            if ((currentLength + OspfUtil.LSREQUEST_LENGTH) >= maxSize) {
+                break;
+            }
+            LsRequestPacket lsRequestPacket = new LsRequestPacket();
+
+            String key = ((String) itr.next());
+            String[] lsaKey = key.split("-");
+            OspfLsa lsa = (OspfLsa) lsReqList.get(key);
+
+            lsRequestPacket.setLsType(Integer.valueOf(lsaKey[0]));
+            lsRequestPacket.setOwnRouterId(lsaKey[2]);
+
+            if (((lsa.getOspfLsaType().value() == OspfLsaType.AREA_LOCAL_OPAQUE_LSA.value()) ||
+                    (lsa.getOspfLsaType().value() == OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
+                    (lsa.getOspfLsaType().value() == OspfLsaType.AS_OPAQUE_LSA.value())) {
+                OpaqueLsaHeader header = (OpaqueLsaHeader) lsa;
+                byte[] opaqueIdBytes = OspfUtil.convertToTwoBytes(header.opaqueId());
+                lsRequestPacket.setLinkStateId(header.opaqueType() + "." + "0" + "." + opaqueIdBytes[0]
+                                                       + "." + opaqueIdBytes[1]);
+            } else {
+                lsRequestPacket.setLinkStateId(lsaKey[1]);
+            }
+
+            lsRequest.addLinkStateRequests(lsRequestPacket);
+            currentLength = currentLength + OspfUtil.LSREQUEST_LENGTH;
+        }
+
+        return lsRequest;
+    }
+
+    /**
+     * Determines whether an adjacency should be established/maintained with the neighbor or not.
+     *
+     * @param ch netty channel instance
+     */
+    public void adjOk(Channel ch) {
+        log.debug("OSPFNbr::adjOk...!!!");
+        if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
+            if (state == OspfNeighborState.TWOWAY) {
+                if (formAdjacencyOrNot()) {
+                    state = OspfNeighborState.EXSTART;
+                    //check for sequence number in lsdb
+                    ddSeqNum++;
+
+                    DdPacket ddPacket = new DdPacket();
+                    // seting OSPF Header
+                    ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
+                    ddPacket.setOspftype(OspfPacketType.DD.value());
+                    ddPacket.setRouterId(ospfArea.routerId());
+                    ddPacket.setAreaId(ospfArea.areaId());
+                    ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
+                    ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                    ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED);
+                    ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
+
+                    // setting DD Body
+                    boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
+                    if (isOpaqueEnabled && this.isOpaqueCapable) {
+                        ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
+                    } else {
+                        ddPacket.setOptions(ospfArea.options());
+                    }
+                    ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
+                    ddPacket.setIsMore(OspfUtil.MORE_SET);
+                    ddPacket.setIsMaster(OspfUtil.IS_MASTER);
+                    ddPacket.setImtu(ospfInterface.mtu());
+                    ddPacket.setSequenceNo(ddSeqNum);
+                    rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
+                    startRxMtDdTimer(ch);
+                    //setting destination ip
+                    ddPacket.setDestinationIp(neighborIpAddr());
+                    setLastSentDdPacket(ddPacket);
+                    ch.write(ddPacket);
+                }
+            } else if (state.getValue() >= OspfNeighborState.EXSTART.getValue()) {
+                if (!formAdjacencyOrNot()) {
+                    state = OspfNeighborState.TWOWAY;
+                    lsReqList.clear();
+                    ddSummaryList.clear();
+                    reTxList.clear();
+                }
+            }
+        }
+    }
+
+    /**
+     * LS Update Packet has been received while state was EXCHANGE or LOADING.
+     * Examine the received LSAs, check whether they were requested or not and process
+     * them accordingly. Therefore use method "processReceivedLsa" for further treatment.
+     *
+     * @param lsUpdPkt LS Update Packet received while Neighbor state was EXCHANGE or
+     *                 LOADING
+     * @param ch       netty channel instance
+     * @throws Exception might throws exception
+     */
+    public void processLsUpdate(LsUpdate lsUpdPkt, Channel ch) throws Exception {
+        stopRxMtLsrTimer();
+        log.debug("OSPFNbr::processLsUpdate...!!!");
+
+        List lsaList = lsUpdPkt.getLsaList();
+        if (!lsaList.isEmpty()) {
+            Iterator itr = lsaList.iterator();
+
+            while (itr.hasNext()) {
+                LsaHeader lsaHeader = (LsaHeader) itr.next();
+                String key = ((OspfAreaImpl) ospfArea).getLsaKey(lsaHeader);
+
+                if (lsReqList.containsKey(key)) {
+                    boolean removeIt;
+                    removeIt = processReceivedLsa(lsaHeader, false, ch,
+                                                  lsUpdPkt.sourceIp());
+                    if (removeIt) {
+                        lsReqList.remove(key);
+                    }
+                } else {
+                    // LSA was received via Flooding
+                    processReceivedLsa(lsaHeader, true, ch,
+                                       lsUpdPkt.sourceIp());
+                }
+            }
+
+            if (lsReqList.isEmpty() && (state == OspfNeighborState.LOADING)) {
+                // loading complete
+                loadingDone();
+            } else {
+                stopRxMtLsrTimer();
+                LsRequest lsRequest = buildLsRequest();
+                lsRequest.setDestinationIp(lsUpdPkt.sourceIp());
+                setLastSentLsrPacket(lsRequest);
+
+                startRxMtLsrTimer(ch);
+            }
+        }
+    }
+
+    /***
+     * Method gets called when no more ls request list and moving to FULL State.
+     *
+     * @throws Exception might throws exception
+     */
+    public void loadingDone() throws Exception {
+        stopRxMtLsrTimer();
+        stopRxMtDdTimer();
+        log.debug("OSPFNbr::loadingDone...!!!");
+        state = OspfNeighborState.FULL;
+        ospfArea.refreshArea(ospfInterface);
+    }
+
+    /**
+     * Adds device and link.
+     *
+     * @param topologyForDeviceAndLink topology for device and link instance
+     */
+    private void callDeviceAndLinkAdding(TopologyForDeviceAndLink topologyForDeviceAndLink) {
+        Map<String, DeviceInformation> deviceInformationMap = topologyForDeviceAndLink.deviceInformationMap();
+        Map<String, LinkInformation> linkInformationMap = topologyForDeviceAndLink.linkInformationMap();
+        OspfRouter ospfRouter = new OspfRouterImpl();
+        log.debug("Device Information in list format along with size {}", deviceInformationMap.size());
+        for (String key : deviceInformationMap.keySet()) {
+            DeviceInformation value = deviceInformationMap.get(key);
+            ospfRouter.setRouterIp(value.routerId());
+            ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
+            ospfRouter.setNeighborRouterId(value.deviceId());
+            OspfDeviceTed ospfDeviceTed = new OspfDeviceTedImpl();
+            List<Ip4Address> ip4Addresses = value.interfaceId();
+            ospfDeviceTed.setIpv4RouterIds(ip4Addresses);
+            ospfRouter.setDeviceTed(ospfDeviceTed);
+            ospfRouter.setOpaque(ospfArea.isOpaqueEnabled());
+            if (value.isDr()) {
+                ospfRouter.setDr(value.isDr());
+            } else {
+                ospfRouter.setDr(false);
+            }
+            int size = value.interfaceId().size();
+            for (int i = 0; i < size; i++) {
+                ospfRouter.setInterfaceId(value.interfaceId().get(i));
+            }
+            if (value.isAlreadyCreated()) {
+                removeDeviceDetails(value.routerId());
+                OspfRouter ospfRouter1 = new OspfRouterImpl();
+                ospfRouter1.setRouterIp(value.routerId());
+                ospfRouter1.setInterfaceId(ospfInterface.ipAddress());
+                ospfRouter1.setAreaIdOfInterface(ospfArea.areaId());
+                ospfRouter1.setDeviceTed(new OspfDeviceTedImpl());
+                topologyForDeviceAndLink.removeLinks(value.routerId());
+                handler.removeDeviceInformation(ospfRouter1);
+            }
+            handler.addDeviceInformation(ospfRouter);
+        }
+        for (Map.Entry<String, LinkInformation> entry : linkInformationMap.entrySet()) {
+            String key = entry.getKey();
+            LinkInformation value = entry.getValue();
+            OspfRouter ospfRouterForLink = new OspfRouterImpl();
+            ospfRouterForLink.setInterfaceId(value.interfaceIp());
+            ospfRouterForLink.setAreaIdOfInterface(ospfArea.areaId());
+            ospfRouterForLink.setOpaque(ospfArea.isOpaqueEnabled());
+            OspfLinkTed ospfLinkTed =
+                    topologyForDeviceAndLink.getOspfLinkTedHashMap(value.linkDestinationId().toString());
+            if (ospfLinkTed == null) {
+                ospfLinkTed = new OspfLinkTedImpl();
+                ospfLinkTed.setMaximumLink(Bandwidth.bps(0));
+                ospfLinkTed.setMaxReserved(Bandwidth.bps(0));
+                ospfLinkTed.setTeMetric(0);
+            }
+
+            if (!value.isLinkSrcIdNotRouterId()) {
+                ospfRouterForLink.setRouterIp(value.linkSourceId());
+                ospfRouterForLink.setNeighborRouterId(value.linkDestinationId());
+                try {
+                    handler.addLinkInformation(ospfRouterForLink, ospfLinkTed);
+                    log.debug("LinkId, LinkSrc , LinkDest , LinkInterface values are : "
+                                      + value.linkId() + " , " + value.linkSourceId() + "  , "
+                                      + value.linkDestinationId() + " , "
+                                      + value.interfaceIp());
+                } catch (Exception e) {
+                    log.debug("Got Exception : {}", e.getMessage());
+                }
+            }
+        }
+    }
+
+    // RFC 2328 Section 13 - partly as flooding procedure
+
+    /**
+     * Processes the received Lsa.
+     *
+     * @param recLsa              received Lsa
+     * @param receivedViaFlooding received via flooding or not
+     * @param ch                  channel instance
+     * @param sourceIp            source of this Lsa
+     * @return true to remove it from lsReqList else false
+     * @throws Exception might throws exception
+     */
+    public boolean processReceivedLsa(LsaHeader recLsa,
+                                      boolean receivedViaFlooding, Channel ch, Ip4Address sourceIp)
+            throws Exception {
+        log.debug("OSPFNbr::processReceivedLsa(recLsa, recievedViaFlooding, ch)...!!!");
+
+        //Validate the lsa checksum RFC 2328 13 (1)
+        ChecksumCalculator checkSum = new ChecksumCalculator();
+        if (!checkSum.isValidLsaCheckSum(recLsa,
+                                         recLsa.getOspfLsaType().value(),
+                                         OspfUtil.LSAPACKET_CHECKSUM_POS1,
+                                         OspfUtil.LSAPACKET_CHECKSUM_POS2)) {
+            log.debug("Checksum mismatch. Received LSA packet type {} ",
+                      recLsa.lsType());
+
+            return true;
+        }
+
+        //If LSA type is unknown discard the lsa RFC 2328 13(2)
+        if (((recLsa.getOspfLsaType().value() > OspfLsaType.EXTERNAL_LSA.value()) &&
+                (recLsa.getOspfLsaType().value() < OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
+                (recLsa.getOspfLsaType().value() > OspfLsaType.AS_OPAQUE_LSA.value())) {
+            return true;
+        }
+
+        //If LSA type is external & the area is configured as stub area discard the lsa RFC 2328 13(3)
+        if ((recLsa.getOspfLsaType() == OspfLsaType.EXTERNAL_LSA) &&
+                (!ospfArea.isExternalRoutingCapability())) // to determine how to store options
+        {
+            return true;
+        }
+
+        //if lsa age is equal to maxage && instance is not in lsdb && none of neighbors are in exchange
+        // or loading state
+        // Acknowledge the receipt by sending LSAck to the sender. 2328 13(4)
+        if ((recLsa.age() == OspfParameters.MAXAGE) &&
+                (ospfArea.lsaLookup(recLsa) == null) &&
+                ospfArea.noNeighborInLsaExchangeProcess()) {
+            // RFC 2328 Section 13. (4)
+            // Because the LSA was not yet requested, it is treated as a flooded LSA and thus
+            // acknowledged.
+            directAcknowledge(recLsa, ch, sourceIp);
+            return true;
+        }
+
+        String key = ((OspfAreaImpl) ospfArea).getLsaKey(recLsa);
+        LsaWrapper lsWrapper = ospfArea.lsaLookup(recLsa);
+        String status = isNullorLatest(lsWrapper, recLsa);
+        //Section 13 (5)
+        if (status.equals("isNullorLatest")) {
+
+            if (recLsa.lsType() == OspfLsaType.ROUTER.value() && recLsa.advertisingRouter().equals(
+                    ospfArea.routerId())) {
+                if (recLsa.lsSequenceNo() > ((LsaWrapperImpl) lsWrapper).lsaHeader().lsSequenceNo()) {
+                    ospfArea.setDbRouterSequenceNumber(recLsa.lsSequenceNo() + 1);
+                    processSelfOriginatedLsa();
+                }
+
+                if (recLsa.age() == OspfParameters.MAXAGE) {
+                    ((LsaWrapperImpl) lsWrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
+                    //remove from db & bin, add the lsa to MaxAge bin.
+                    ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
+                            lsWrapper).lsaHeader()), lsWrapper);
+                    ospfArea.removeLsaFromBin(lsWrapper);
+                }
+
+                return true;
+            } else if (recLsa.lsType() == OspfLsaType.NETWORK.value() && isLinkStateMatchesOwnRouterId(
+                    recLsa.linkStateId())) {
+                // if we are not DR or if origination router ID not equal to our router ID //either
+                // DR state changed or our router ID was changed
+                //set LSAge = MaxAge
+                //flood the LSA
+                if (((OspfInterfaceImpl) ospfInterface).state() != OspfInterfaceState.DR ||
+                        !recLsa.advertisingRouter().equals(
+                                ospfArea.routerId())) {
+                    if (lsWrapper != null) {
+                        ((LsaWrapperImpl) lsWrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
+                        //remove from bin, add the lsa to MaxAge bin.
+                        ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
+                                lsWrapper).lsaHeader()), lsWrapper);
+                        ospfArea.removeLsaFromBin(lsWrapper);
+                    } else {
+                        recLsa.setAge(OspfParameters.MAXAGE);
+                        ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
+                    }
+                }
+
+                return true;
+            } else {
+                if (recLsa.age() == OspfParameters.MAXAGE) {
+                    ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
+                    //remove from db & bin, add the lsa to MaxAge bin.
+                    if (lsWrapper != null) {
+                        lsWrapper.setLsaAgeReceived(OspfParameters.MAXAGE);
+                        ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
+                                lsWrapper).lsaHeader()), lsWrapper);
+                        ospfArea.removeLsaFromBin(lsWrapper);
+                    } else {
+                        ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
+                    }
+
+                    return true;
+                } else {
+                    ospfArea.addLsa(recLsa, ospfInterface);
+                    log.debug("Inside addLsaMethod");
+                    topologyForDeviceAndLink.addLocalDevice(recLsa, ospfInterface, ospfArea);
+                    callDeviceAndLinkAdding(topologyForDeviceAndLink);
+                    log.debug("Adding to lsdb interface State {}", ((OspfInterfaceImpl) ospfInterface).state().value());
+                    // should not send any acknowledge if flooded out on receiving interface
+                    if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.BDR.value()) {
+                        if (neighborDr.equals(sourceIp)) {
+                            log.debug("Adding for delayed ack {}", recLsa);
+                            ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
+                        }
+                    } else {
+                        log.debug("Adding for delayed ack {}", recLsa);
+                        ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
+                    }
+
+                    if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.DR.value() ||
+                            ((OspfInterfaceImpl) ospfInterface).state().value() ==
+                                    OspfInterfaceState.POINT2POINT.value()) {
+                        ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
+                    }
+                }
+
+            }
+        }
+        // RFC 2328 Section 13  (6)
+        if (lsReqList.contains(key)) {
+            badLSReq(ch);
+        }
+        if (status.equals("same")) { //13 (7)
+            if (pendingReTxList.containsKey(key)) {
+                pendingReTxList.remove(key);
+                if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.BDR.value()) {
+                    if (neighborDr.equals(recLsa.advertisingRouter())) {
+                        ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
+                    }
+                }
+            } else {
+                directAcknowledge(recLsa, ch, sourceIp);
+                return true;
+            }
+        } else if (status.equals("old")) { // section 13 - point 8
+            if ((recLsa.lsSequenceNo() == OspfParameters.MAXSEQUENCENUMBER) &&
+                    (recLsa.age() == OspfParameters.MAXAGE)) {
+                // section 13 - point 8
+                // simple discard the received LSA -
+                return true;
+            } else {
+                // respond back with the same LSA
+                //Using flood LSA to sent the LSUpdate back to advertising router
+                int diff = Math.abs(lsWrapper.lsaAgeReceived() - recLsa.age());
+                if (diff > OspfParameters.MINLSARRIVAL) {
+                    sendLsa(((LsaWrapperImpl) lsWrapper).lsaHeader(), sourceIp, ch);
+                }
+            }
+        }
+        callDeviceAndLinkAdding(topologyForDeviceAndLink);
+        return true;
+    }
+
+    /**
+     * Checks Link State ID is equal to one of the router's own IP interface addresses.
+     *
+     * @param linkStateId link state id
+     * @return true if link state matches or false
+     */
+    private boolean isLinkStateMatchesOwnRouterId(String linkStateId) {
+        boolean isLinkStateMatches = false;
+        List<OspfInterface> interfaceLst = ospfArea.getInterfacesLst();
+        for (OspfInterface ospfInterface : interfaceLst) {
+            if (ospfInterface.ipAddress().toString().equals(linkStateId)) {
+                isLinkStateMatches = true;
+                break;
+            }
+        }
+
+        return isLinkStateMatches;
+    }
+
+    /**
+     * RFC 2328 Section 13 (5).
+     *
+     * @param lsWrapper ls wrapper instance
+     * @param recLsa    received LSA instance
+     * @return returns a string status
+     */
+    public String isNullorLatest(LsaWrapper lsWrapper, LsaHeader recLsa) {
+
+
+        if (lsWrapper != null) {
+            LsaHeader ownLsa = (LsaHeader) lsWrapper.ospfLsa();
+            String status = ospfArea.isNewerOrSameLsa(recLsa, ownLsa);
+
+            if (status.equals("latest")) {
+                return "isNullorLatest";
+            } else {
+                return status;
+            }
+        } else {
+            return "isNullorLatest";
+        }
+    }
+
+    /**
+     * RFC 2328 section 13.4
+     * Processing self-originated LSAs.
+     *
+     * @throws Exception might throws exception
+     */
+    public void processSelfOriginatedLsa() throws Exception {
+        ospfArea.refreshArea(ospfInterface);
+    }
+
+    /**
+     * Sends the LSA to destination address.
+     *
+     * @param lsa         LSA instance to sent
+     * @param destination destination IP address
+     * @param ch          netty channel instance
+     */
+    public void sendLsa(LsaHeader lsa, Ip4Address destination, Channel ch) {
+        if (lsa == null) {
+            return;
+        }
+
+        LsUpdate responseLsUpdate = new LsUpdate();
+        // seting OSPF Header
+        responseLsUpdate.setOspfVer(OspfUtil.OSPF_VERSION);
+        responseLsUpdate.setOspftype(OspfPacketType.LSUPDATE.value());
+        responseLsUpdate.setRouterId(ospfArea.routerId());
+        responseLsUpdate.setAreaId(ospfArea.areaId());
+        responseLsUpdate.setAuthType(OspfUtil.NOT_ASSIGNED);
+        responseLsUpdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
+        responseLsUpdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+        responseLsUpdate.setChecksum(OspfUtil.NOT_ASSIGNED);
+        responseLsUpdate.setNumberOfLsa(1);
+        responseLsUpdate.addLsa(lsa);
+
+        //setting the destination.
+        responseLsUpdate.setDestinationIp(destination);
+        ch.write(responseLsUpdate);
+    }
+
+    /**
+     * Sends a direct Acknowledgment for a particular LSA to the Neighbor.
+     *
+     * @param ackLsa   LSA instance
+     * @param ch       netty channel instance
+     * @param sourceIp source IP address
+     */
+    public void directAcknowledge(LsaHeader ackLsa, Channel ch, Ip4Address sourceIp) {
+        log.debug("OSPFNbr::directAcknowledge...!!!");
+
+        LsAcknowledge ackContent = new LsAcknowledge();
+        // seting OSPF Header
+        ackContent.setOspfVer(OspfUtil.OSPF_VERSION);
+        ackContent.setOspftype(OspfPacketType.LSAACK.value());
+        ackContent.setRouterId(ospfArea.routerId());
+        ackContent.setAreaId(ospfArea.areaId());
+        ackContent.setAuthType(OspfUtil.NOT_ASSIGNED);
+        ackContent.setAuthentication(OspfUtil.NOT_ASSIGNED);
+        ackContent.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+        ackContent.setChecksum(OspfUtil.NOT_ASSIGNED);
+        ackContent.addLinkStateHeader(ackLsa);
+        //setting the destination IP
+        ackContent.setDestinationIp(sourceIp);
+        ch.write(ackContent);
+    }
+
+    /**
+     * Called when neighbor is down.
+     *
+     * @throws Exception might throws exception
+     */
+    public void neighborDown() throws Exception {
+        log.debug("Neighbor Down {} and NeighborId {}", neighborIpAddr,
+                  neighborId);
+        stopInactivityTimeCheck();
+        stopRxMtDdTimer();
+        stopRxMtLsrTimer();
+
+        if (floodingTimerScheduled) {
+            stopFloodingTimer();
+            floodingTimerScheduled = false;
+        }
+
+        state = OspfNeighborState.DOWN;
+        ospfArea.refreshArea(ospfInterface);
+        lsReqList.clear();
+        ddSummaryList.clear();
+        if (neighborIpAddr.equals(neighborBdr) ||
+                neighborIpAddr.equals(neighborDr)) {
+            handler.neighborChange();
+        }
+        log.debug("Neighbor Went Down : "
+                          + this.neighborIpAddr + " , " + this.neighborId);
+        removeDeviceDetails(this.neighborId);
+        OspfRouter ospfRouter = new OspfRouterImpl();
+        ospfRouter.setRouterIp(this.neighborId());
+        ospfRouter.setInterfaceId(ospfInterface.ipAddress());
+        ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
+        ospfRouter.setDeviceTed(new OspfDeviceTedImpl());
+        handler.removeDeviceInformation(ospfRouter);
+        removeDeviceDetails(this.neighborIpAddr);
+        OspfRouter ospfRouter1 = new OspfRouterImpl();
+        ospfRouter1.setRouterIp(this.neighborIpAddr);
+        ospfRouter1.setInterfaceId(ospfInterface.ipAddress());
+        ospfRouter1.setAreaIdOfInterface(ospfArea.areaId());
+        ospfRouter1.setDeviceTed(new OspfDeviceTedImpl());
+        handler.removeDeviceInformation(ospfRouter1);
+        handler.removeLinkInformation(this);
+        callDeviceAndLinkAdding(topologyForDeviceAndLink);
+    }
+
+    /**
+     * Removes device details.
+     *
+     * @param routerId router id
+     */
+    private void removeDeviceDetails(Ip4Address routerId) {
+        String key = "device:" + routerId;
+        topologyForDeviceAndLink.removeDeviceInformationMap(key);
+        topologyForDeviceAndLink.removeLinks(routerId);
+    }
+
+    /**
+     * Starts the inactivity timer.
+     */
+    private void startInactivityTimeCheck() {
+        if (!inActivityTimerScheduled) {
+            log.debug("OSPFNbr::startInactivityTimeCheck");
+            inActivityTimeCheckTask = new InternalInactivityTimeCheck();
+            exServiceInActivity = Executors.newSingleThreadScheduledExecutor();
+            exServiceInActivity.scheduleAtFixedRate(inActivityTimeCheckTask, routerDeadInterval,
+                                                    routerDeadInterval, TimeUnit.SECONDS);
+            inActivityTimerScheduled = true;
+        }
+    }
+
+    /**
+     * Stops the inactivity timer.
+     */
+    private void stopInactivityTimeCheck() {
+        if (inActivityTimerScheduled) {
+            log.debug("OSPFNbr::stopInactivityTimeCheck ");
+            exServiceInActivity.shutdown();
+            inActivityTimerScheduled = false;
+        }
+    }
+
+    /**
+     * Starts the flooding timer.
+     *
+     * @param channel channel instance
+     */
+    public void startFloodingTimer(Channel channel) {
+
+        if (!floodingTimerScheduled) {
+            log.debug("OSPFNbr::startFloodingTimer");
+            floodingTask = new InternalFloodingTask(channel);
+            exServiceFlooding = Executors.newSingleThreadScheduledExecutor();
+            //Run every 5 seconds.
+            exServiceFlooding.scheduleAtFixedRate(floodingTask, OspfParameters.START_NOW,
+                                                  OspfParameters.MINLSINTERVAL, TimeUnit.SECONDS);
+            floodingTimerScheduled = true;
+        }
+    }
+
+    /**
+     * Stops the flooding timer.
+     */
+    private void stopFloodingTimer() {
+        if (floodingTimerScheduled) {
+            log.debug("OSPFNbr::stopFloodingTimer ");
+            exServiceFlooding.shutdown();
+            floodingTimerScheduled = false;
+        }
+    }
+
+    /**
+     * Starts the Dd Retransmission executor task.
+     *
+     * @param ch netty channel instance
+     */
+    private void startRxMtDdTimer(Channel ch) {
+        if (!rxmtDdPacketTimerScheduled) {
+            long retransmitInterval = ospfInterface.reTransmitInterval();
+            rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
+            exServiceRxmtDDPacket = Executors.newSingleThreadScheduledExecutor();
+            exServiceRxmtDDPacket.scheduleAtFixedRate(rxmtDdPacketTask, retransmitInterval,
+                                                      retransmitInterval, TimeUnit.SECONDS);
+            rxmtDdPacketTimerScheduled = true;
+        }
+    }
+
+    /**
+     * Stops the Dd Retransmission executor task.
+     */
+    private void stopRxMtDdTimer() {
+        if (rxmtDdPacketTimerScheduled) {
+            exServiceRxmtDDPacket.shutdown();
+            rxmtDdPacketTimerScheduled = false;
+        }
+    }
+
+    /**
+     * Starts Ls request retransmission executor task.
+     *
+     * @param ch Netty channel instance
+     */
+    private void startRxMtLsrTimer(Channel ch) {
+        if (!rxmtLsrTimerScheduled) {
+            log.debug("OSPFNbr::startRxMtLsrTimer...!!!");
+            long retransmitIntrvl = ospfInterface.reTransmitInterval();
+            rxmtLsrPacketTask = new InternalRxmtLsrPacket(ch);
+            exServiceRxmtLsr = Executors.newSingleThreadScheduledExecutor();
+            exServiceRxmtLsr.scheduleAtFixedRate(rxmtLsrPacketTask, retransmitIntrvl,
+                                                 retransmitIntrvl, TimeUnit.SECONDS);
+            rxmtLsrTimerScheduled = true;
+        }
+    }
+
+    /**
+     * Stops Ls request retransmission executor task.
+     */
+    private void stopRxMtLsrTimer() {
+        if (rxmtLsrTimerScheduled) {
+            exServiceRxmtLsr.shutdown();
+            rxmtLsrTimerScheduled = false;
+        }
+    }
+
+    /**
+     * Gets the last sent DdPacket.
+     *
+     * @return DdPacket instance
+     */
+    public DdPacket lastDdPacket() {
+        return lastDdPacket;
+    }
+
+    /**
+     * Sets the last sent DdPacket.
+     *
+     * @param lastDdPacket DdPacket instance
+     */
+    public void setLastDdPacket(DdPacket lastDdPacket) {
+        this.lastDdPacket = lastDdPacket;
+    }
+
+    /**
+     * Gets neighbor id.
+     *
+     * @return neighbor id
+     */
+    public Ip4Address neighborId() {
+        return neighborId;
+    }
+
+    /**
+     * Sets the neighbor id.
+     *
+     * @param neighborId neighbor id
+     */
+    public void setNeighborId(Ip4Address neighborId) {
+        this.neighborId = neighborId;
+    }
+
+    /**
+     * Gets the neighbor DR address.
+     *
+     * @return neighbor DR address
+     */
+    public Ip4Address neighborDr() {
+        return neighborDr;
+    }
+
+    /**
+     * Sets the neighbor DR address.
+     *
+     * @param neighborDr neighbor DR address
+     */
+    public void setNeighborDr(Ip4Address neighborDr) {
+        this.neighborDr = neighborDr;
+    }
+
+    /**
+     * Gets the neighbor BDR address.
+     *
+     * @return neighbor BDR address
+     */
+    public Ip4Address neighborBdr() {
+        return neighborBdr;
+    }
+
+    /**
+     * Sets the neighbor BDR address.
+     *
+     * @param neighborBdr neighbor BDR address
+     */
+    public void setNeighborBdr(Ip4Address neighborBdr) {
+        this.neighborBdr = neighborBdr;
+    }
+
+    /**
+     * Gets router priority.
+     *
+     * @return router priority
+     */
+    public int routerPriority() {
+        return routerPriority;
+    }
+
+    /**
+     * Sets router priority.
+     *
+     * @param routerPriority router priority
+     */
+    public void setRouterPriority(int routerPriority) {
+        this.routerPriority = routerPriority;
+    }
+
+    /**
+     * Gets the options value.
+     *
+     * @return options value
+     */
+    public int options() {
+        return options;
+    }
+
+    /**
+     * Sets the options value.
+     *
+     * @param options options value
+     */
+    public void setOptions(int options) {
+        this.options = options;
+    }
+
+    /**
+     * Gets the DD sequence number.
+     *
+     * @return DD sequence number
+     */
+    public long ddSeqNum() {
+        return ddSeqNum;
+    }
+
+    /**
+     * Sets the DD sequence number.
+     *
+     * @param ddSeqNum DD sequence number
+     */
+    public void setDdSeqNum(long ddSeqNum) {
+        this.ddSeqNum = ddSeqNum;
+    }
+
+    /**
+     * Gets neighbor is master or not.
+     *
+     * @return true if neighbor is master else false
+     */
+    public int isMaster() {
+        return isMaster;
+    }
+
+    /**
+     * Gets the last sent DD Packet.
+     *
+     * @return last sent DD Packet
+     */
+    public DdPacket lastSentDdPacket() {
+        return lastSentDdPacket;
+    }
+
+    /**
+     * Sets the last sent DD Packet.
+     *
+     * @param lastSentDdPacket last sent DD Packet
+     */
+    public void setLastSentDdPacket(DdPacket lastSentDdPacket) {
+        this.lastSentDdPacket = lastSentDdPacket;
+    }
+
+    /**
+     * Gets the last sent Ls Request Packet.
+     *
+     * @return last sent Ls Request Packet
+     */
+    public LsRequest getLastSentLsrPacket() {
+        return lastSentLsrPacket;
+    }
+
+    /**
+     * Sets the last sent Ls Request Packet.
+     *
+     * @param lastSentLsrPacket last sent Ls Request Packet
+     */
+    public void setLastSentLsrPacket(LsRequest lastSentLsrPacket) {
+        this.lastSentLsrPacket = lastSentLsrPacket;
+    }
+
+    /**
+     * Gets the neighbors state.
+     *
+     * @return neighbors state
+     */
+    public OspfNeighborState getState() {
+        return state;
+    }
+
+    /**
+     * Sets the neighbors state.
+     *
+     * @param state neighbors state
+     */
+    public void setState(OspfNeighborState state) {
+        this.state = state;
+    }
+
+    /**
+     * Sets neighbor is master or not.
+     *
+     * @param isMaster neighbor is master or not
+     */
+    public void setIsMaster(int isMaster) {
+        this.isMaster = isMaster;
+    }
+
+    /**
+     * Gets the ls request list.
+     *
+     * @return ls request list
+     */
+    public Hashtable getLsReqList() {
+        return lsReqList;
+    }
+
+    /**
+     * Gets the reTxList instance.
+     *
+     * @return reTxList instance
+     */
+    public Map getReTxList() {
+        return reTxList;
+    }
+
+    /**
+     * Gets the pending re transmit list.
+     *
+     * @return pendingReTxList instance
+     */
+    public Map<String, OspfLsa> getPendingReTxList() {
+        return pendingReTxList;
+    }
+
+
+    /**
+     * Represents a Task which will do an inactivity time check.
+     */
+    private class InternalInactivityTimeCheck implements Runnable {
+        /**
+         * Constructor.
+         */
+        InternalInactivityTimeCheck() {
+        }
+
+        @Override
+        public void run() {
+            try {
+                log.debug("Neighbor Not Heard till the past router dead interval .");
+                neighborDown();
+            } catch (Exception e) {
+                log.debug("Exception at inactivity time check...!!!");
+            }
+        }
+    }
+
+    /**
+     * Task which re transmits DdPacket every configured time interval.
+     */
+    private class InternalRxmtDdPacket implements Runnable {
+        Channel ch;
+
+        /**
+         * Creates an instance or Re transmit DD packet timer.
+         *
+         * @param ch netty channel instance
+         */
+        InternalRxmtDdPacket(Channel ch) {
+            this.ch = ch;
+        }
+
+        @Override
+        public void run() {
+            if ((ch != null) && ch.isConnected()) {
+                DdPacket ddPacket = lastSentDdPacket();
+                ch.write(ddPacket);
+                log.debug("Re-Transmit DD Packet .");
+            } else {
+                log.debug(
+                        "Re-Transmit DD Packet failed. Channel not connected..");
+            }
+        }
+    }
+
+    /**
+     * Task which re transmits Ls request Packet every configured time interval.
+     */
+    private class InternalRxmtLsrPacket implements Runnable {
+        Channel ch;
+
+        /**
+         * Creates an instance or Re transmit LS Request packet timer.
+         *
+         * @param ch netty channel instance
+         */
+        InternalRxmtLsrPacket(Channel ch) {
+            this.ch = ch;
+        }
+
+        @Override
+        public void run() {
+            if ((ch != null) && ch.isConnected()) {
+                LsRequest lsrPacket = getLastSentLsrPacket();
+                ch.write(lsrPacket);
+                log.debug("Re-Transmit LSRequest Packet .");
+            } else {
+                log.debug(
+                        "Re-Transmit LSRequest failed. Channel not connected..");
+            }
+        }
+    }
+
+    /**
+     * Task which transmits Ls update Packet based on the re transmit list.
+     * every configured time interval.
+     */
+    private class InternalFloodingTask implements Runnable {
+        Channel channel;
+
+        /**
+         * Creates an instance or Flooding task.
+         *
+         * @param ch netty channel instance
+         */
+        InternalFloodingTask(Channel ch) {
+            this.channel = ch;
+        }
+
+        @Override
+        public void run() {
+            if ((channel != null) && channel.isConnected()) {
+
+                if ((pendingReTxList != null) && (pendingReTxList.size() > 0)) {
+                    List<LsUpdate> lsUpdateList = buildLsUpdate(pendingReTxList);
+
+                    for (LsUpdate lsupdate : lsUpdateList) {
+                        //Pending for acknowledge directly sent it to neighbor
+                        lsupdate.setDestinationIp(neighborIpAddr);
+                        channel.write(lsupdate);
+                    }
+                }
+
+                if ((reTxList != null) && (reTxList.size() > 0)) {
+                    List<LsUpdate> lsUpdateList = buildLsUpdate(reTxList);
+
+                    for (LsUpdate lsupdate : lsUpdateList) {
+                        //set the destination
+                        if ((((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR) ||
+                                (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT)) {
+                            lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
+                        } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER ||
+                                (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR)) {
+                            lsupdate.setDestinationIp(neighborDr);
+                        }
+                        channel.write(lsupdate);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Builds the LsUpdate for flooding.
+         *
+         * @param txList list contains LSAs
+         * @return list of LsUpdate instances
+         */
+        private List buildLsUpdate(Map<String, OspfLsa> txList) {
+            List<LsUpdate> lsUpdateList = new ArrayList<>();
+            ListIterator itr = new ArrayList(txList.keySet()).listIterator();
+            while (itr.hasNext()) {
+                LsUpdate lsupdate = new LsUpdate();
+                // seting OSPF Header
+                lsupdate.setOspfVer(OspfUtil.OSPF_VERSION);
+                lsupdate.setOspftype(OspfPacketType.LSUPDATE.value());
+                lsupdate.setRouterId(ospfArea.routerId());
+                lsupdate.setAreaId(ospfArea.areaId());
+                lsupdate.setAuthType(OspfUtil.NOT_ASSIGNED);
+                lsupdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
+                lsupdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
+                lsupdate.setChecksum(OspfUtil.NOT_ASSIGNED);
+
+                //limit to mtu
+                int currentLength = OspfUtil.OSPF_HEADER_LENGTH + OspfUtil.FOUR_BYTES;
+                int maxSize = ospfInterface.mtu() -
+                        OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
+
+                int noLsa = 0;
+                while (itr.hasNext()) {
+
+                    String key = (String) itr.next();
+                    OspfLsa lsa = txList.get(key);
+                    if ((lsa.age() + OspfParameters.INFTRA_NS_DELAY) >= OspfParameters.MAXAGE) {
+                        ((LsaHeader) lsa.lsaHeader()).setAge(OspfParameters.MAXAGE);
+                    } else {
+                        ((LsaHeader) lsa.lsaHeader()).setAge(lsa.age() + OspfParameters.INFTRA_NS_DELAY);
+                    }
+
+                    if ((currentLength + ((LsaHeader) lsa.lsaHeader()).lsPacketLen()) >= maxSize) {
+                        itr.previous();
+                        break;
+                    }
+                    log.debug("FloodingTimer::LSA Type::{}, Header: {}, LSA: {}", lsa.getOspfLsaType(),
+                              lsa.lsaHeader(), lsa);
+
+                    if (lsa != null) {
+                        lsupdate.addLsa(lsa);
+                        noLsa++;
+                        currentLength = currentLength + ((LsaHeader) lsa.lsaHeader()).lsPacketLen();
+                    }
+                    log.debug("FloodingTimer::Removing key {}", key);
+                    if (txList.equals(reTxList)) {
+                        reTxList.remove(key);
+                        pendingReTxList.put(key, lsa);
+                    }
+                }
+                //set number of lsa's
+                lsupdate.setNumberOfLsa(noLsa);
+                lsUpdateList.add(lsupdate);
+            }
+            return lsUpdateList;
+        }
+    }
+}
\ No newline at end of file
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/OspfLsdbImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/OspfLsdbImpl.java
new file mode 100755
index 0000000..2c30155
--- /dev/null
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/OspfLsdbImpl.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ospf.controller.lsdb;
+
+import com.google.common.base.Objects;
+import org.onosproject.ospf.controller.LsaBin;
+import org.onosproject.ospf.controller.LsaWrapper;
+import org.onosproject.ospf.controller.LsdbAge;
+import org.onosproject.ospf.controller.OspfArea;
+import org.onosproject.ospf.controller.OspfInterface;
+import org.onosproject.ospf.controller.OspfLsaType;
+import org.onosproject.ospf.controller.OspfLsdb;
+import org.onosproject.ospf.controller.area.OspfAreaImpl;
+import org.onosproject.ospf.protocol.lsa.LsaHeader;
+import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
+import org.onosproject.ospf.protocol.util.OspfParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Represents the Link State Database.
+ */
+public class OspfLsdbImpl implements OspfLsdb {
+    private static final Logger log = LoggerFactory.getLogger(OspfLsdbImpl.class);
+    private Map routerLsas = new HashMap();
+    private Map networkLsas = new HashMap();
+    private Map summaryLsas = new HashMap();
+    private Map asbrSummaryLSAs = new HashMap();
+    private Map opaque9Lsas = new HashMap();
+    private Map opaque10Lsas = new HashMap();
+    private Map opaque11Lsas = new HashMap();
+    private Map externalLsas = new HashMap();
+    private long routerLsaSeqNo = OspfParameters.STARTLSSEQUENCENUM;
+    private long networkLsaSeqNo = OspfParameters.STARTLSSEQUENCENUM;
+    private LsdbAge lsdbAge = null;
+    private OspfArea ospfArea = null;
+
+
+    /**
+     * Creates an instance of OSPF LSDB.
+     *
+     * @param ospfArea area instance
+     */
+    public OspfLsdbImpl(OspfArea ospfArea) {
+        this.ospfArea = ospfArea;
+        lsdbAge = new LsdbAgeImpl(ospfArea);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        OspfLsdbImpl that = (OspfLsdbImpl) o;
+        return Objects.equal(routerLsas.size(), that.routerLsas.size()) &&
+                Objects.equal(networkLsas.size(), that.networkLsas.size()) &&
+                Objects.equal(summaryLsas.size(), that.summaryLsas.size()) &&
+                Objects.equal(asbrSummaryLSAs.size(), that.asbrSummaryLSAs.size()) &&
+                Objects.equal(lsdbAge, that.lsdbAge) &&
+                Objects.equal(routerLsaSeqNo, that.routerLsaSeqNo) &&
+                Objects.equal(networkLsaSeqNo, that.networkLsaSeqNo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(routerLsas, networkLsas, summaryLsas, asbrSummaryLSAs, lsdbAge,
+                                routerLsaSeqNo, networkLsaSeqNo);
+    }
+
+    /**
+     * Initializes the link state database.
+     */
+    public void initializeDb() {
+        lsdbAge.startDbAging();
+    }
+
+    /**
+     * Returns all LSA Headers (Router and Summary) in a Vector.
+     *
+     * @param excludeMaxAgeLsa exclude the max age LSAs
+     * @param isOpaqueCapable  is opaque capable or not
+     * @return List of LSA headers
+     */
+    public List getAllLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaqueCapable) {
+        List summList = new CopyOnWriteArrayList();
+        addLsaToHeaderList(summList, excludeMaxAgeLsa, routerLsas);
+        addLsaToHeaderList(summList, excludeMaxAgeLsa, networkLsas);
+        addLsaToHeaderList(summList, excludeMaxAgeLsa, summaryLsas);
+        addLsaToHeaderList(summList, excludeMaxAgeLsa, asbrSummaryLSAs);
+        addLsaToHeaderList(summList, excludeMaxAgeLsa, externalLsas);
+        if (isOpaqueCapable) {
+            addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque9Lsas);
+            addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque10Lsas);
+            addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque11Lsas);
+        }
+
+        return summList;
+    }
+
+    /**
+     * Adds the LSAs to summary list.
+     *
+     * @param summList         summary list
+     * @param excludeMaxAgeLsa exclude max age LSA
+     * @param lsaMap           map of LSA
+     */
+    private void addLsaToHeaderList(List summList, boolean excludeMaxAgeLsa, Map lsaMap) {
+        Iterator slotVals = lsaMap.values().iterator();
+        while (slotVals.hasNext()) {
+            LsaWrapper wrapper = (LsaWrapper) slotVals.next();
+            if (excludeMaxAgeLsa) {
+                //if current age of lsa is max age or lsa present in Max Age bin
+                if (wrapper.currentAge() != OspfParameters.MAXAGE &&
+                        lsdbAge.getMaxAgeBin().ospfLsa(((OspfAreaImpl)
+                                ospfArea).getLsaKey(((LsaWrapperImpl) wrapper).lsaHeader())) == null) {
+                    addToList(wrapper, summList);
+                }
+            } else {
+                addToList(wrapper, summList);
+            }
+        }
+    }
+
+    /**
+     * Adds the LSWrapper to summary list.
+     *
+     * @param wrapper  LSA wrapper instance
+     * @param summList LSA summary list
+     */
+    private void addToList(LsaWrapper wrapper, List summList) {
+        LsaHeader header = (LsaHeader) wrapper.ospfLsa();
+        //set the current age
+        header.setAge(wrapper.currentAge());
+        summList.add(header);
+    }
+
+    /**
+     * Gets the LSDB LSA key from Lsa Header.
+     *
+     * @param lsaHeader LSA header instance
+     * @return key
+     */
+    public String getLsaKey(LsaHeader lsaHeader) {
+        String lsaKey = "";
+        switch (lsaHeader.lsType()) {
+            case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
+            case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
+            case OspfParameters.AS_OPAQUE_LSA:
+                OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
+                lsaKey = lsaHeader.lsType() + "-" + header.opaqueType() + header.opaqueId() + "-" +
+                        lsaHeader.advertisingRouter();
+                break;
+            case OspfParameters.ROUTER:
+            case OspfParameters.NETWORK:
+            case OspfParameters.ASBR_SUMMARY:
+            case OspfParameters.SUMMARY:
+            case OspfParameters.EXTERNAL_LSA:
+                lsaKey = lsaHeader.lsType() + "-" + lsaHeader.linkStateId() + "-" +
+                        lsaHeader.advertisingRouter();
+                break;
+            default:
+                log.debug("Unknown LSA type..!!!");
+                break;
+        }
+
+        return lsaKey;
+    }
+
+    /**
+     * Gets wrapper instance in LSDB.
+     *
+     * @param lsaHeader LSA header instance.
+     * @return LSA Wrapper instance.
+     */
+    public LsaWrapper lsaLookup(LsaHeader lsaHeader) {
+
+        return findLsa(lsaHeader.lsType(), getLsaKey(lsaHeader));
+    }
+
+    /**
+     * Finds the LSA from appropriate maps.
+     *
+     * @param lsType type of LSA
+     * @param lsaKey key
+     * @return LSA wrapper object
+     */
+    public LsaWrapper findLsa(int lsType, String lsaKey) {
+        LsaWrapper lsaWrapper = null;
+
+        switch (lsType) {
+            case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
+                lsaWrapper = (LsaWrapper) opaque9Lsas.get(lsaKey);
+                break;
+            case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
+                lsaWrapper = (LsaWrapper) opaque10Lsas.get(lsaKey);
+                break;
+            case OspfParameters.AS_OPAQUE_LSA:
+                lsaWrapper = (LsaWrapper) opaque11Lsas.get(lsaKey);
+                break;
+            case OspfParameters.ROUTER:
+                lsaWrapper = (LsaWrapper) routerLsas.get(lsaKey);
+                break;
+            case OspfParameters.NETWORK:
+                lsaWrapper = (LsaWrapper) networkLsas.get(lsaKey);
+                break;
+            case OspfParameters.ASBR_SUMMARY:
+                lsaWrapper = (LsaWrapper) asbrSummaryLSAs.get(lsaKey);
+                break;
+            case OspfParameters.SUMMARY:
+                lsaWrapper = (LsaWrapper) summaryLsas.get(lsaKey);
+                break;
+            case OspfParameters.EXTERNAL_LSA:
+                lsaWrapper = (LsaWrapper) externalLsas.get(lsaKey);
+                break;
+            default:
+                log.debug("Unknown LSA type..!!!");
+                break;
+        }
+
+        //set the current age
+        if (lsaWrapper != null) {
+            //set the current age
+            ((LsaWrapperImpl) lsaWrapper).lsaHeader().setAge(lsaWrapper.currentAge());
+            ((LsaHeader) lsaWrapper.ospfLsa()).setAge(lsaWrapper.currentAge());
+        }
+
+        return lsaWrapper;
+    }
+
+
+    /**
+     * Installs a new self-originated LSA if possible.
+     * Return true if installing was successful else false.
+     *
+     * @param newLsa           LSA header instance
+     * @param isSelfOriginated is self originated or not
+     * @param ospfInterface    OSPF interface instance
+     * @return true if successfully added
+     */
+    public boolean addLsa(LsaHeader newLsa, boolean isSelfOriginated, OspfInterface ospfInterface) {
+
+        LsaWrapperImpl lsaWrapper = new LsaWrapperImpl();
+        lsaWrapper.setLsaType(newLsa.getOspfLsaType());
+        lsaWrapper.setOspfLsa(newLsa);
+        lsaWrapper.setLsaHeader(newLsa);
+        lsaWrapper.setLsaAgeReceived(newLsa.age());
+        lsaWrapper.setAgeCounterWhenReceived(lsdbAge.getAgeCounter());
+        lsaWrapper.setIsSelfOriginated(isSelfOriginated);
+        lsaWrapper.setIsSelfOriginated(isSelfOriginated);
+        lsaWrapper.setOspfInterface(ospfInterface);
+        lsaWrapper.setLsdbAge(lsdbAge);
+        addLsa(lsaWrapper);
+
+        log.debug("Added LSA In LSDB: {}", newLsa);
+
+        return true;
+    }
+
+    /**
+     * Installs a new self-originated LSA if possible.
+     * Return true if installing was successful else false.
+     * Adding LSA In cases
+     * 1) New Self Originated LSA based on change in topology
+     * 2) New Self Originated LSA because of LSRefresh
+     * 2) New LSA received via Link State Update Packet
+     *
+     * @param newLsa LSA wrapper instance
+     * @return true if added successfully
+     */
+    private boolean addLsa(LsaWrapper newLsa) {
+        // adding an LSA - verify if it's old or new
+        // verify min failed
+        // to verify if it's a new LSA or updating the old LSA .
+        // fetch the LSA Type
+        // verify if the LSA age is ! Max Age
+        // a) it is  received during the flooding process (Section 13)
+        // b) it is originated by the router itself (Section 12.4)
+        // start aging .
+        String key = getLsaKey(((LsaWrapperImpl) newLsa).lsaHeader());
+        //Remove the lsa from bin if exist. we will be adding it in new bin based on the current age.
+        removeLsaFromBin(lsaLookup(((LsaWrapperImpl) newLsa).lsaHeader()));
+
+        switch (((LsaWrapperImpl) newLsa).lsaHeader().lsType()) {
+
+            case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
+                opaque9Lsas.put(key, newLsa);
+                break;
+            case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
+                opaque10Lsas.put(key, newLsa);
+                break;
+            case OspfParameters.AS_OPAQUE_LSA:
+                opaque11Lsas.put(key, newLsa);
+                break;
+            case OspfParameters.ROUTER:
+                routerLsas.put(key, newLsa);
+                break;
+            case OspfParameters.NETWORK:
+                networkLsas.put(key, newLsa);
+                break;
+            case OspfParameters.ASBR_SUMMARY:
+                asbrSummaryLSAs.put(key, newLsa);
+                break;
+            case OspfParameters.SUMMARY:
+                summaryLsas.put(key, newLsa);
+                break;
+            case OspfParameters.EXTERNAL_LSA:
+                externalLsas.put(key, newLsa);
+                break;
+            default:
+                log.debug("Unknown LSA type to add..!!!");
+                break;
+        }
+        //add it to bin
+        Integer binNumber = lsdbAge.age2Bin(((LsaWrapperImpl) newLsa).lsaHeader().age());
+        LsaBin lsaBin = lsdbAge.getLsaBin(binNumber);
+        if (lsaBin != null) {
+            //remove from existing
+            newLsa.setBinNumber(binNumber);
+            lsaBin.addOspfLsa(key, newLsa);
+            lsdbAge.addLsaBin(binNumber, lsaBin);
+            log.debug("Added Type {} LSA to LSDB and LSABin[{}], Age of LSA {}", newLsa.lsaType(),
+                      binNumber, ((LsaWrapperImpl) newLsa).lsaHeader().age());
+        }
+
+        return false;
+    }
+
+    /**
+     * Adds the LSA to maxAge bin.
+     *
+     * @param key     key
+     * @param wrapper LSA wrapper instance
+     */
+    public void addLsaToMaxAgeBin(String key, Object wrapper) {
+        lsdbAge.addLsaToMaxAgeBin(key, (LsaWrapper) wrapper);
+    }
+
+    /**
+     * Removes LSA from Bin.
+     *
+     * @param lsaWrapper LSA wrapper instance
+     */
+    public void removeLsaFromBin(Object lsaWrapper) {
+        if (lsaWrapper != null) {
+            lsdbAge.removeLsaFromBin((LsaWrapper) lsaWrapper);
+        }
+    }
+
+    /**
+     * RFC 2328 - Section 13.1.  Determining which LSA is newer.
+     *
+     * @param lsa1 LSA instance
+     * @param lsa2 LSA instance
+     * @return string status
+     */
+    public String isNewerOrSameLsa(LsaHeader lsa1, LsaHeader lsa2) {
+        if (lsa1.lsSequenceNo() > lsa2.lsSequenceNo()) {
+            return "latest";
+        } else if (lsa1.lsSequenceNo() < lsa2.lsSequenceNo()) {
+            return "old";
+        } else if (lsa1.lsSequenceNo() == lsa2.lsSequenceNo()) {
+            if (lsa1.lsCheckSum() > lsa2.lsCheckSum()) {
+                return "latest";
+            } else if (lsa1.lsCheckSum() < lsa2.lsCheckSum()) {
+                return "old";
+            } else if (lsa1.lsCheckSum() == lsa2.lsCheckSum()) {
+                if (lsa1.age() == lsa2.age()) {
+                    return "same";
+                } else if (lsa1.age() == OspfParameters.MAXAGE) {
+                    return "latest";
+                } else if (lsa2.age() == OspfParameters.MAXAGE) {
+                    return "old";
+                } else if (OspfParameters.MAXAGEDIFF == (lsa1.age() - lsa2.age())) {
+                    if (lsa1.age() < lsa2.age()) {
+                        return "latest";
+                    } else {
+                        return "old";
+                    }
+                } else {
+                    return "same";
+                }
+            }
+        }
+
+        return "";
+    }
+
+    /**
+     * Gets the sequence number.
+     *
+     * @param lsaType type of LSA
+     * @return sequence number
+     */
+    public long getLsSequenceNumber(OspfLsaType lsaType) {
+        switch (lsaType) {
+            case ROUTER:
+                return routerLsaSeqNo++;
+            case NETWORK:
+                return networkLsaSeqNo++;
+            default:
+                return OspfParameters.STARTLSSEQUENCENUM;
+        }
+    }
+
+    /**
+     * Deletes the given LSA.
+     *
+     * @param lsaHeader LSA header instance
+     */
+    public void deleteLsa(LsaHeader lsaHeader) {
+
+        String lsaKey = getLsaKey(lsaHeader);
+        switch (lsaHeader.lsType()) {
+            case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
+                opaque9Lsas.remove(lsaKey);
+                break;
+            case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
+                opaque10Lsas.remove(lsaKey);
+                break;
+            case OspfParameters.AS_OPAQUE_LSA:
+                opaque11Lsas.remove(lsaKey);
+                break;
+            case OspfParameters.ROUTER:
+                routerLsas.remove(lsaKey);
+                break;
+            case OspfParameters.NETWORK:
+                networkLsas.remove(lsaKey);
+                break;
+            case OspfParameters.ASBR_SUMMARY:
+                asbrSummaryLSAs.remove(lsaKey);
+                break;
+            case OspfParameters.SUMMARY:
+                summaryLsas.remove(lsaKey);
+                break;
+            case OspfParameters.EXTERNAL_LSA:
+                externalLsas.remove(lsaKey);
+                break;
+            default:
+                log.debug("Unknown LSA type to delete..!!!");
+                break;
+        }
+    }
+
+    /**
+     * Sets sequence number.
+     *
+     * @param routerLsaSeqNo sequence number
+     */
+    public void setRouterLsaSeqNo(long routerLsaSeqNo) {
+        this.routerLsaSeqNo = routerLsaSeqNo;
+    }
+
+    /**
+     * Sets sequence number.
+     *
+     * @param networkLsaSeqNo sequence number
+     */
+    public void setNetworkLsaSeqNo(long networkLsaSeqNo) {
+        this.networkLsaSeqNo = networkLsaSeqNo;
+    }
+}
\ No newline at end of file