/*
* 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;
        }
    }
}