blob: 2cf07ba80b5f5f92b67bb389d5e3e3e8fbe22ea1 [file] [log] [blame]
/*
* Copyright 2016-present 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.isis.controller.impl.lsdb;
import org.onosproject.isis.controller.IsisLsdbAge;
import org.onosproject.isis.controller.IsisLspBin;
import org.onosproject.isis.controller.LspWrapper;
import org.onosproject.isis.io.isispacket.pdu.LsPdu;
import org.onosproject.isis.io.util.IsisConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Representation of ISIS link state database ageing process.
*/
public class DefaultIsisLsdbAge implements IsisLsdbAge {
private static final Logger log = LoggerFactory.getLogger(DefaultIsisLsdbAge.class);
protected static int ageCounter = 0;
private InternalAgeTimer dbAgeTimer;
private ScheduledExecutorService exServiceage;
private Integer maxBins = 1200;
private Map<Integer, IsisLspBin> ageBins = new ConcurrentHashMap<>(maxBins);
private int ageCounterRollOver = 0;
private IsisLspQueueConsumer queueConsumer = null;
private BlockingQueue<LspWrapper> lsaQueue = new ArrayBlockingQueue<>(1024);
/**
* Creates an instance of LSDB age.
*/
public DefaultIsisLsdbAge() {
// create LSBin's in the HashMap.
for (int i = 0; i < maxBins; i++) {
IsisLspBin lspBin = new DefaultIsisLspBin(i);
ageBins.put(i, lspBin);
}
}
/**
* Returns age counter.
*
* @return age counter
*/
public int ageCounter() {
return ageCounter;
}
/**
* Returns age counter roll over.
*
* @return age counter roll over
*/
public int ageCounterRollOver() {
return ageCounterRollOver;
}
/**
* Adds LSP to LS bin for ageing.
*
* @param binNumber key to store in bin
* @param lspBin LSP bin instance
*/
public void addLspBin(int binNumber, IsisLspBin lspBin) {
if (!ageBins.containsKey(binNumber)) {
ageBins.put(binNumber, lspBin);
}
}
/**
* Returns LSP from Bin.
*
* @param binKey key
* @return bin instance
*/
public IsisLspBin getLspBin(int binKey) {
return ageBins.get(binKey);
}
/**
* Removes LSP from Bin.
*
* @param lspWrapper wrapper instance
*/
public void removeLspFromBin(LspWrapper lspWrapper) {
if (ageBins.containsKey(lspWrapper.binNumber())) {
IsisLspBin lsaBin = ageBins.get(lspWrapper.binNumber());
lsaBin.removeIsisLsp(((LsPdu) lspWrapper.lsPdu()).lspId(), lspWrapper);
}
}
/**
* Returns the bin number.
*
* @param age Can be either age or ageCounter
* @return bin number.
*/
public int age2Bin(int age) {
if (age <= ageCounter) {
return (ageCounter - age);
} else {
return ((IsisConstants.LSPMAXAGE - 1) + (ageCounter - age));
}
}
/**
* Starts the aging timer and queue consumer.
*/
public void startDbAging() {
startDbAgeTimer();
queueConsumer = new IsisLspQueueConsumer(lsaQueue);
new Thread(queueConsumer).start();
}
/**
* Starts DB aging task.
*/
private void startDbAgeTimer() {
dbAgeTimer = new InternalAgeTimer();
//from 1 sec
exServiceage = Executors.newSingleThreadScheduledExecutor();
exServiceage.scheduleAtFixedRate(dbAgeTimer, 1, 1, TimeUnit.SECONDS);
}
/**
* Gets called every second as part of the aging process.
*/
public void ageLsp() {
refreshLsa();
maxAgeLsa();
if (ageCounter == IsisConstants.LSPMAXAGE) {
ageCounter = 0;
ageCounterRollOver++;
} else {
ageCounter++;
}
}
/**
* If the LSP have completed the MaxAge - they are moved called stop aging.
*/
public void maxAgeLsa() {
if (ageCounter == 0) {
return;
}
//Get from Age Bins
IsisLspBin lspBin = ageBins.get(ageCounter - 1);
if (lspBin == null) {
return;
}
Map lspBinMap = lspBin.listOfLsp();
for (Object key : lspBinMap.keySet()) {
LspWrapper lspWrapper = (LspWrapper) lspBinMap.get((String) key);
if (lspWrapper.currentAge() == IsisConstants.LSPMAXAGE) {
lspWrapper.setLspProcessing(IsisConstants.MAXAGELSP);
log.debug("Lsp picked for maxage removal. Age Counter: {}, AgeCounterRollover: {}, " +
"AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
ageCounter, ageCounterRollOver, lspWrapper.currentAge(),
lspWrapper.lsPdu().isisPduType(), key);
//add it to lspQueue for processing
try {
lsaQueue.put(lspWrapper);
//remove from bin
lspBin.removeIsisLsp((String) key, lspWrapper);
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::maxAgeLsp::{}", e.getMessage());
}
}
}
}
/*
* If the LSP is in age bin of 900s- it's pushed into refresh list.
*/
public void refreshLsa() {
int binNumber;
if (ageCounter < IsisConstants.LSPREFRESH) {
binNumber = ageCounter + IsisConstants.LSPREFRESH;
} else {
binNumber = ageCounter - IsisConstants.LSPREFRESH;
}
if (binNumber > IsisConstants.LSPMAXAGE) {
binNumber = binNumber - IsisConstants.LSPMAXAGE;
}
IsisLspBin lspBin = ageBins.get(binNumber);
if (lspBin == null) {
return;
}
Map lspBinMap = lspBin.listOfLsp();
for (Object key : lspBinMap.keySet()) {
LspWrapper lsp = (LspWrapper) lspBinMap.get((String) key);
try {
if (lsp.isSelfOriginated()) {
log.debug("Lsp picked for refreshLsp. binNumber: {}, LSA Type: {}, LSA Key: {}",
binNumber, lsp.lspType(), key);
lsp.setLspProcessing(IsisConstants.REFRESHLSP);
lsaQueue.put(lsp);
//remove from bin
lspBin.removeIsisLsp((String) key, lsp);
}
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::refreshLsp::{}", e.getMessage());
}
}
}
/**
* Runnable task which runs every second and calls aging process.
*/
private class InternalAgeTimer implements Runnable {
/**
* Creates an instance of age timer task.
*/
InternalAgeTimer() {
log.debug("Starts::IsisLsdbAge::AgeTimer...!!! ");
}
@Override
public void run() {
ageLsp();
}
}
}