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/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