ONOS-2740,ONOS-2741,from ONOS-3032 - to ONOS 3071 , OSPF Protocol Implementation

Change-Id: I8955ca10bf966c7b3917a3f3a41037abce87f1c5
This commit is contained in:
Kiran Ramachandra 2016-02-17 17:15:21 +05:30 committed by Thomas Vachuska
parent 3d94a6c502
commit e8699cd5d8
4 changed files with 1980 additions and 0 deletions

View File

@ -0,0 +1,185 @@
/*
* 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 org.jboss.netty.channel.Channel;
import org.onosproject.ospf.controller.LsaWrapper;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfLsaType;
import org.onosproject.ospf.controller.area.OspfAreaImpl;
import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
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.util.concurrent.BlockingQueue;
/**
* Consumes LSA from the Queue and processes it.
* Its a producer consumer implementation using Blocking queue.
*/
public class LsaQueueConsumer implements Runnable {
private static final Logger log = LoggerFactory.getLogger(LsaQueueConsumer.class);
private BlockingQueue queue = null;
private Channel channel;
private OspfArea ospfArea;
/**
* Creates an instance of LSA queue consumer.
*
* @param queue queue instance
* @param channel netty channel instance
* @param ospfArea OSPF area instance
*/
public LsaQueueConsumer(BlockingQueue queue, Channel channel, OspfArea ospfArea) {
this.queue = queue;
this.channel = channel;
this.ospfArea = ospfArea;
}
/**
* Threads run method.
*/
public void run() {
log.debug("LSAQueueConsumer:run...!!!");
try {
while (true) {
if (!queue.isEmpty()) {
LsaWrapper wrapper = (LsaWrapper) queue.take();
String lsaProcessing = wrapper.lsaProcessing();
switch (lsaProcessing) {
case OspfParameters.VERIFYCHECKSUM:
log.debug("LSAQueueConsumer: Message - " + OspfParameters.VERIFYCHECKSUM + " consumed.");
processVerifyChecksum(wrapper);
break;
case OspfParameters.REFRESHLSA:
log.debug("LSAQueueConsumer: Message - " + OspfParameters.REFRESHLSA + " consumed.");
processRefreshLsa(wrapper);
break;
case OspfParameters.MAXAGELSA:
log.debug("LSAQueueConsumer: Message - " + OspfParameters.MAXAGELSA + " consumed.");
processMaxAgeLsa(wrapper);
break;
default:
log.debug("Unknown command to process the LSA in queue ...!!!");
break;
}
}
}
} catch (Exception e) {
log.debug("Error::LSAQueueConsumer::{}", e.getMessage());
}
}
/**
* Processes verify checksum - checkAges.
*
* @param wrapper LSA wrapper instance
*/
private void processVerifyChecksum(LsaWrapper wrapper) throws Exception {
ChecksumCalculator checkSum = new ChecksumCalculator();
if (!checkSum.isValidLsaCheckSum(wrapper.ospfLsa(), ((LsaWrapperImpl) wrapper).lsaHeader().lsType(),
OspfUtil.LSAPACKET_CHECKSUM_POS1,
OspfUtil.LSAPACKET_CHECKSUM_POS2)) {
log.debug("LSAQueueConsumer::Checksum mismatch. Received LSA packet type {} ",
((LsaWrapperImpl) wrapper).lsaHeader().lsType());
//Checksum Invalid
//RFC 2328 Restart the Router.
//Currently we are not restarting. We are not handling this case.
}
}
/**
* Process refresh LSA.
*
* @param wrapper LSA wrapper instance
*/
private void processRefreshLsa(LsaWrapper wrapper) throws Exception {
if (wrapper.isSelfOriginated()) { //self originated
//set the destination
OspfInterface ospfInterface = wrapper.ospfInterface();
if (ospfInterface != null) {
LsaHeader header = ((LsaWrapperImpl) wrapper).lsaHeader();
header.setAge(wrapper.currentAge());
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR) {
if (header.lsType() == OspfLsaType.ROUTER.value()) {
RouterLsa routerLsa = ((OspfAreaImpl) ospfArea).buildRouterLsa(ospfInterface);
((OspfAreaImpl) ospfArea).addLsa(routerLsa, true, ospfInterface);
((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(routerLsa);
} else if (header.lsType() == OspfLsaType.NETWORK.value()) {
if (ospfInterface.listOfNeighbors().size() > 0) {
NetworkLsa networkLsa = ((OspfAreaImpl) ospfArea).buildNetworkLsa(
ospfInterface.ipAddress(), ospfInterface.ipNetworkMask());
ospfArea.addLsa(networkLsa, true, ospfInterface);
((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(networkLsa);
}
}
}
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
ospfArea.refreshArea(ospfInterface);
}
log.debug("LSAQueueConsumer: processRefreshLsa - Flooded SelfOriginated LSA {}",
((LsaWrapperImpl) wrapper).lsaHeader());
}
}
}
/**
* Process max age LSA.
*
* @param wrapper LSA wrapper instance
*/
private void processMaxAgeLsa(LsaWrapper wrapper) {
//set the destination
OspfInterface ospfInterface = wrapper.ospfInterface();
if (ospfInterface != null) {
LsaHeader header = (LsaHeader) wrapper.ospfLsa().lsaHeader();
header.setAge(OspfParameters.MAXAGE);
((LsaWrapperImpl) wrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
//remove from db
((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(((LsaWrapperImpl) wrapper).lsaHeader());
((OspfAreaImpl) ospfArea).deleteLsa(((LsaWrapperImpl) wrapper).lsaHeader());
} else {
((OspfAreaImpl) ospfArea).deleteLsa(((LsaWrapperImpl) wrapper).lsaHeader());
}
log.debug("LSAQueueConsumer: processMaxAgeLsa - Flooded SelfOriginated-Max Age LSA {}",
((LsaWrapperImpl) wrapper).lsaHeader());
}
}
/**
* Sets the channel.
*
* @param channel channel instance
*/
public void setChannel(Channel channel) {
this.channel = channel;
}
}

View File

@ -0,0 +1,375 @@
/*
* 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.jboss.netty.channel.Channel;
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.area.OspfAreaImpl;
import org.onosproject.ospf.protocol.util.OspfParameters;
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 LSDB Aging process.
*/
public class LsdbAgeImpl implements LsdbAge {
private static final Logger log =
LoggerFactory.getLogger(LsdbAgeImpl.class);
protected int ageCounter = 0;
private InternalAgeTimer dbAgeTimer;
private ScheduledExecutorService exServiceage;
// creating age bins of MAXAGE
private Map<Integer, LsaBin> ageBins = new ConcurrentHashMap<>(OspfParameters.MAXAGE);
private LsaBin maxAgeBin = new LsaBinImpl(OspfParameters.MAXAGE);
private int ageCounterRollOver = 0;
private Channel channel = null;
private LsaQueueConsumer queueConsumer = null;
private BlockingQueue<LsaWrapper> lsaQueue = new ArrayBlockingQueue(1024);
private OspfArea ospfArea = null;
/**
* Creates an instance of LSDB age.
*
* @param ospfArea OSPF area instance
*/
public LsdbAgeImpl(OspfArea ospfArea) {
// create LSBin's in the HashMap.
for (int i = 0; i < OspfParameters.MAXAGE; i++) {
LsaBin lsaBin = new LsaBinImpl(i);
ageBins.put(i, lsaBin);
}
this.ospfArea = ospfArea;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LsdbAgeImpl that = (LsdbAgeImpl) o;
return Objects.equal(ageBins, that.ageBins) &&
Objects.equal(ageCounter, that.ageCounter) &&
Objects.equal(ageCounterRollOver, that.ageCounterRollOver) &&
Objects.equal(lsaQueue, lsaQueue);
}
@Override
public int hashCode() {
return Objects.hashCode(ageBins, ageCounter, ageCounterRollOver, lsaQueue);
}
/**
* Adds LSA to bin.
*
* @param binKey key to store in bin
* @param lsaBin LSA bin instance
*/
public void addLsaBin(Integer binKey, LsaBin lsaBin) {
if (!ageBins.containsKey(binKey)) {
ageBins.put(binKey, lsaBin);
}
}
/**
* Gets LSA from Bin.
*
* @param binKey key
* @return bin instance
*/
public LsaBin getLsaBin(Integer binKey) {
return ageBins.get(binKey);
}
/**
* Adds the LSA to maxAge bin.
*
* @param key key
* @param wrapper wrapper instance
*/
public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
maxAgeBin.addOspfLsa(key, wrapper);
}
/**
* Removes LSA from Bin.
*
* @param lsaWrapper wrapper instance
*/
public void removeLsaFromBin(LsaWrapper lsaWrapper) {
if (ageBins.containsKey(lsaWrapper.binNumber())) {
LsaBin lsaBin = ageBins.get(lsaWrapper.binNumber());
lsaBin.removeOspfLsa(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
lsaWrapper).lsaHeader()), lsaWrapper);
}
}
/**
* Starts the aging timer and queue consumer.
*/
public void startDbAging() {
startDbAgeTimer();
queueConsumer = new LsaQueueConsumer(lsaQueue, channel, ospfArea);
new Thread(queueConsumer).start();
}
/**
* Gets called every 1 second as part of the timer.
*/
public void ageLsaAndFlood() {
//every 5 mins checksum validation
checkAges();
//every 30 mins - flood LSA
refreshLsa();
//every 60 mins - flood LSA
maxAgeLsa();
if (ageCounter == OspfParameters.MAXAGE) {
ageCounter = 0;
ageCounterRollOver++;
} else {
//increment age bin
ageCounter++;
}
}
/**
* If the LSA have completed the MaxAge - they are moved called stop aging and flooded.
*/
public void maxAgeLsa() {
if (ageCounter == 0) {
return;
}
//Get from Age Bins
LsaBin lsaBin = ageBins.get(ageCounter - 1);
if (lsaBin == null) {
return;
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
if (lsa.currentAge() == OspfParameters.MAXAGE) {
lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
log.debug("Lsa picked for maxage flooding. Age Counter: {}, AgeCounterRollover: {}, " +
"AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
ageCounter, ageCounterRollOver, lsa.currentAge(), lsa.lsaType(), key);
//add it to lsaQueue for processing
try {
lsaQueue.put(lsa);
//remove from bin
lsaBin.removeOspfLsa((String) key, lsa);
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
}
}
}
//Get from maxAgeBin
Map lsaMaxAgeBinMap = maxAgeBin.listOfLsa();
for (Object key : lsaMaxAgeBinMap.keySet()) {
LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get((String) key);
lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
log.debug("Lsa picked for maxage flooding. Age Counter: {}, LSA Type: {}, LSA Key: {}",
ageCounter, lsa.lsaType(), key);
//add it to lsaQueue for processing
try {
lsaQueue.put(lsa);
//remove from bin
maxAgeBin.removeOspfLsa((String) key, lsa);
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
}
}
}
/*
* If the LSA is in age bin of 1800 - it's pushed into refresh list.
*/
public void refreshLsa() {
int binNumber;
if (ageCounter < OspfParameters.LSREFRESHTIME) {
binNumber = ageCounter + OspfParameters.LSREFRESHTIME;
} else {
binNumber = ageCounter - OspfParameters.LSREFRESHTIME;
}
LsaBin lsaBin = ageBins.get(binNumber);
if (lsaBin == null) {
return;
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
try {
if (lsa.isSelfOriginated()) {
log.debug("Lsa picked for refreshLsa. binNumber: {}, LSA Type: {}, LSA Key: {}",
binNumber, lsa.lsaType(), key);
lsa.setLsaProcessing(OspfParameters.REFRESHLSA);
lsaQueue.put(lsa);
//remove from bin
lsaBin.removeOspfLsa((String) key, lsa);
}
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::refreshLsa::{}", e.getMessage());
}
}
}
/**
* Verify the checksum for the LSAs who are in bins of 300 and it's multiples.
*/
public void checkAges() {
//evry 5 min age counter + multiples of 300
for (int age = OspfParameters.CHECKAGE; age < OspfParameters.MAXAGE;
age += OspfParameters.CHECKAGE) {
LsaBin lsaBin = ageBins.get(age2Bin(age));
if (lsaBin == null) {
continue;
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
lsa.setLsaProcessing(OspfParameters.VERIFYCHECKSUM);
try {
lsaQueue.put(lsa);
} catch (InterruptedException e) {
log.debug("Error::LSDBAge::checkAges::{}", e.getMessage());
}
}
}
}
/**
* Starts DB age timer method start the aging task.
*/
private void startDbAgeTimer() {
log.debug("OSPFNbr::startWaitTimer");
dbAgeTimer = new InternalAgeTimer();
//from 1 sec
exServiceage = Executors.newSingleThreadScheduledExecutor();
exServiceage.scheduleAtFixedRate(dbAgeTimer, OspfParameters.AGECOUNTER,
OspfParameters.AGECOUNTER, TimeUnit.SECONDS);
}
/**
* Stops the aging task.
*/
private void stopDbAgeTimer() {
log.debug("OSPFNbr::stopWaitTimer ");
exServiceage.shutdown();
}
/**
* Gets the netty channel.
*
* @return netty channel
*/
public Channel getChannel() {
return channel;
}
/**
* Sets the netty channel.
*
* @param channel netty channel
*/
public void setChannel(Channel channel) {
this.channel = channel;
if (queueConsumer != null) {
queueConsumer.setChannel(channel);
}
}
/**
* Gets the age counter.
*
* @return ageCounter
*/
public int getAgeCounter() {
return ageCounter;
}
/**
* Gets the age counter roll over value.
*
* @return the age counter roll over value
*/
public int getAgeCounterRollOver() {
return ageCounterRollOver;
}
/**
* Gets the max age bin.
*
* @return lsa bin instance
*/
public LsaBin getMaxAgeBin() {
return maxAgeBin;
}
/**
* Gets the bin number.
*
* @param x Can be either age or ageCounter
* @return bin number.
*/
public int age2Bin(int x) {
if (x <= ageCounter) {
return (ageCounter - x);
} else {
return ((OspfParameters.MAXAGE - 1) + (ageCounter - x));
}
}
/**
* Runnable task which runs every second and calls aging process.
*/
private class InternalAgeTimer implements Runnable {
/**
* Constructor.
*/
InternalAgeTimer() {
log.debug("Starts::LsdbAge::AgeTimer...!!! ");
}
@Override
public void run() {
ageLsaAndFlood();
}
}
}

View File

@ -0,0 +1,20 @@
/*
* 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.
*/
/**
* Implementation of the OSPF controller.
*/
package org.onosproject.ospf.controller;