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