Kiran Ramachandra
Committed by Thomas Vachuska

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

Change-Id: I8955ca10bf966c7b3917a3f3a41037abce87f1c5
/*
* 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.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.ReadTimeoutException;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.controller.LsaWrapper;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfLinkTed;
import org.onosproject.ospf.controller.OspfLsa;
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.lsdb.OspfLsdbImpl;
import org.onosproject.ospf.controller.util.OspfEligibleRouter;
import org.onosproject.ospf.controller.util.OspfInterfaceType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
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.HelloPacket;
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.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Channel handler deals with the OSPF channel connection.
* Also it dispatches messages to the appropriate handlers.
*/
public class OspfInterfaceChannelHandler extends IdleStateAwareChannelHandler {
private static final Logger log =
LoggerFactory.getLogger(OspfInterfaceChannelHandler.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private OspfInterface ospfInterface;
private OspfArea ospfArea;
private boolean isClosed = false;
private Controller controller;
private Channel channel;
private long delay = 0;
private InternalHelloTimer helloTimerTask;
private InternalWaitTimer waitTimerTask;
private InternalDelayedAckTimer delayedAckTimerTask;
private ScheduledExecutorService exServiceHello;
private ScheduledExecutorService exServiceWait;
private ScheduledExecutorService exServiceDelayedAck;
private boolean isDelayedAckTimerScheduled = false;
private int delayedAckTimerInterval = 2500;
private TopologyForDeviceAndLink topologyForDeviceAndLink;
public OspfInterfaceChannelHandler() {
}
/**
* Creates an instance of OSPF channel handler.
*
* @param controller controller instance
* @param ospfArea ospf area instance
* @param ospfInterface ospf interface instance
*/
public OspfInterfaceChannelHandler(Controller controller, OspfArea ospfArea, OspfInterface ospfInterface) {
this.ospfArea = ospfArea;
this.ospfInterface = ospfInterface;
this.controller = controller;
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
this.ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
this.ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
this.topologyForDeviceAndLink = new TopologyForDeviceAndLinkImpl();
}
/**
* Represents an interface is up and connected.
*
* @throws Exception might throws exception
*/
public void interfaceUp() throws Exception {
log.debug("OSPFInterfaceChannelHandler::interfaceUp...!!!");
if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.POINT2POINT);
log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} ",
ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());
} else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
//if router priority is 0, move the state to DROther
if (ospfInterface.routerPriority() == 0) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
} else {
log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} RouterPriority {}",
ospfInterface.interfaceType(),
((OspfInterfaceImpl) ospfInterface).state(), ospfInterface.routerPriority());
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.WAITING);
//start wait timer - like inactivity timer with router deadInterval
startWaitTimer();
}
}
// Start hello timer with interval from config - convert seconds to milliseconds
startHelloTimer(ospfInterface.helloIntervalTime());
ospfArea.refreshArea(ospfInterface);
}
/**
* Gets called when a BDR was detected before the wait timer expired.
*
* @param ch channel instance
* @throws Exception might throws exception
*/
public void backupSeen(Channel ch) throws Exception {
log.debug("OSPFInterfaceChannelHandler::backupSeen ");
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
electRouter(ch);
}
}
/**
* Gets called when no hello message received for particular period.
*
* @param ch channel instance
* @throws Exception might throws exception
*/
public void waitTimer(Channel ch) throws Exception {
log.debug("OSPFInterfaceChannelHandler::waitTimer ");
//section 9.4
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
electRouter(ch);
}
}
/**
* Neighbor change event is triggered when the router priority gets changed.
*
* @throws Exception might throws exception
*/
public void neighborChange() throws Exception {
log.debug("OSPFInterfaceChannelHandler::neighborChange ");
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
electRouter(channel);
}
}
/**
* Gets called when an interface is down.
* All interface variables are reset, and interface timers disabled.
* Also all neighbor connections associated with the interface are destroyed.
*/
public void interfaceDown() {
log.debug("OSPFInterfaceChannelHandler::interfaceDown ");
stopHelloTimer();
ospfInterface.listOfNeighbors().clear();
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) throws Exception {
log.info("OSPF channelConnected from {}", evt.getChannel().getRemoteAddress());
channel = evt.getChannel();
interfaceUp();
startDelayedAckTimer();
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
interfaceDown();
stopDelayedAckTimer();
log.debug("OspfChannelHandler::channelDisconnected...!!!");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
log.info("[exceptionCaught]: " + e.toString());
if (e.getCause() instanceof ReadTimeoutException) {
// device timeout
log.error("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress());
return;
} else if (e.getCause() instanceof ClosedChannelException) {
log.debug("Channel for OSPF {} already closed", e.getChannel().getRemoteAddress());
} else if (e.getCause() instanceof IOException) {
log.error("Disconnecting OSPF {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
e.getCause().getMessage());
if (log.isDebugEnabled()) {
log.debug("StackTrace for previous Exception: {}", e.getCause());
}
} else if (e.getCause() instanceof OspfParseException) {
OspfParseException errMsg = (OspfParseException) e.getCause();
byte errorCode = errMsg.errorCode();
byte errorSubCode = errMsg.errorSubCode();
log.error("Error while parsing message from OSPF {}, ErrorCode {}",
e.getChannel().getRemoteAddress(), errorCode);
} else if (e.getCause() instanceof RejectedExecutionException) {
log.warn("Could not process message: queue full");
} else {
log.error("Error while processing message from OSPF {}, state {}",
e.getChannel().getRemoteAddress(), ((OspfInterfaceImpl) ospfInterface).state());
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
log.debug("OspfChannelHandler::messageReceived...!!!");
Object message = e.getMessage();
if (message instanceof List) {
List<OspfMessage> ospfMessageList = (List<OspfMessage>) message;
log.debug("OspfChannelHandler::List of OspfMessages Size {}", ospfMessageList.size());
if (ospfMessageList != null) {
for (OspfMessage ospfMessage : ospfMessageList) {
processOSPFMessage(ospfMessage, ctx);
}
} else {
log.debug("OspfChannelHandler::OspfMessages Null List...!!");
}
}
if (message instanceof OspfMessage) {
OspfMessage ospfMessage = (OspfMessage) message;
log.debug("OspfChannelHandler::OspfMessages received...!!");
processOSPFMessage(ospfMessage, ctx);
}
}
/**
* When an OSPF message received it is handed over to this method.
* Based on the type of the OSPF message received it will be handed over
* to corresponding message handler methods.
*
* @param ospfMessage received OSPF message
* @param ctx channel handler context instance.
* @throws Exception might throws exception
*/
public void processOSPFMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processOSPFMessage...!!!");
if (!validateMessage(ospfMessage)) {
return;
}
switch (ospfMessage.ospfMessageType().value()) {
case OspfParameters.HELLO:
processHelloMessage(ospfMessage, ctx);
break;
case OspfParameters.DD:
processDdMessage(ospfMessage, ctx);
break;
case OspfParameters.LSREQUEST:
processLsRequestMessage(ospfMessage, ctx);
break;
case OspfParameters.LSUPDATE:
processLsUpdateMessage(ospfMessage, ctx);
break;
case OspfParameters.LSACK:
processLsAckMessage(ospfMessage, ctx);
break;
default:
log.debug("Unknown packet to process...!!!");
break;
}
}
/**
* Validates the OSPF message received.
*
* @param ospfMessage OSPF message.
* @return true if it is a valid else false.
* @throws Exception might throws exception
*/
private boolean validateMessage(OspfMessage ospfMessage) throws Exception {
boolean isValid = true;
OspfPacketHeader header = (OspfPacketHeader) ospfMessage;
//added the check to eliminate self origin packets also two interfaces on same router.
if (!header.sourceIp().equals(ospfInterface.ipAddress()) && !header.routerId().equals(
ospfArea.routerId())) {
//Verify the checksum
ChecksumCalculator checksum = new ChecksumCalculator();
if (!checksum.isValidOspfCheckSum(ospfMessage, OspfUtil.OSPFPACKET_CHECKSUM_POS1,
OspfUtil.OSPFPACKET_CHECKSUM_POS2)) {
log.debug("Checksum mismatch. Received packet type {} ", ospfMessage.ospfMessageType());
return false;
}
if (((OspfPacketHeader) ospfMessage).ospfVersion() != OspfUtil.OSPF_VERSION_2) {
log.debug("Received osfpMessage Version should match with Interface Version ");
return false;
}
if (!((OspfPacketHeader) ospfMessage).areaId().equals(ospfArea.areaId())) {
log.debug("Received ospf packets are from different area than our Area ID. " +
"Received Area ID {}, Our AreaId {} ",
((OspfPacketHeader) ospfMessage).areaId(), ospfArea.areaId());
return false;
}
//According to RFC-2328 (8.2)
/**
* ABR should receive packets from backbone 0.0.0.0 as we are not acting as ABR
* we are rejecting the packet.
*/
if (((OspfPacketHeader) ospfMessage).areaId().equals(Ip4Address.valueOf("0.0.0.0"))) {
log.debug("ABR should receive packets from backbone 0.0.0.0 as we are not acting as " +
"ABR we are rejecting the ospf packet");
return false;
}
if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value() &&
!OspfUtil.sameNetwork(((OspfPacketHeader) ospfMessage).sourceIp(),
ospfInterface.ipAddress(), ospfInterface.ipNetworkMask())) {
log.debug("Received packets from different subnets. Discarding...!!!");
return false;
}
} else {
isValid = false;
}
return isValid;
}
/**
* Processes Hello message.
*
* @param ospfMessage OSPF message instance.
* @param ctx context instance.
* @throws Exception might throws exception
*/
void processHelloMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processHelloMessage...!!!");
HelloPacket helloPacket = (HelloPacket) ospfMessage;
// processing of hello packet as per RFC 2328 section 10.5
log.debug("OspfChannelHandler::processHelloMessage::Interface Type {} OSPFInterfaceState {} ",
ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());
if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
if (!helloPacket.networkMask().equals(ospfInterface.ipNetworkMask())) {
log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received does not " +
"match the same network mask as the configure Interface");
return;
}
}
if (helloPacket.helloInterval() != ospfInterface.helloIntervalTime()) {
log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
"hello interval as configured Interface");
return;
}
if (helloPacket.routerDeadInterval() != ospfInterface.routerDeadIntervalTime()) {
log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
"Router Dead interval as configured Interface");
return;
}
if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
// to verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
OspfNbr nbr;
if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
nbr = new OspfNbrImpl(ospfArea, ospfInterface, helloPacket.sourceIp(),
helloPacket.routerId(), helloPacket.options(), this, topologyForDeviceAndLink);
ospfInterface.addNeighbouringRouter(nbr);
} else {
nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
nbr.setRouterPriority(helloPacket.routerPriority());
}
if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
} else {
((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
}
} else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0"))) &&
(!helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))) {
stopWaitTimer();
ospfInterface.setDr(helloPacket.dr());
ospfInterface.setBdr(helloPacket.bdr());
if (helloPacket.dr().equals(ospfInterface.ipAddress())) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
//refresh router Lsa
ospfArea.refreshArea(ospfInterface);
} else if (helloPacket.bdr().equals(ospfInterface.ipAddress())) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
//refresh router Lsa
ospfArea.refreshArea(ospfInterface);
} else {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
ospfArea.refreshArea(ospfInterface);
}
} else if (!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
!helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
ospfInterface.setDr(helloPacket.dr());
ospfInterface.setBdr(helloPacket.bdr());
}
Ip4Address sourceIp = helloPacket.sourceIp();
OspfNbr nbr;
if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
helloPacket.options(), this, topologyForDeviceAndLink);
nbr.setNeighborId(helloPacket.routerId());
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
nbr.setRouterPriority(helloPacket.routerPriority());
ospfInterface.addNeighbouringRouter(nbr);
} else {
nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
nbr.setRouterPriority(helloPacket.routerPriority());
}
if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
} else {
((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
}
if (helloPacket.dr().equals(sourceIp)) {
if (helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
// call backup seen
stopWaitTimer();
backupSeen(ctx.getChannel());
}
}
if (helloPacket.bdr().equals(sourceIp)) {
// call backup seen
stopWaitTimer();
backupSeen(ctx.getChannel());
}
} else {
if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
!helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))
&& ospfInterface.routerPriority() == 0) {
ospfInterface.setDr(helloPacket.dr());
ospfInterface.setBdr(helloPacket.bdr());
}
//To verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
Ip4Address sourceIp = helloPacket.sourceIp();
OspfNbr nbr;
if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
helloPacket.options(), this, topologyForDeviceAndLink);
nbr.setNeighborId(helloPacket.routerId());
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
nbr.setRouterPriority(helloPacket.routerPriority());
ospfInterface.addNeighbouringRouter(nbr);
((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
} else {
log.debug("OspfChannelHandler::NeighborInList::helloPacket.bdr(): {}, " +
"helloPacket.dr(): {}", helloPacket.bdr(), helloPacket.dr());
nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
nbr.setRouterPriority(helloPacket.routerPriority());
if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
} else {
((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
}
if (nbr.routerPriority() != helloPacket.routerPriority()) {
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
neighborChange();
}
if (nbr.neighborIpAddr().equals(helloPacket.dr()) &&
!(nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
neighborChange();
}
if (!(nbr.neighborIpAddr().equals(helloPacket.dr())) &&
(nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
neighborChange();
}
if (nbr.neighborIpAddr().equals(helloPacket.bdr()) &&
!(nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
neighborChange();
}
if (!(nbr.neighborIpAddr().equals(helloPacket.bdr())) &&
(nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
neighborChange();
}
nbr.setNeighborBdr(helloPacket.bdr());
nbr.setNeighborDr(helloPacket.dr());
}
}
}
}
/**
* process the DD message which received.
*
* @param ospfMessage OSPF message instance.
* @param ctx channel handler context instance
* @throws Exception might throws exception
*/
void processDdMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processDdMessage...!!!");
DdPacket ddPacket = (DdPacket) ospfMessage;
log.debug("Got DD packet from {}", ddPacket.sourceIp());
//check it is present in listOfNeighbors
Ip4Address neighbourId = ddPacket.routerId();
OspfNbr nbr = ospfInterface.neighbouringRouter(neighbourId.toString());
if (nbr != null) {
log.debug("OspfChannelHandler::processDdMessage:: OSPFNeighborState {}", nbr.getState());
// set options for the NBR
nbr.setIsOpaqueCapable(ddPacket.isOpaqueCapable());
if (ddPacket.imtu() > ospfInterface.mtu()) {
log.debug("the MTU size is greater than the interface MTU");
return;
}
if (nbr.getState() == OspfNeighborState.DOWN) {
return;
}
if (nbr.getState() == OspfNeighborState.ATTEMPT) {
return;
}
if (nbr.getState() == OspfNeighborState.TWOWAY) {
nbr.adjOk(channel);
return;
}
//if init is the state call twoWayReceived
if (nbr.getState() == OspfNeighborState.INIT) {
((OspfNbrImpl) nbr).twoWayReceived(ddPacket, ctx.getChannel());
} else if (nbr.getState() == OspfNeighborState.EXSTART) {
//get I,M,MS Bits
int initialize = ddPacket.isInitialize();
int more = ddPacket.isMore();
int masterOrSlave = ddPacket.isMaster();
int options = ddPacket.options();
nbr.setOptions(options);
if (initialize == OspfUtil.INITIALIZE_SET && more == OspfUtil.MORE_SET &&
masterOrSlave == OspfUtil.IS_MASTER) {
if (ddPacket.getLsaHeaderList().isEmpty()) {
if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) >
OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
nbr.setIsMaster(OspfUtil.IS_MASTER);
((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
nbr.setDdSeqNum(ddPacket.sequenceNo());
nbr.setOptions(ddPacket.options());
((OspfNbrImpl) nbr).negotiationDone(ddPacket, true, ddPacket.getLsaHeaderList(),
ctx.getChannel());
}
}
}
if (initialize == OspfUtil.INITIALIZE_NOTSET && masterOrSlave == OspfUtil.NOT_MASTER) {
if (nbr.ddSeqNum() == ddPacket.sequenceNo()) {
if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) <
OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
nbr.setOptions(ddPacket.options());
nbr.setDdSeqNum(nbr.ddSeqNum() + 1);
((OspfNbrImpl) nbr).negotiationDone(ddPacket, false, ddPacket.getLsaHeaderList(),
ctx.getChannel());
}
}
}
} else if (nbr.getState() == OspfNeighborState.EXCHANGE) {
//get I,M,MS Bits
log.debug("Neighbor state:: EXCHANGE");
boolean isDuplicateDDPacket = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
int initialize = ddPacket.isInitialize();
int more = ddPacket.isMore();
int masterOrSlave = ddPacket.isMaster();
int options = ddPacket.options();
if (!isDuplicateDDPacket) {
//if dd packet is not duplicate then continue
if (nbr.isMaster() != masterOrSlave) {
DdPacket newResPacket =
(DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Master/Slave Inconsistency");
newResPacket.setDestinationIp(ddPacket.sourceIp());
log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
} else if (initialize == 1) {
DdPacket newResPacket =
(DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
newResPacket.setDestinationIp(ddPacket.sourceIp());
log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
} else {
if (masterOrSlave == OspfUtil.NOT_MASTER) {
if (ddPacket.sequenceNo() == nbr.ddSeqNum()) {
//Process the DD Packet
((OspfNbrImpl) nbr).processDdPacket(false, ddPacket, ctx.getChannel());
log.debug("Received DD Packet");
} else {
DdPacket newResPacket =
(DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Sequence Number Mismatch");
newResPacket.setDestinationIp(ddPacket.sourceIp());
log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
}
} else {
//we are the slave
if (ddPacket.sequenceNo() == (nbr.ddSeqNum() + 1)) {
((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
((OspfNbrImpl) nbr).processDdPacket(true, ddPacket, ctx.getChannel());
log.debug("Process DD Packet");
} else {
DdPacket newResPacket =
(DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("options inconsistency");
newResPacket.setDestinationIp(ddPacket.sourceIp());
log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
}
}
}
} else {
if (masterOrSlave == OspfUtil.NOT_MASTER) {
return;
} else {
DdPacket newResPacket = ((OspfNbrImpl) nbr).lastSentDdPacket();
log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
}
}
} else if (nbr.getState() == OspfNeighborState.LOADING || nbr.getState() == OspfNeighborState.FULL) {
//In case if we are slave then we have to send the last received DD Packet
int options = ddPacket.options();
if (nbr.options() != options) {
OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
newResPacket.setDestinationIp(ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
} else if (ddPacket.isInitialize() == OspfUtil.INITIALIZE_SET) {
OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
newResPacket.setDestinationIp(ddPacket.sourceIp());
ctx.getChannel().write(newResPacket);
}
boolean isDuplicate = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
//we are master
if (nbr.isMaster() != OspfUtil.IS_MASTER) {
// check if the packet is duplicate, duplicates should be discarded by the master
if (isDuplicate) {
log.debug("received a duplicate DD packet");
}
} else {
//The slave must respond to duplicates by repeating the last Database Description packet
//that it had sent.
if (isDuplicate) {
ddPacket.setDestinationIp(ddPacket.sourceIp());
ctx.getChannel().write(((OspfNbrImpl) nbr).lastSentDdPacket());
log.debug("Sending back the duplicate packet ");
}
}
}
}
}
/**
* Process the Ls Request message.
*
* @param ospfMessage OSPF message instance.
* @param ctx channel handler context instance.
* @throws Exception might throws exception
*/
void processLsRequestMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processLsRequestMessage...!!!");
LsRequest lsrPacket = (LsRequest) ospfMessage;
OspfNbr nbr = ospfInterface.neighbouringRouter(lsrPacket.routerId().toString());
if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING ||
nbr.getState() == OspfNeighborState.FULL) {
LsRequest reqMsg = (LsRequest) ospfMessage;
if (reqMsg.getLinkStateRequests().isEmpty()) {
log.debug("Received Link State Request Vector is Empty ");
return;
} else {
//Send the LsUpdate back
ListIterator<LsRequestPacket> listItr = reqMsg.getLinkStateRequests().listIterator();
while (listItr.hasNext()) {
LsUpdate lsupdate = new LsUpdate();
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 (listItr.hasNext()) {
LsRequestPacket lsRequest = (LsRequestPacket) listItr.next();
// to verify length of the LSA
LsaWrapper wrapper = ospfArea.getLsa(lsRequest.lsType(), lsRequest.linkStateId(),
lsRequest.ownRouterId());
OspfLsa ospflsa = wrapper.ospfLsa();
if ((currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen()) >= maxSize) {
listItr.previous();
break;
}
if (ospflsa != null) {
lsupdate.addLsa(ospflsa);
noLsa++;
currentLength = currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen();
} else {
nbr.badLSReq(channel);
}
}
lsupdate.setNumberOfLsa(noLsa);
//set the destination
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
} else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
lsupdate.setDestinationIp(OspfUtil.ALL_DROUTERS);
}
ctx.getChannel().write(lsupdate);
}
}
}
}
/**
* Process the ls update message.
*
* @param ospfMessage OSPF message instance.
* @param ctx channel handler context instance.
* @throws Exception might throws exception
*/
void processLsUpdateMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processLsUpdateMessage");
LsUpdate lsUpdate = (LsUpdate) ospfMessage;
String neighbourId = lsUpdate.routerId().toString();
//LSUpdate packet has been associated with a particular neighbor.
//Neighbor should not be in lesser state than Exchange.
if (ospfInterface.isNeighborInList(neighbourId)) {
OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(neighbourId);
if (nbr.getState() == OspfNeighborState.EXCHANGE ||
nbr.getState() == OspfNeighborState.LOADING) {
nbr.processLsUpdate(lsUpdate, ctx.getChannel());
} else if (nbr.getState() == OspfNeighborState.FULL) {
if (lsUpdate.noLsa() != 0) {
List<OspfLsa> list = lsUpdate.getLsaList();
Iterator itr = list.iterator();
while (itr.hasNext()) {
LsaHeader lsa = (LsaHeader) itr.next();
nbr.processReceivedLsa(lsa, true, ctx.getChannel(), lsUpdate.sourceIp());
}
} else {
return;
}
}
}
}
/**
* Process the ls acknowledge message.
*
* @param ospfMessage OSPF message instance.
* @param ctx channel handler context instance.
* @throws Exception might throws exception
*/
void processLsAckMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processLsAckMessage");
LsAcknowledge lsAckPacket = (LsAcknowledge) ospfMessage;
//check it is present in listOfNeighbors
OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(lsAckPacket.routerId().toString());
if (nbr != null) {
if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
// discard the packet.
return;
} else {
// process ls acknowledgements
Iterator itr = lsAckPacket.getLinkStateHeaders().iterator();
while (itr.hasNext()) {
LsaHeader lsRequest = (LsaHeader) itr.next();
OspfLsa ospfLsa =
(OspfLsa) nbr.getPendingReTxList().get(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
if (lsRequest != null && ospfLsa != null) {
String isSame = ((OspfLsdbImpl) ospfArea.database()).isNewerOrSameLsa(
lsRequest, (LsaHeader) ospfLsa);
if (isSame.equals("same")) {
nbr.getPendingReTxList().remove(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
}
}
}
}
}
}
/**
* Compares two Dd Packets to check whether its duplicate or not.
*
* @param receivedDPacket received DD packet from network.
* @param lastDdPacket Last DdPacket which we sent.
* @return true if it is a duplicate packet else false.
*/
public boolean compareDdPackets(DdPacket receivedDPacket, DdPacket lastDdPacket) {
if (receivedDPacket.isInitialize() == lastDdPacket.isInitialize()) {
if (receivedDPacket.isMaster() == lastDdPacket.isMaster()) {
if (receivedDPacket.isMore() == lastDdPacket.isMore()) {
if (receivedDPacket.options() == lastDdPacket.options()) {
if (receivedDPacket.sequenceNo() == lastDdPacket.sequenceNo()) {
return true;
}
}
}
}
}
return false;
}
/**
* Closes the Netty channel.
*
* @param ctx the Channel Handler Context
*/
void closeChannel(ChannelHandlerContext ctx) {
log.debug("OspfChannelHandler::closeChannel");
isClosed = true;
ctx.getChannel().close();
}
/**
* Starts the hello timer which sends hello packet every configured seconds.
*
* @param period the interval to run task
*/
private void startHelloTimer(long period) {
log.debug("OSPFInterfaceChannelHandler::startHelloTimer");
exServiceHello = Executors.newSingleThreadScheduledExecutor();
helloTimerTask = new InternalHelloTimer();
final ScheduledFuture<?> helloHandle =
exServiceHello.scheduleAtFixedRate(helloTimerTask, delay, period, TimeUnit.SECONDS);
}
/**
* Stops the hello timer.
*/
private void stopHelloTimer() {
log.debug("OSPFInterfaceChannelHandler::stopHelloTimer ");
exServiceHello.shutdown();
}
/**
* Starts the wait timer.
*/
private void startWaitTimer() {
log.debug("OSPFNbr::startWaitTimer");
exServiceWait = Executors.newSingleThreadScheduledExecutor();
waitTimerTask = new InternalWaitTimer();
final ScheduledFuture<?> waitTimerHandle =
exServiceWait.schedule(waitTimerTask, ospfInterface.routerDeadIntervalTime(),
TimeUnit.SECONDS);
}
/**
* Stops the wait timer.
*/
private void stopWaitTimer() {
log.debug("OSPFNbr::stopWaitTimer ");
exServiceWait.shutdown();
}
/**
* Starts the timer which waits for configured seconds and sends Delayed Ack Packet.
*/
private void startDelayedAckTimer() {
if (!isDelayedAckTimerScheduled) {
log.debug("Started DelayedAckTimer...!!!");
exServiceDelayedAck = Executors.newSingleThreadScheduledExecutor();
delayedAckTimerTask = new InternalDelayedAckTimer();
final ScheduledFuture<?> delayAckHandle =
exServiceDelayedAck.scheduleAtFixedRate(delayedAckTimerTask, delayedAckTimerInterval,
delayedAckTimerInterval, TimeUnit.MILLISECONDS);
isDelayedAckTimerScheduled = true;
}
}
/**
* Stops the delayed acknowledge timer.
*/
private void stopDelayedAckTimer() {
if (isDelayedAckTimerScheduled) {
log.debug("Stopped DelayedAckTimer...!!!");
isDelayedAckTimerScheduled = false;
exServiceDelayedAck.shutdown();
}
}
/**
* Performs DR election.
*
* @param ch Netty Channel instance.
* @throws Exception might throws exception
*/
public void electRouter(Channel ch) throws Exception {
Ip4Address currentDr = ospfInterface.dr();
Ip4Address currentBdr = ospfInterface.bdr();
OspfInterfaceState oldState = ((OspfInterfaceImpl) ospfInterface).state();
OspfInterfaceState newState;
log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
currentDr, currentBdr);
List<OspfEligibleRouter> eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());
log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
OspfEligibleRouter electedBdr = electBdr(eligibleRouters);
OspfEligibleRouter electedDr = electDr(eligibleRouters, electedBdr);
ospfInterface.setBdr(electedBdr.getIpAddress());
ospfInterface.setDr(electedDr.getIpAddress());
if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
!electedBdr.getIpAddress().equals(currentBdr)) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
}
if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
!electedDr.getIpAddress().equals(currentDr)) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
}
if (((OspfInterfaceImpl) ospfInterface).state() != oldState &&
!(((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER &&
oldState.value() < OspfInterfaceState.DROTHER.value())) {
log.debug("Recalculating as the State is changed ");
log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
currentDr, currentBdr);
eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());
log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
electedBdr = electBdr(eligibleRouters);
electedDr = electDr(eligibleRouters, electedBdr);
ospfInterface.setBdr(electedBdr.getIpAddress());
ospfInterface.setDr(electedDr.getIpAddress());
}
if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
!electedBdr.getIpAddress().equals(currentBdr)) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
ospfArea.refreshArea(ospfInterface);
}
if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
!electedDr.getIpAddress().equals(currentDr)) {
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
//Refresh Router Lsa & Network Lsa
ospfArea.refreshArea(ospfInterface);
}
if (currentDr != electedDr.getIpAddress() || currentBdr != electedBdr.getIpAddress()) {
Set<String> negibhorIdList;
negibhorIdList = ospfInterface.listOfNeighbors().keySet();
for (String routerid : negibhorIdList) {
OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerid);
if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue()) {
nbr.adjOk(ch);
}
}
}
log.debug("OSPFInterfaceChannelHandler::electRouter -> ElectedDR: {}, ElectedBDR: {}",
electedDr.getIpAddress(), electedBdr.getIpAddress());
}
/**
* BDR Election process. Find the list of eligible router to participate in the process.
*
* @param electedDr router elected as DR.
* @return list of eligible routers
*/
public List<OspfEligibleRouter> calculateListOfEligibleRouters(OspfEligibleRouter electedDr) {
log.debug("OSPFNbr::calculateListOfEligibleRouters ");
Set<String> neighborIdList;
List<OspfEligibleRouter> eligibleRouters = new ArrayList<>();
neighborIdList = ospfInterface.listOfNeighbors().keySet();
for (String routerId : neighborIdList) {
OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerId);
if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue() &&
nbr.routerPriority() > 0) {
OspfEligibleRouter router = new OspfEligibleRouter();
router.setIpAddress(nbr.neighborIpAddr());
router.setRouterId(nbr.neighborId());
router.setRouterPriority(nbr.routerPriority());
if (nbr.neighborDr().equals(nbr.neighborIpAddr()) ||
electedDr.getIpAddress().equals(nbr.neighborIpAddr())) {
router.setIsDr(true);
} else if (nbr.neighborBdr().equals(nbr.neighborIpAddr())) {
router.setIsBdr(true);
}
eligibleRouters.add(router);
}
}
// interface does not have states like two and all
if (ospfInterface.routerPriority() > 0) {
OspfEligibleRouter router = new OspfEligibleRouter();
router.setIpAddress(ospfInterface.ipAddress());
router.setRouterId(ospfArea.routerId());
router.setRouterPriority(ospfInterface.routerPriority());
if (ospfInterface.dr().equals(ospfInterface.ipAddress()) ||
electedDr.getIpAddress().equals(ospfInterface.ipAddress())) {
router.setIsDr(true);
} else if (ospfInterface.bdr().equals(ospfInterface.ipAddress()) &&
!ospfInterface.dr().equals(ospfInterface.ipAddress())) {
router.setIsBdr(true);
}
eligibleRouters.add(router);
}
return eligibleRouters;
}
/**
* Based on router priority assigns BDR.
*
* @param eligibleRouters list of routers to participate in bdr election.
* @return OSPF Eligible router instance.
*/
public OspfEligibleRouter electBdr(List<OspfEligibleRouter> eligibleRouters) {
log.debug("OSPFInterfaceChannelHandler::electBdr -> eligibleRouters: {}", eligibleRouters);
List<OspfEligibleRouter> declaredAsBdr = new ArrayList<>();
List<OspfEligibleRouter> notDrAndBdr = new ArrayList<>();
for (OspfEligibleRouter router : eligibleRouters) {
if (router.isBdr()) {
declaredAsBdr.add(router);
}
if (!router.isBdr() && !router.isDr()) {
notDrAndBdr.add(router);
}
}
OspfEligibleRouter electedBdr = new OspfEligibleRouter();
if (!declaredAsBdr.isEmpty()) {
if (declaredAsBdr.size() == 1) {
electedBdr = declaredAsBdr.get(0);
} else if (declaredAsBdr.size() > 1) {
electedBdr = selectRouterBasedOnPriority(declaredAsBdr);
}
} else {
if (notDrAndBdr.size() == 1) {
electedBdr = notDrAndBdr.get(0);
} else if (notDrAndBdr.size() > 1) {
electedBdr = selectRouterBasedOnPriority(notDrAndBdr);
}
}
electedBdr.setIsBdr(true);
electedBdr.setIsDr(false);
return electedBdr;
}
/**
* DR Election process.
*
* @param eligibleRouters list of eligible routers.
* @param electedBdr Elected Bdr, OSPF eligible router instance.
* @return OSPF eligible router instance.
*/
public OspfEligibleRouter electDr(List<OspfEligibleRouter> eligibleRouters,
OspfEligibleRouter electedBdr) {
List<OspfEligibleRouter> declaredAsDr = new ArrayList<>();
for (OspfEligibleRouter router : eligibleRouters) {
if (router.isDr()) {
declaredAsDr.add(router);
}
}
OspfEligibleRouter electedDr = new OspfEligibleRouter();
if (!declaredAsDr.isEmpty()) {
if (declaredAsDr.size() == 1) {
electedDr = declaredAsDr.get(0);
} else if (eligibleRouters.size() > 1) {
electedDr = selectRouterBasedOnPriority(declaredAsDr);
}
} else {
electedDr = electedBdr;
electedDr.setIsDr(true);
electedDr.setIsBdr(false);
}
return electedDr;
}
/**
* DR election process.
*
* @param routersList list of eligible routers.
* @return OSPF eligible router instance.
*/
public OspfEligibleRouter selectRouterBasedOnPriority(List<OspfEligibleRouter> routersList) {
OspfEligibleRouter initialRouter = routersList.get(0);
for (int i = 1; i < routersList.size(); i++) {
OspfEligibleRouter router = routersList.get(i);
if (router.getRouterPriority() > initialRouter.getRouterPriority()) {
initialRouter = router;
} else if (router.getRouterPriority() == initialRouter.getRouterPriority()) {
try {
//if (router.getIpAddress().toInt() > initialRouter.getIpAddress().toInt()) {
if (OspfUtil.ipAddressToLong(router.getIpAddress().toString()) >
OspfUtil.ipAddressToLong(initialRouter.getIpAddress().toString())) {
initialRouter = router;
}
} catch (Exception e) {
log.debug("OSPFInterfaceChannelHandler::selectRouterBasedOnPriority ->" +
" eligibleRouters: {}", initialRouter);
}
}
}
return initialRouter;
}
/**
* Adds device information.
*
* @param ospfRouter OSPF router instance
*/
public void addDeviceInformation(OspfRouter ospfRouter) {
controller.addDeviceDetails(ospfRouter);
}
/**
* removes device information.
*
* @param ospfRouter OSPF neighbor instance
*/
public void removeDeviceInformation(OspfRouter ospfRouter) {
controller.removeDeviceDetails(ospfRouter);
}
/**
* Adds link information.
*
* @param ospfRouter OSPF router instance
* @param ospfLinkTed list link ted instances
*/
public void addLinkInformation(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
controller.addLinkDetails(ospfRouter, ospfLinkTed);
}
/**
* Removes link information.
*
* @param ospfNbr OSPF neighbor instance
*/
public void removeLinkInformation(OspfNbr ospfNbr) {
controller.removeLinkDetails(buildOspfRouterDetails(ospfNbr));
}
/**
* Builds router details.
*
* @param ospfNbr OSPF neighbor instance
* @return OSPF router instance
*/
private OspfRouter buildOspfRouterDetails(OspfNbr ospfNbr) {
OspfRouter ospfRouter = new OspfRouterImpl();
ospfRouter.setRouterIp(ospfNbr.neighborId());
ospfRouter.setInterfaceId(ospfInterface.ipAddress());
ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
ospfRouter.setDeviceTed(new OspfDeviceTedImpl());
return ospfRouter;
}
/**
* Represents a Hello task which sent a hello message every configured time interval.
*/
private class InternalHelloTimer implements Runnable {
/**
* Creates an instance of Hello Timer.
*/
InternalHelloTimer() {
}
@Override
public void run() {
if (!isClosed && channel != null && channel.isOpen() && channel.isConnected()) {
HelloPacket hellopacket = new HelloPacket();
//Headers
hellopacket.setOspfVer(OspfUtil.OSPF_VERSION);
hellopacket.setOspftype(OspfPacketType.HELLO.value());
hellopacket.setOspfPacLength(0); //will be modified while encoding
hellopacket.setRouterId(ospfArea.routerId());
hellopacket.setAreaId(ospfArea.areaId());
hellopacket.setChecksum(0); //will be modified while encoding
hellopacket.setAuthType(Integer.parseInt(ospfInterface.authType()));
hellopacket.setAuthentication(Integer.parseInt(ospfInterface.authKey()));
//Body
hellopacket.setNetworkMask(ospfInterface.ipNetworkMask());
hellopacket.setOptions(ospfArea.options());
hellopacket.setHelloInterval(ospfInterface.helloIntervalTime());
hellopacket.setRouterPriority(ospfInterface.routerPriority());
hellopacket.setRouterDeadInterval(ospfInterface.routerDeadIntervalTime());
hellopacket.setDr(ospfInterface.dr());
hellopacket.setBdr(ospfInterface.bdr());
HashMap<String, OspfNbr> listOfNeighbors = ospfInterface.listOfNeighbors();
Set<String> keys = listOfNeighbors.keySet();
Iterator itr = keys.iterator();
while (itr.hasNext()) {
String nbrKey = (String) itr.next();
OspfNbrImpl nbr = (OspfNbrImpl) listOfNeighbors.get(nbrKey);
if (nbr.getState() != OspfNeighborState.DOWN) {
hellopacket.addNeighbor(Ip4Address.valueOf(nbrKey));
}
}
// build a hello Packet
if (channel == null || !channel.isOpen() || !channel.isConnected()) {
log.debug("Hello Packet not sent !!.. Channel Issue...");
return;
}
hellopacket.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
ChannelFuture future = channel.write(hellopacket);
if (future.isSuccess()) {
log.debug("Hello Packet successfully sent !!");
} else {
future.awaitUninterruptibly();
}
}
}
}
/**
* Represents a Wait Timer task which waits the interface state to become WAITING.
* It initiates DR election process.
*/
private class InternalWaitTimer implements Runnable {
Channel ch;
/**
* Creates an instance of Wait Timer.
*/
InternalWaitTimer() {
this.ch = channel;
}
@Override
public void run() {
log.debug("Wait timer expires...");
if (ch != null && ch.isConnected()) {
try {
waitTimer(ch);
} catch (Exception e) {
log.debug("Exception at wait timer ...!!!");
}
}
}
}
/**
* Represents a task which sent a LS Acknowledge from the link state headers list.
*/
private class InternalDelayedAckTimer implements Runnable {
Channel ch;
/**
* Creates an instance of Delayed acknowledge timer.
*/
InternalDelayedAckTimer() {
this.ch = channel;
}
@Override
public void run() {
if (!((OspfInterfaceImpl) ospfInterface).linkStateHeaders().isEmpty()) {
isDelayedAckTimerScheduled = true;
if (ch != null && ch.isConnected()) {
List<LsaHeader> listOfLsaHeadersAcknowledged = new ArrayList<>();
List<LsaHeader> listOfLsaHeaders = ((OspfInterfaceImpl) ospfInterface).linkStateHeaders();
log.debug("Delayed Ack, Number of Lsa's to Ack {}", listOfLsaHeaders.size());
Iterator itr = listOfLsaHeaders.iterator();
while (itr.hasNext()) {
LsAcknowledge ackContent = new LsAcknowledge();
//Setting 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);
ackContent.setChecksum(OspfUtil.NOT_ASSIGNED);
//limit to mtu
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.LSA_HEADER_LENGTH) >= maxSize) {
break;
}
LsaHeader lsaHeader = (LsaHeader) itr.next();
ackContent.addLinkStateHeader(lsaHeader);
currentLength = currentLength + OspfUtil.LSA_HEADER_LENGTH;
listOfLsaHeadersAcknowledged.add(lsaHeader);
log.debug("Delayed Ack, Added Lsa's to Ack {}", lsaHeader);
}
log.debug("Delayed Ack, Number of Lsa's in LsAck packet {}",
ackContent.getLinkStateHeaders().size());
//set the destination
if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR
|| ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
ackContent.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
} else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
ackContent.setDestinationIp(OspfUtil.ALL_DROUTERS);
}
ch.write(ackContent);
for (LsaHeader lsa : listOfLsaHeadersAcknowledged) {
((OspfInterfaceImpl) ospfInterface).linkStateHeaders().remove(lsa);
ospfInterface.removeLsaFromNeighborMap(((OspfAreaImpl) ospfArea).getLsaKey(lsa));
}
}
}
}
}
}
}
\ No newline at end of file
/*
* 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;
}
}
\ No newline at end of file
/*
* 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();
}
}
}
\ No newline at end of file
/*
* 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;
\ No newline at end of file