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
