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