blob: 5ac63b14e8927ffa62aa206f01f3c405158121f5 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ospf.controller.impl;
import org.jboss.netty.channel.Channel;
import org.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.OspfArea;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfMessage;
import org.onosproject.ospf.controller.OspfNbr;
import org.onosproject.ospf.controller.OspfProcess;
import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
import org.onosproject.ospf.controller.util.OspfInterfaceType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.util.OspfInterfaceState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RejectedExecutionException;
/**
* Channel handler deals with the OSPF channel connection.
* Also it dispatches messages to the appropriate handlers for processing.
*/
public class OspfInterfaceChannelHandler extends IdleStateAwareChannelHandler {
private static final Logger log = LoggerFactory.getLogger(OspfInterfaceChannelHandler.class);
private static Map<Integer, Object> isisDb = null;
private Channel channel = null;
private Controller controller;
private List<OspfProcess> processes = null;
private byte[] configPacket = null;
private Map<Integer, OspfInterface> ospfInterfaceMap = new ConcurrentHashMap<>();
/**
* Creates an instance of OSPF channel handler.
*
* @param controller controller instance
* @param processes list of configured processes
*/
public OspfInterfaceChannelHandler(Controller controller, List<OspfProcess> processes) {
this.controller = controller;
this.processes = processes;
}
/**
* Initializes the interface map with interface details.
*/
public void initializeInterfaceMap() {
for (OspfProcess process : processes) {
for (OspfArea area : process.areas()) {
for (OspfInterface ospfInterface : area.ospfInterfaceList()) {
OspfInterface anInterface = ospfInterfaceMap.get(ospfInterface.interfaceIndex());
if (anInterface == null) {
ospfInterface.setOspfArea(area);
((OspfInterfaceImpl) ospfInterface).setController(controller);
((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
ospfInterfaceMap.put(ospfInterface.interfaceIndex(), ospfInterface);
}
((OspfInterfaceImpl) ospfInterface).setChannel(channel);
ospfInterface.interfaceUp();
ospfInterface.startDelayedAckTimer();
}
//Initialize the LSDB and aging process
area.initializeDb();
}
}
}
/**
* Updates the interface map with interface details.
*
* @param ospfProcesses updated process instances
*/
public void updateInterfaceMap(List<OspfProcess> ospfProcesses) {
for (OspfProcess ospfUpdatedProcess : ospfProcesses) {
for (OspfArea updatedArea : ospfUpdatedProcess.areas()) {
for (OspfInterface ospfUpdatedInterface : updatedArea.ospfInterfaceList()) {
OspfInterface ospfInterface = ospfInterfaceMap.get(ospfUpdatedInterface.interfaceIndex());
if (ospfInterface == null) {
ospfUpdatedInterface.setOspfArea(updatedArea);
((OspfInterfaceImpl) ospfUpdatedInterface).setController(controller);
((OspfInterfaceImpl) ospfUpdatedInterface).setState(OspfInterfaceState.DOWN);
ospfUpdatedInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
ospfUpdatedInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
ospfInterfaceMap.put(ospfUpdatedInterface.interfaceIndex(), ospfUpdatedInterface);
((OspfInterfaceImpl) ospfUpdatedInterface).setChannel(channel);
ospfUpdatedInterface.interfaceUp();
ospfUpdatedInterface.startDelayedAckTimer();
} else {
ospfInterface.setOspfArea(updatedArea);
if (ospfInterface.routerDeadIntervalTime() != ospfUpdatedInterface.routerDeadIntervalTime()) {
ospfInterface.setRouterDeadIntervalTime(ospfUpdatedInterface.routerDeadIntervalTime());
Map<String, OspfNbr> neighbors = ospfInterface.listOfNeighbors();
for (String key : neighbors.keySet()) {
OspfNbr ospfNbr = ospfInterface.neighbouringRouter(key);
ospfNbr.setRouterDeadInterval(ospfInterface.routerDeadIntervalTime());
ospfNbr.stopInactivityTimeCheck();
ospfNbr.startInactivityTimeCheck();
}
}
if (ospfInterface.interfaceType() != ospfUpdatedInterface.interfaceType()) {
ospfInterface.setInterfaceType(ospfUpdatedInterface.interfaceType());
if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
}
ospfInterface.removeNeighbors();
}
if (ospfInterface.helloIntervalTime() != ospfUpdatedInterface.helloIntervalTime()) {
ospfInterface.setHelloIntervalTime(ospfUpdatedInterface.helloIntervalTime());
ospfInterface.stopHelloTimer();
ospfInterface.startHelloTimer();
}
ospfInterfaceMap.put(ospfInterface.interfaceIndex(), ospfInterface);
}
}
}
}
}
/**
* Initialize channel, start hello sender and initialize LSDB.
*/
private void initialize() {
log.debug("OspfChannelHandler initialize..!!!");
if (configPacket != null) {
log.debug("OspfChannelHandler initialize -> sentConfig packet of length ::"
+ configPacket.length);
sentConfigPacket(configPacket);
}
initializeInterfaceMap();
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
log.info("OSPF channelConnected from {}", evt.getChannel().getRemoteAddress());
this.channel = evt.getChannel();
initialize();
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
log.debug("OspfChannelHandler::channelDisconnected...!!!");
for (Integer interfaceIndex : ospfInterfaceMap.keySet()) {
OspfInterface anInterface = ospfInterfaceMap.get(interfaceIndex);
if (anInterface != null) {
anInterface.interfaceDown();
anInterface.stopDelayedAckTimer();
}
}
if (controller != null) {
controller.connectPeer();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
log.debug("[exceptionCaught]: " + e.toString());
if (e.getCause() instanceof ReadTimeoutException) {
log.debug("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.debug("Disconnecting OSPF {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
e.getCause().getMessage());
} else if (e.getCause() instanceof OspfParseException) {
OspfParseException errMsg = (OspfParseException) e.getCause();
byte errorCode = errMsg.errorCode();
byte errorSubCode = errMsg.errorSubCode();
log.debug("Error while parsing message from OSPF {}, ErrorCode {}",
e.getChannel().getRemoteAddress(), errorCode);
} else if (e.getCause() instanceof RejectedExecutionException) {
log.debug("Could not process message: queue full");
} else {
log.debug("Error while processing message from OSPF {}, {}",
e.getChannel().getRemoteAddress(), e.getCause().getMessage());
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
log.debug("OspfChannelHandler::messageReceived...!!!");
Object message = e.getMessage();
if (message instanceof List) {
List<OspfMessage> ospfMessageList = (List<OspfMessage>) message;
log.debug("OspfChannelHandler::List of IsisMessages Size {}", ospfMessageList.size());
for (OspfMessage ospfMessage : ospfMessageList) {
processOspfMessage(ospfMessage, ctx);
}
}
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.
*/
private void processOspfMessage(OspfMessage
ospfMessage, ChannelHandlerContext ctx) {
log.debug("OspfChannelHandler::processOspfMessage...!!!");
int interfaceIndex = ospfMessage.interfaceIndex();
OspfInterface ospfInterface = ospfInterfaceMap.get(interfaceIndex);
if (ospfInterface != null) {
ospfInterface.processOspfMessage(ospfMessage, ctx);
}
}
/**
* Sends the interface configuration packet to server.
*
* @param configPacket interface configuration
*/
public void sentConfigPacket(byte[] configPacket) {
if (channel != null) {
channel.write(configPacket);
log.debug("OspfChannelHandler sentConfigPacket packet sent..!!!");
} else {
log.debug("OspfChannelHandler sentConfigPacket channel not connected - re try..!!!");
this.configPacket = configPacket;
}
}
}