Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 1 | /* |
Brian O'Connor | a09fe5b | 2017-08-03 21:12:30 -0700 | [diff] [blame] | 2 | * Copyright 2016-present Open Networking Foundation |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 16 | package org.onosproject.ospf.controller.impl; |
| 17 | |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 18 | import org.jboss.netty.channel.Channel; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 19 | import org.jboss.netty.channel.ChannelHandlerContext; |
| 20 | import org.jboss.netty.channel.ChannelStateEvent; |
| 21 | import org.jboss.netty.channel.ExceptionEvent; |
| 22 | import org.jboss.netty.channel.MessageEvent; |
| 23 | import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; |
| 24 | import org.jboss.netty.handler.timeout.ReadTimeoutException; |
| 25 | import org.onlab.packet.Ip4Address; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 26 | import org.onosproject.ospf.controller.OspfArea; |
| 27 | import org.onosproject.ospf.controller.OspfInterface; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 28 | import org.onosproject.ospf.controller.OspfMessage; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 29 | import org.onosproject.ospf.controller.OspfNbr; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 30 | import org.onosproject.ospf.controller.OspfProcess; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 31 | import org.onosproject.ospf.controller.area.OspfInterfaceImpl; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 32 | import org.onosproject.ospf.controller.util.OspfInterfaceType; |
| 33 | import org.onosproject.ospf.exceptions.OspfParseException; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 34 | import org.onosproject.ospf.protocol.util.OspfInterfaceState; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 35 | import org.slf4j.Logger; |
| 36 | import org.slf4j.LoggerFactory; |
| 37 | |
| 38 | import java.io.IOException; |
| 39 | import java.nio.channels.ClosedChannelException; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 40 | import java.util.List; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 41 | import java.util.Map; |
| 42 | import java.util.concurrent.ConcurrentHashMap; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 43 | import java.util.concurrent.RejectedExecutionException; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 44 | |
| 45 | /** |
| 46 | * Channel handler deals with the OSPF channel connection. |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 47 | * Also it dispatches messages to the appropriate handlers for processing. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 48 | */ |
| 49 | public class OspfInterfaceChannelHandler extends IdleStateAwareChannelHandler { |
| 50 | |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 51 | private static final Logger log = LoggerFactory.getLogger(OspfInterfaceChannelHandler.class); |
| 52 | private static Map<Integer, Object> isisDb = null; |
| 53 | private Channel channel = null; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 54 | private Controller controller; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 55 | private List<OspfProcess> processes = null; |
| 56 | private byte[] configPacket = null; |
| 57 | private Map<Integer, OspfInterface> ospfInterfaceMap = new ConcurrentHashMap<>(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 58 | |
| 59 | /** |
| 60 | * Creates an instance of OSPF channel handler. |
| 61 | * |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 62 | * @param controller controller instance |
| 63 | * @param processes list of configured processes |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 64 | */ |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 65 | public OspfInterfaceChannelHandler(Controller controller, List<OspfProcess> processes) { |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 66 | this.controller = controller; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 67 | this.processes = processes; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | /** |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 71 | * Initializes the interface map with interface details. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 72 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 73 | public void initializeInterfaceMap() { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 74 | for (OspfProcess process : processes) { |
| 75 | for (OspfArea area : process.areas()) { |
| 76 | for (OspfInterface ospfInterface : area.ospfInterfaceList()) { |
| 77 | OspfInterface anInterface = ospfInterfaceMap.get(ospfInterface.interfaceIndex()); |
| 78 | if (anInterface == null) { |
| 79 | ospfInterface.setOspfArea(area); |
| 80 | ((OspfInterfaceImpl) ospfInterface).setController(controller); |
| 81 | ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN); |
| 82 | ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0")); |
| 83 | ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0")); |
| 84 | ospfInterfaceMap.put(ospfInterface.interfaceIndex(), ospfInterface); |
| 85 | } |
| 86 | ((OspfInterfaceImpl) ospfInterface).setChannel(channel); |
| 87 | ospfInterface.interfaceUp(); |
| 88 | ospfInterface.startDelayedAckTimer(); |
| 89 | } |
| 90 | //Initialize the LSDB and aging process |
| 91 | area.initializeDb(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 92 | } |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 93 | } |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 94 | } |
| 95 | |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 96 | /** |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 97 | * Updates the interface map with interface details. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 98 | * |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 99 | * @param ospfProcesses updated process instances |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 100 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 101 | public void updateInterfaceMap(List<OspfProcess> ospfProcesses) { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 102 | for (OspfProcess ospfUpdatedProcess : ospfProcesses) { |
| 103 | for (OspfArea updatedArea : ospfUpdatedProcess.areas()) { |
| 104 | for (OspfInterface ospfUpdatedInterface : updatedArea.ospfInterfaceList()) { |
| 105 | OspfInterface ospfInterface = ospfInterfaceMap.get(ospfUpdatedInterface.interfaceIndex()); |
| 106 | if (ospfInterface == null) { |
| 107 | ospfUpdatedInterface.setOspfArea(updatedArea); |
| 108 | ((OspfInterfaceImpl) ospfUpdatedInterface).setController(controller); |
| 109 | ((OspfInterfaceImpl) ospfUpdatedInterface).setState(OspfInterfaceState.DOWN); |
| 110 | ospfUpdatedInterface.setDr(Ip4Address.valueOf("0.0.0.0")); |
| 111 | ospfUpdatedInterface.setBdr(Ip4Address.valueOf("0.0.0.0")); |
| 112 | ospfInterfaceMap.put(ospfUpdatedInterface.interfaceIndex(), ospfUpdatedInterface); |
| 113 | ((OspfInterfaceImpl) ospfUpdatedInterface).setChannel(channel); |
| 114 | ospfUpdatedInterface.interfaceUp(); |
| 115 | ospfUpdatedInterface.startDelayedAckTimer(); |
| 116 | } else { |
| 117 | ospfInterface.setOspfArea(updatedArea); |
| 118 | |
| 119 | if (ospfInterface.routerDeadIntervalTime() != ospfUpdatedInterface.routerDeadIntervalTime()) { |
| 120 | ospfInterface.setRouterDeadIntervalTime(ospfUpdatedInterface.routerDeadIntervalTime()); |
| 121 | Map<String, OspfNbr> neighbors = ospfInterface.listOfNeighbors(); |
| 122 | for (String key : neighbors.keySet()) { |
| 123 | OspfNbr ospfNbr = ospfInterface.neighbouringRouter(key); |
| 124 | ospfNbr.setRouterDeadInterval(ospfInterface.routerDeadIntervalTime()); |
| 125 | ospfNbr.stopInactivityTimeCheck(); |
| 126 | ospfNbr.startInactivityTimeCheck(); |
| 127 | } |
| 128 | } |
| 129 | if (ospfInterface.interfaceType() != ospfUpdatedInterface.interfaceType()) { |
| 130 | ospfInterface.setInterfaceType(ospfUpdatedInterface.interfaceType()); |
| 131 | if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) { |
| 132 | ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0")); |
| 133 | ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0")); |
| 134 | } |
| 135 | ospfInterface.removeNeighbors(); |
| 136 | } |
| 137 | if (ospfInterface.helloIntervalTime() != ospfUpdatedInterface.helloIntervalTime()) { |
| 138 | ospfInterface.setHelloIntervalTime(ospfUpdatedInterface.helloIntervalTime()); |
| 139 | ospfInterface.stopHelloTimer(); |
| 140 | ospfInterface.startHelloTimer(); |
| 141 | } |
| 142 | ospfInterfaceMap.put(ospfInterface.interfaceIndex(), ospfInterface); |
| 143 | } |
| 144 | } |
| 145 | } |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 146 | } |
| 147 | } |
| 148 | |
| 149 | /** |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 150 | * Initialize channel, start hello sender and initialize LSDB. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 151 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 152 | private void initialize() { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 153 | log.debug("OspfChannelHandler initialize..!!!"); |
| 154 | if (configPacket != null) { |
| 155 | log.debug("OspfChannelHandler initialize -> sentConfig packet of length ::" |
| 156 | + configPacket.length); |
| 157 | sentConfigPacket(configPacket); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 158 | } |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 159 | initializeInterfaceMap(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | @Override |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 163 | public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) { |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 164 | log.info("OSPF channelConnected from {}", evt.getChannel().getRemoteAddress()); |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 165 | this.channel = evt.getChannel(); |
| 166 | initialize(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 167 | } |
| 168 | |
| 169 | @Override |
| 170 | public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) { |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 171 | log.debug("OspfChannelHandler::channelDisconnected...!!!"); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 172 | |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 173 | for (Integer interfaceIndex : ospfInterfaceMap.keySet()) { |
| 174 | OspfInterface anInterface = ospfInterfaceMap.get(interfaceIndex); |
| 175 | if (anInterface != null) { |
| 176 | anInterface.interfaceDown(); |
| 177 | anInterface.stopDelayedAckTimer(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 178 | } |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | if (controller != null) { |
| 182 | controller.connectPeer(); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 183 | } |
| 184 | } |
| 185 | |
| 186 | @Override |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 187 | public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 188 | log.debug("[exceptionCaught]: " + e.toString()); |
| 189 | if (e.getCause() instanceof ReadTimeoutException) { |
| 190 | log.debug("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress()); |
| 191 | return; |
| 192 | } else if (e.getCause() instanceof ClosedChannelException) { |
| 193 | log.debug("Channel for OSPF {} already closed", e.getChannel().getRemoteAddress()); |
| 194 | } else if (e.getCause() instanceof IOException) { |
| 195 | log.debug("Disconnecting OSPF {} due to IO Error: {}", e.getChannel().getRemoteAddress(), |
| 196 | e.getCause().getMessage()); |
| 197 | } else if (e.getCause() instanceof OspfParseException) { |
| 198 | OspfParseException errMsg = (OspfParseException) e.getCause(); |
| 199 | byte errorCode = errMsg.errorCode(); |
| 200 | byte errorSubCode = errMsg.errorSubCode(); |
| 201 | log.debug("Error while parsing message from OSPF {}, ErrorCode {}", |
| 202 | e.getChannel().getRemoteAddress(), errorCode); |
| 203 | } else if (e.getCause() instanceof RejectedExecutionException) { |
| 204 | log.debug("Could not process message: queue full"); |
| 205 | } else { |
| 206 | log.debug("Error while processing message from OSPF {}, {}", |
| 207 | e.getChannel().getRemoteAddress(), e.getCause().getMessage()); |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | @Override |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 212 | public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 213 | log.debug("OspfChannelHandler::messageReceived...!!!"); |
| 214 | Object message = e.getMessage(); |
| 215 | if (message instanceof List) { |
| 216 | List<OspfMessage> ospfMessageList = (List<OspfMessage>) message; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 217 | log.debug("OspfChannelHandler::List of IsisMessages Size {}", ospfMessageList.size()); |
Ray Milkey | fe0e085 | 2018-01-18 11:14:05 -0800 | [diff] [blame] | 218 | |
| 219 | for (OspfMessage ospfMessage : ospfMessageList) { |
| 220 | processOspfMessage(ospfMessage, ctx); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 221 | } |
| 222 | } |
| 223 | if (message instanceof OspfMessage) { |
| 224 | OspfMessage ospfMessage = (OspfMessage) message; |
| 225 | log.debug("OspfChannelHandler::OspfMessages received...!!"); |
sunish vk | aa48da8 | 2016-03-02 23:17:06 +0530 | [diff] [blame] | 226 | processOspfMessage(ospfMessage, ctx); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 227 | } |
| 228 | } |
| 229 | |
| 230 | /** |
| 231 | * When an OSPF message received it is handed over to this method. |
| 232 | * Based on the type of the OSPF message received it will be handed over |
| 233 | * to corresponding message handler methods. |
| 234 | * |
| 235 | * @param ospfMessage received OSPF message |
| 236 | * @param ctx channel handler context instance. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 237 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 238 | private void processOspfMessage(OspfMessage |
| 239 | ospfMessage, ChannelHandlerContext ctx) { |
sunish vk | aa48da8 | 2016-03-02 23:17:06 +0530 | [diff] [blame] | 240 | log.debug("OspfChannelHandler::processOspfMessage...!!!"); |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 241 | int interfaceIndex = ospfMessage.interfaceIndex(); |
| 242 | OspfInterface ospfInterface = ospfInterfaceMap.get(interfaceIndex); |
| 243 | if (ospfInterface != null) { |
| 244 | ospfInterface.processOspfMessage(ospfMessage, ctx); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 245 | } |
| 246 | } |
| 247 | |
| 248 | /** |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 249 | * Sends the interface configuration packet to server. |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 250 | * |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 251 | * @param configPacket interface configuration |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 252 | */ |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 253 | public void sentConfigPacket(byte[] configPacket) { |
| 254 | if (channel != null) { |
| 255 | channel.write(configPacket); |
| 256 | log.debug("OspfChannelHandler sentConfigPacket packet sent..!!!"); |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 257 | } else { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 258 | log.debug("OspfChannelHandler sentConfigPacket channel not connected - re try..!!!"); |
| 259 | this.configPacket = configPacket; |
Kiran Ramachandra | e8699cd | 2016-02-17 17:15:21 +0530 | [diff] [blame] | 260 | } |
| 261 | } |
| 262 | } |