blob: 1a2e68798a9de1df75a92c3194184de5fa5d735a [file] [log] [blame]
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +05303 *
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 */
16
17package org.onosproject.ospf.controller.impl;
18
19import org.apache.felix.scr.annotations.Reference;
20import org.apache.felix.scr.annotations.ReferenceCardinality;
21import org.jboss.netty.channel.Channel;
22import org.jboss.netty.channel.ChannelFuture;
23import org.jboss.netty.channel.ChannelHandlerContext;
24import org.jboss.netty.channel.ChannelStateEvent;
25import org.jboss.netty.channel.ExceptionEvent;
26import org.jboss.netty.channel.MessageEvent;
27import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
28import org.jboss.netty.handler.timeout.ReadTimeoutException;
29import org.onlab.packet.Ip4Address;
30import org.onosproject.ospf.controller.LsaWrapper;
31import org.onosproject.ospf.controller.OspfArea;
32import org.onosproject.ospf.controller.OspfInterface;
33import org.onosproject.ospf.controller.OspfLinkTed;
34import org.onosproject.ospf.controller.OspfLsa;
35import org.onosproject.ospf.controller.OspfNbr;
36import org.onosproject.ospf.controller.OspfNeighborState;
37import org.onosproject.ospf.controller.OspfRouter;
38import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
39import org.onosproject.ospf.controller.area.OspfAreaImpl;
40import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
41import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
42import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
43import org.onosproject.ospf.controller.util.OspfEligibleRouter;
44import org.onosproject.ospf.controller.util.OspfInterfaceType;
45import org.onosproject.ospf.exceptions.OspfParseException;
46import org.onosproject.ospf.protocol.lsa.LsaHeader;
47import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
48import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
49import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
50import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
51import org.onosproject.ospf.protocol.ospfpacket.types.HelloPacket;
52import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
53import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
54import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
55import org.onosproject.ospf.protocol.util.ChecksumCalculator;
56import org.onosproject.ospf.protocol.util.OspfInterfaceState;
57import org.onosproject.ospf.protocol.util.OspfPacketType;
58import org.onosproject.ospf.protocol.util.OspfParameters;
59import org.onosproject.ospf.protocol.util.OspfUtil;
60import org.slf4j.Logger;
61import org.slf4j.LoggerFactory;
62
63import java.io.IOException;
64import java.nio.channels.ClosedChannelException;
65import java.util.ArrayList;
66import java.util.HashMap;
67import java.util.Iterator;
68import java.util.List;
69import java.util.ListIterator;
70import java.util.Set;
71import java.util.concurrent.Executors;
72import java.util.concurrent.RejectedExecutionException;
73import java.util.concurrent.ScheduledExecutorService;
74import java.util.concurrent.ScheduledFuture;
75import java.util.concurrent.TimeUnit;
76
77/**
78 * Channel handler deals with the OSPF channel connection.
79 * Also it dispatches messages to the appropriate handlers.
80 */
81public class OspfInterfaceChannelHandler extends IdleStateAwareChannelHandler {
82
83 private static final Logger log =
84 LoggerFactory.getLogger(OspfInterfaceChannelHandler.class);
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 private OspfInterface ospfInterface;
87 private OspfArea ospfArea;
88 private boolean isClosed = false;
89 private Controller controller;
90 private Channel channel;
91 private long delay = 0;
92 private InternalHelloTimer helloTimerTask;
93 private InternalWaitTimer waitTimerTask;
94 private InternalDelayedAckTimer delayedAckTimerTask;
95 private ScheduledExecutorService exServiceHello;
96 private ScheduledExecutorService exServiceWait;
97 private ScheduledExecutorService exServiceDelayedAck;
98 private boolean isDelayedAckTimerScheduled = false;
99 private int delayedAckTimerInterval = 2500;
100 private TopologyForDeviceAndLink topologyForDeviceAndLink;
101
102 public OspfInterfaceChannelHandler() {
103
104 }
105
106 /**
107 * Creates an instance of OSPF channel handler.
108 *
109 * @param controller controller instance
110 * @param ospfArea ospf area instance
111 * @param ospfInterface ospf interface instance
112 */
113 public OspfInterfaceChannelHandler(Controller controller, OspfArea ospfArea, OspfInterface ospfInterface) {
114
115 this.ospfArea = ospfArea;
116 this.ospfInterface = ospfInterface;
117 this.controller = controller;
118 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
119 this.ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
120 this.ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
121 this.topologyForDeviceAndLink = new TopologyForDeviceAndLinkImpl();
122 }
123
124 /**
125 * Represents an interface is up and connected.
126 *
127 * @throws Exception might throws exception
128 */
129 public void interfaceUp() throws Exception {
130 log.debug("OSPFInterfaceChannelHandler::interfaceUp...!!!");
131 if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
132 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.POINT2POINT);
133 log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} ",
134 ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());
135 } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
136 //if router priority is 0, move the state to DROther
137 if (ospfInterface.routerPriority() == 0) {
138 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
139 } else {
140 log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} RouterPriority {}",
141 ospfInterface.interfaceType(),
142 ((OspfInterfaceImpl) ospfInterface).state(), ospfInterface.routerPriority());
143 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.WAITING);
144 //start wait timer - like inactivity timer with router deadInterval
145 startWaitTimer();
146 }
147
148 }
149 // Start hello timer with interval from config - convert seconds to milliseconds
150 startHelloTimer(ospfInterface.helloIntervalTime());
151 ospfArea.refreshArea(ospfInterface);
152 }
153
154
155 /**
156 * Gets called when a BDR was detected before the wait timer expired.
157 *
158 * @param ch channel instance
159 * @throws Exception might throws exception
160 */
161 public void backupSeen(Channel ch) throws Exception {
162 log.debug("OSPFInterfaceChannelHandler::backupSeen ");
163 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
164 electRouter(ch);
165 }
166 }
167
168 /**
169 * Gets called when no hello message received for particular period.
170 *
171 * @param ch channel instance
172 * @throws Exception might throws exception
173 */
174 public void waitTimer(Channel ch) throws Exception {
175 log.debug("OSPFInterfaceChannelHandler::waitTimer ");
176 //section 9.4
177 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
178 electRouter(ch);
179 }
180 }
181
182 /**
183 * Neighbor change event is triggered when the router priority gets changed.
184 *
185 * @throws Exception might throws exception
186 */
187 public void neighborChange() throws Exception {
188 log.debug("OSPFInterfaceChannelHandler::neighborChange ");
189 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
190 ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
191 ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
192 electRouter(channel);
193 }
194 }
195
196 /**
197 * Gets called when an interface is down.
198 * All interface variables are reset, and interface timers disabled.
199 * Also all neighbor connections associated with the interface are destroyed.
200 */
201 public void interfaceDown() {
202 log.debug("OSPFInterfaceChannelHandler::interfaceDown ");
203 stopHelloTimer();
204 ospfInterface.listOfNeighbors().clear();
205 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
206 }
207
208 @Override
209 public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) throws Exception {
210 log.info("OSPF channelConnected from {}", evt.getChannel().getRemoteAddress());
211 channel = evt.getChannel();
212 interfaceUp();
213 startDelayedAckTimer();
214 }
215
216 @Override
217 public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
218 interfaceDown();
219 stopDelayedAckTimer();
220 log.debug("OspfChannelHandler::channelDisconnected...!!!");
221 }
222
223 @Override
224 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
225 log.info("[exceptionCaught]: " + e.toString());
226 if (e.getCause() instanceof ReadTimeoutException) {
227 // device timeout
228 log.error("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress());
229 return;
230 } else if (e.getCause() instanceof ClosedChannelException) {
231 log.debug("Channel for OSPF {} already closed", e.getChannel().getRemoteAddress());
232 } else if (e.getCause() instanceof IOException) {
233 log.error("Disconnecting OSPF {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
234 e.getCause().getMessage());
235 if (log.isDebugEnabled()) {
236 log.debug("StackTrace for previous Exception: {}", e.getCause());
237 }
238 } else if (e.getCause() instanceof OspfParseException) {
239 OspfParseException errMsg = (OspfParseException) e.getCause();
240 byte errorCode = errMsg.errorCode();
241 byte errorSubCode = errMsg.errorSubCode();
242 log.error("Error while parsing message from OSPF {}, ErrorCode {}",
243 e.getChannel().getRemoteAddress(), errorCode);
244 } else if (e.getCause() instanceof RejectedExecutionException) {
245 log.warn("Could not process message: queue full");
246 } else {
247 log.error("Error while processing message from OSPF {}, state {}",
248 e.getChannel().getRemoteAddress(), ((OspfInterfaceImpl) ospfInterface).state());
249 }
250 }
251
252 @Override
253 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
254 log.debug("OspfChannelHandler::messageReceived...!!!");
255 Object message = e.getMessage();
256 if (message instanceof List) {
257 List<OspfMessage> ospfMessageList = (List<OspfMessage>) message;
258 log.debug("OspfChannelHandler::List of OspfMessages Size {}", ospfMessageList.size());
259 if (ospfMessageList != null) {
260 for (OspfMessage ospfMessage : ospfMessageList) {
sunish vkaa48da82016-03-02 23:17:06 +0530261 processOspfMessage(ospfMessage, ctx);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530262 }
263 } else {
264 log.debug("OspfChannelHandler::OspfMessages Null List...!!");
265 }
266 }
267 if (message instanceof OspfMessage) {
268 OspfMessage ospfMessage = (OspfMessage) message;
269 log.debug("OspfChannelHandler::OspfMessages received...!!");
sunish vkaa48da82016-03-02 23:17:06 +0530270 processOspfMessage(ospfMessage, ctx);
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530271 }
272 }
273
274 /**
275 * When an OSPF message received it is handed over to this method.
276 * Based on the type of the OSPF message received it will be handed over
277 * to corresponding message handler methods.
278 *
279 * @param ospfMessage received OSPF message
280 * @param ctx channel handler context instance.
281 * @throws Exception might throws exception
282 */
sunish vkaa48da82016-03-02 23:17:06 +0530283 public void processOspfMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
284 log.debug("OspfChannelHandler::processOspfMessage...!!!");
Kiran Ramachandrae8699cd2016-02-17 17:15:21 +0530285
286 if (!validateMessage(ospfMessage)) {
287 return;
288 }
289
290 switch (ospfMessage.ospfMessageType().value()) {
291 case OspfParameters.HELLO:
292 processHelloMessage(ospfMessage, ctx);
293 break;
294 case OspfParameters.DD:
295 processDdMessage(ospfMessage, ctx);
296 break;
297 case OspfParameters.LSREQUEST:
298 processLsRequestMessage(ospfMessage, ctx);
299 break;
300 case OspfParameters.LSUPDATE:
301 processLsUpdateMessage(ospfMessage, ctx);
302 break;
303 case OspfParameters.LSACK:
304 processLsAckMessage(ospfMessage, ctx);
305 break;
306 default:
307 log.debug("Unknown packet to process...!!!");
308 break;
309 }
310 }
311
312 /**
313 * Validates the OSPF message received.
314 *
315 * @param ospfMessage OSPF message.
316 * @return true if it is a valid else false.
317 * @throws Exception might throws exception
318 */
319 private boolean validateMessage(OspfMessage ospfMessage) throws Exception {
320 boolean isValid = true;
321 OspfPacketHeader header = (OspfPacketHeader) ospfMessage;
322
323 //added the check to eliminate self origin packets also two interfaces on same router.
324 if (!header.sourceIp().equals(ospfInterface.ipAddress()) && !header.routerId().equals(
325 ospfArea.routerId())) {
326 //Verify the checksum
327 ChecksumCalculator checksum = new ChecksumCalculator();
328 if (!checksum.isValidOspfCheckSum(ospfMessage, OspfUtil.OSPFPACKET_CHECKSUM_POS1,
329 OspfUtil.OSPFPACKET_CHECKSUM_POS2)) {
330 log.debug("Checksum mismatch. Received packet type {} ", ospfMessage.ospfMessageType());
331 return false;
332 }
333 if (((OspfPacketHeader) ospfMessage).ospfVersion() != OspfUtil.OSPF_VERSION_2) {
334 log.debug("Received osfpMessage Version should match with Interface Version ");
335 return false;
336 }
337 if (!((OspfPacketHeader) ospfMessage).areaId().equals(ospfArea.areaId())) {
338 log.debug("Received ospf packets are from different area than our Area ID. " +
339 "Received Area ID {}, Our AreaId {} ",
340 ((OspfPacketHeader) ospfMessage).areaId(), ospfArea.areaId());
341 return false;
342 }
343
344 //According to RFC-2328 (8.2)
345 /**
346 * ABR should receive packets from backbone 0.0.0.0 as we are not acting as ABR
347 * we are rejecting the packet.
348 */
349 if (((OspfPacketHeader) ospfMessage).areaId().equals(Ip4Address.valueOf("0.0.0.0"))) {
350 log.debug("ABR should receive packets from backbone 0.0.0.0 as we are not acting as " +
351 "ABR we are rejecting the ospf packet");
352 return false;
353 }
354 if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value() &&
355 !OspfUtil.sameNetwork(((OspfPacketHeader) ospfMessage).sourceIp(),
356 ospfInterface.ipAddress(), ospfInterface.ipNetworkMask())) {
357 log.debug("Received packets from different subnets. Discarding...!!!");
358 return false;
359 }
360 } else {
361 isValid = false;
362 }
363
364 return isValid;
365 }
366
367 /**
368 * Processes Hello message.
369 *
370 * @param ospfMessage OSPF message instance.
371 * @param ctx context instance.
372 * @throws Exception might throws exception
373 */
374 void processHelloMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
375 log.debug("OspfChannelHandler::processHelloMessage...!!!");
376 HelloPacket helloPacket = (HelloPacket) ospfMessage;
377
378 // processing of hello packet as per RFC 2328 section 10.5
379 log.debug("OspfChannelHandler::processHelloMessage::Interface Type {} OSPFInterfaceState {} ",
380 ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());
381
382 if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
383 if (!helloPacket.networkMask().equals(ospfInterface.ipNetworkMask())) {
384 log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received does not " +
385 "match the same network mask as the configure Interface");
386 return;
387 }
388 }
389 if (helloPacket.helloInterval() != ospfInterface.helloIntervalTime()) {
390 log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
391 "hello interval as configured Interface");
392 return;
393 }
394 if (helloPacket.routerDeadInterval() != ospfInterface.routerDeadIntervalTime()) {
395 log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
396 "Router Dead interval as configured Interface");
397 return;
398 }
399
400 if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
401 // to verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
402 OspfNbr nbr;
403 if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
404 nbr = new OspfNbrImpl(ospfArea, ospfInterface, helloPacket.sourceIp(),
405 helloPacket.routerId(), helloPacket.options(), this, topologyForDeviceAndLink);
406 ospfInterface.addNeighbouringRouter(nbr);
407 } else {
408 nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
409 nbr.setRouterPriority(helloPacket.routerPriority());
410 }
411 if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
412 ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
413 } else {
414 ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
415 }
416 } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
417
418 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
419 if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0"))) &&
420 (!helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))) {
421 stopWaitTimer();
422 ospfInterface.setDr(helloPacket.dr());
423 ospfInterface.setBdr(helloPacket.bdr());
424 if (helloPacket.dr().equals(ospfInterface.ipAddress())) {
425 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
426 //refresh router Lsa
427 ospfArea.refreshArea(ospfInterface);
428 } else if (helloPacket.bdr().equals(ospfInterface.ipAddress())) {
429 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
430 //refresh router Lsa
431 ospfArea.refreshArea(ospfInterface);
432 } else {
433 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
434 ospfArea.refreshArea(ospfInterface);
435 }
436
437 } else if (!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
438 !helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
439 ospfInterface.setDr(helloPacket.dr());
440 ospfInterface.setBdr(helloPacket.bdr());
441 }
442 Ip4Address sourceIp = helloPacket.sourceIp();
443 OspfNbr nbr;
444 if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
445 nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
446 helloPacket.options(), this, topologyForDeviceAndLink);
447 nbr.setNeighborId(helloPacket.routerId());
448 nbr.setNeighborBdr(helloPacket.bdr());
449 nbr.setNeighborDr(helloPacket.dr());
450 nbr.setRouterPriority(helloPacket.routerPriority());
451 ospfInterface.addNeighbouringRouter(nbr);
452 } else {
453 nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
454 nbr.setRouterPriority(helloPacket.routerPriority());
455 }
456 if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
457 ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
458 } else {
459 ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
460 }
461
462 if (helloPacket.dr().equals(sourceIp)) {
463 if (helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
464 // call backup seen
465 stopWaitTimer();
466 backupSeen(ctx.getChannel());
467 }
468 }
469
470 if (helloPacket.bdr().equals(sourceIp)) {
471 // call backup seen
472 stopWaitTimer();
473 backupSeen(ctx.getChannel());
474 }
475 } else {
476
477 if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
478 !helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))
479 && ospfInterface.routerPriority() == 0) {
480 ospfInterface.setDr(helloPacket.dr());
481 ospfInterface.setBdr(helloPacket.bdr());
482 }
483 //To verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
484 Ip4Address sourceIp = helloPacket.sourceIp();
485 OspfNbr nbr;
486 if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
487 nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
488 helloPacket.options(), this, topologyForDeviceAndLink);
489 nbr.setNeighborId(helloPacket.routerId());
490 nbr.setNeighborBdr(helloPacket.bdr());
491 nbr.setNeighborDr(helloPacket.dr());
492 nbr.setRouterPriority(helloPacket.routerPriority());
493 ospfInterface.addNeighbouringRouter(nbr);
494 ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
495 } else {
496 log.debug("OspfChannelHandler::NeighborInList::helloPacket.bdr(): {}, " +
497 "helloPacket.dr(): {}", helloPacket.bdr(), helloPacket.dr());
498 nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
499 nbr.setRouterPriority(helloPacket.routerPriority());
500 if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
501 ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
502 } else {
503 ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
504 }
505 if (nbr.routerPriority() != helloPacket.routerPriority()) {
506 nbr.setNeighborBdr(helloPacket.bdr());
507 nbr.setNeighborDr(helloPacket.dr());
508 neighborChange();
509 }
510
511
512 if (nbr.neighborIpAddr().equals(helloPacket.dr()) &&
513 !(nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
514 nbr.setNeighborBdr(helloPacket.bdr());
515 nbr.setNeighborDr(helloPacket.dr());
516 neighborChange();
517 }
518
519 if (!(nbr.neighborIpAddr().equals(helloPacket.dr())) &&
520 (nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
521 nbr.setNeighborBdr(helloPacket.bdr());
522 nbr.setNeighborDr(helloPacket.dr());
523 neighborChange();
524 }
525
526 if (nbr.neighborIpAddr().equals(helloPacket.bdr()) &&
527 !(nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
528 nbr.setNeighborBdr(helloPacket.bdr());
529 nbr.setNeighborDr(helloPacket.dr());
530 neighborChange();
531 }
532
533 if (!(nbr.neighborIpAddr().equals(helloPacket.bdr())) &&
534 (nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
535 nbr.setNeighborBdr(helloPacket.bdr());
536 nbr.setNeighborDr(helloPacket.dr());
537 neighborChange();
538 }
539
540 nbr.setNeighborBdr(helloPacket.bdr());
541 nbr.setNeighborDr(helloPacket.dr());
542 }
543
544 }
545 }
546 }
547
548 /**
549 * process the DD message which received.
550 *
551 * @param ospfMessage OSPF message instance.
552 * @param ctx channel handler context instance
553 * @throws Exception might throws exception
554 */
555 void processDdMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
556 log.debug("OspfChannelHandler::processDdMessage...!!!");
557
558 DdPacket ddPacket = (DdPacket) ospfMessage;
559 log.debug("Got DD packet from {}", ddPacket.sourceIp());
560 //check it is present in listOfNeighbors
561 Ip4Address neighbourId = ddPacket.routerId();
562 OspfNbr nbr = ospfInterface.neighbouringRouter(neighbourId.toString());
563
564 if (nbr != null) {
565 log.debug("OspfChannelHandler::processDdMessage:: OSPFNeighborState {}", nbr.getState());
566 // set options for the NBR
567 nbr.setIsOpaqueCapable(ddPacket.isOpaqueCapable());
568 if (ddPacket.imtu() > ospfInterface.mtu()) {
569 log.debug("the MTU size is greater than the interface MTU");
570 return;
571 }
572 if (nbr.getState() == OspfNeighborState.DOWN) {
573 return;
574 }
575 if (nbr.getState() == OspfNeighborState.ATTEMPT) {
576 return;
577 }
578 if (nbr.getState() == OspfNeighborState.TWOWAY) {
579 nbr.adjOk(channel);
580 return;
581 }
582 //if init is the state call twoWayReceived
583 if (nbr.getState() == OspfNeighborState.INIT) {
584 ((OspfNbrImpl) nbr).twoWayReceived(ddPacket, ctx.getChannel());
585 } else if (nbr.getState() == OspfNeighborState.EXSTART) {
586 //get I,M,MS Bits
587 int initialize = ddPacket.isInitialize();
588 int more = ddPacket.isMore();
589 int masterOrSlave = ddPacket.isMaster();
590 int options = ddPacket.options();
591 nbr.setOptions(options);
592
593 if (initialize == OspfUtil.INITIALIZE_SET && more == OspfUtil.MORE_SET &&
594 masterOrSlave == OspfUtil.IS_MASTER) {
595 if (ddPacket.getLsaHeaderList().isEmpty()) {
596 if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) >
597 OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
598 nbr.setIsMaster(OspfUtil.IS_MASTER);
599 ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
600 nbr.setDdSeqNum(ddPacket.sequenceNo());
601 nbr.setOptions(ddPacket.options());
602 ((OspfNbrImpl) nbr).negotiationDone(ddPacket, true, ddPacket.getLsaHeaderList(),
603 ctx.getChannel());
604 }
605 }
606 }
607 if (initialize == OspfUtil.INITIALIZE_NOTSET && masterOrSlave == OspfUtil.NOT_MASTER) {
608 if (nbr.ddSeqNum() == ddPacket.sequenceNo()) {
609 if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) <
610 OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
611 ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
612 nbr.setOptions(ddPacket.options());
613 nbr.setDdSeqNum(nbr.ddSeqNum() + 1);
614 ((OspfNbrImpl) nbr).negotiationDone(ddPacket, false, ddPacket.getLsaHeaderList(),
615 ctx.getChannel());
616 }
617 }
618 }
619
620 } else if (nbr.getState() == OspfNeighborState.EXCHANGE) {
621 //get I,M,MS Bits
622 log.debug("Neighbor state:: EXCHANGE");
623 boolean isDuplicateDDPacket = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
624 int initialize = ddPacket.isInitialize();
625 int more = ddPacket.isMore();
626 int masterOrSlave = ddPacket.isMaster();
627 int options = ddPacket.options();
628
629 if (!isDuplicateDDPacket) {
630 //if dd packet is not duplicate then continue
631 if (nbr.isMaster() != masterOrSlave) {
632 DdPacket newResPacket =
633 (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Master/Slave Inconsistency");
634 newResPacket.setDestinationIp(ddPacket.sourceIp());
635 log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
636 ctx.getChannel().write(newResPacket);
637 } else if (initialize == 1) {
638 DdPacket newResPacket =
639 (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
640 newResPacket.setDestinationIp(ddPacket.sourceIp());
641 log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
642 ctx.getChannel().write(newResPacket);
643 } else {
644
645 if (masterOrSlave == OspfUtil.NOT_MASTER) {
646 if (ddPacket.sequenceNo() == nbr.ddSeqNum()) {
647 //Process the DD Packet
648 ((OspfNbrImpl) nbr).processDdPacket(false, ddPacket, ctx.getChannel());
649 log.debug("Received DD Packet");
650 } else {
651 DdPacket newResPacket =
652 (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Sequence Number Mismatch");
653 newResPacket.setDestinationIp(ddPacket.sourceIp());
654 log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
655 ctx.getChannel().write(newResPacket);
656 }
657 } else {
658 //we are the slave
659 if (ddPacket.sequenceNo() == (nbr.ddSeqNum() + 1)) {
660 ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
661 ((OspfNbrImpl) nbr).processDdPacket(true, ddPacket, ctx.getChannel());
662 log.debug("Process DD Packet");
663 } else {
664 DdPacket newResPacket =
665 (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("options inconsistency");
666 newResPacket.setDestinationIp(ddPacket.sourceIp());
667 log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
668 ctx.getChannel().write(newResPacket);
669 }
670 }
671 }
672 } else {
673 if (masterOrSlave == OspfUtil.NOT_MASTER) {
674 return;
675 } else {
676 DdPacket newResPacket = ((OspfNbrImpl) nbr).lastSentDdPacket();
677 log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
678 ctx.getChannel().write(newResPacket);
679 }
680 }
681 } else if (nbr.getState() == OspfNeighborState.LOADING || nbr.getState() == OspfNeighborState.FULL) {
682 //In case if we are slave then we have to send the last received DD Packet
683 int options = ddPacket.options();
684 if (nbr.options() != options) {
685 OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
686 newResPacket.setDestinationIp(ddPacket.sourceIp());
687 ctx.getChannel().write(newResPacket);
688 } else if (ddPacket.isInitialize() == OspfUtil.INITIALIZE_SET) {
689 OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
690 newResPacket.setDestinationIp(ddPacket.sourceIp());
691 ctx.getChannel().write(newResPacket);
692 }
693 boolean isDuplicate = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
694 //we are master
695 if (nbr.isMaster() != OspfUtil.IS_MASTER) {
696 // check if the packet is duplicate, duplicates should be discarded by the master
697 if (isDuplicate) {
698 log.debug("received a duplicate DD packet");
699 }
700 } else {
701 //The slave must respond to duplicates by repeating the last Database Description packet
702 //that it had sent.
703 if (isDuplicate) {
704 ddPacket.setDestinationIp(ddPacket.sourceIp());
705 ctx.getChannel().write(((OspfNbrImpl) nbr).lastSentDdPacket());
706 log.debug("Sending back the duplicate packet ");
707 }
708 }
709 }
710 }
711 }
712
713 /**
714 * Process the Ls Request message.
715 *
716 * @param ospfMessage OSPF message instance.
717 * @param ctx channel handler context instance.
718 * @throws Exception might throws exception
719 */
720 void processLsRequestMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
721 log.debug("OspfChannelHandler::processLsRequestMessage...!!!");
722 LsRequest lsrPacket = (LsRequest) ospfMessage;
723 OspfNbr nbr = ospfInterface.neighbouringRouter(lsrPacket.routerId().toString());
724
725 if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING ||
726 nbr.getState() == OspfNeighborState.FULL) {
727
728 LsRequest reqMsg = (LsRequest) ospfMessage;
729 if (reqMsg.getLinkStateRequests().isEmpty()) {
730 log.debug("Received Link State Request Vector is Empty ");
731 return;
732 } else {
733 //Send the LsUpdate back
734 ListIterator<LsRequestPacket> listItr = reqMsg.getLinkStateRequests().listIterator();
735 while (listItr.hasNext()) {
736 LsUpdate lsupdate = new LsUpdate();
737 lsupdate.setOspfVer(OspfUtil.OSPF_VERSION);
738 lsupdate.setOspftype(OspfPacketType.LSUPDATE.value());
739 lsupdate.setRouterId(ospfArea.routerId());
740 lsupdate.setAreaId(ospfArea.areaId());
741 lsupdate.setAuthType(OspfUtil.NOT_ASSIGNED);
742 lsupdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
743 lsupdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
744 lsupdate.setChecksum(OspfUtil.NOT_ASSIGNED);
745
746 //limit to mtu
747 int currentLength = OspfUtil.OSPF_HEADER_LENGTH + OspfUtil.FOUR_BYTES;
748 int maxSize = ospfInterface.mtu() -
749 OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
750 int noLsa = 0;
751 while (listItr.hasNext()) {
752 LsRequestPacket lsRequest = (LsRequestPacket) listItr.next();
753 // to verify length of the LSA
754 LsaWrapper wrapper = ospfArea.getLsa(lsRequest.lsType(), lsRequest.linkStateId(),
755 lsRequest.ownRouterId());
756 OspfLsa ospflsa = wrapper.ospfLsa();
757 if ((currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen()) >= maxSize) {
758 listItr.previous();
759 break;
760 }
761 if (ospflsa != null) {
762 lsupdate.addLsa(ospflsa);
763 noLsa++;
764
765 currentLength = currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen();
766 } else {
767 nbr.badLSReq(channel);
768 }
769 }
770 lsupdate.setNumberOfLsa(noLsa);
771 //set the destination
772 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
773 ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
774 ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
775 lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
776 } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
777 lsupdate.setDestinationIp(OspfUtil.ALL_DROUTERS);
778 }
779 ctx.getChannel().write(lsupdate);
780 }
781 }
782 }
783 }
784
785 /**
786 * Process the ls update message.
787 *
788 * @param ospfMessage OSPF message instance.
789 * @param ctx channel handler context instance.
790 * @throws Exception might throws exception
791 */
792 void processLsUpdateMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
793 log.debug("OspfChannelHandler::processLsUpdateMessage");
794 LsUpdate lsUpdate = (LsUpdate) ospfMessage;
795 String neighbourId = lsUpdate.routerId().toString();
796 //LSUpdate packet has been associated with a particular neighbor.
797 //Neighbor should not be in lesser state than Exchange.
798 if (ospfInterface.isNeighborInList(neighbourId)) {
799 OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(neighbourId);
800 if (nbr.getState() == OspfNeighborState.EXCHANGE ||
801 nbr.getState() == OspfNeighborState.LOADING) {
802 nbr.processLsUpdate(lsUpdate, ctx.getChannel());
803 } else if (nbr.getState() == OspfNeighborState.FULL) {
804 if (lsUpdate.noLsa() != 0) {
805 List<OspfLsa> list = lsUpdate.getLsaList();
806 Iterator itr = list.iterator();
807 while (itr.hasNext()) {
808 LsaHeader lsa = (LsaHeader) itr.next();
809 nbr.processReceivedLsa(lsa, true, ctx.getChannel(), lsUpdate.sourceIp());
810 }
811 } else {
812 return;
813 }
814 }
815 }
816 }
817
818 /**
819 * Process the ls acknowledge message.
820 *
821 * @param ospfMessage OSPF message instance.
822 * @param ctx channel handler context instance.
823 * @throws Exception might throws exception
824 */
825 void processLsAckMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
826 log.debug("OspfChannelHandler::processLsAckMessage");
827 LsAcknowledge lsAckPacket = (LsAcknowledge) ospfMessage;
828 //check it is present in listOfNeighbors
829 OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(lsAckPacket.routerId().toString());
830 if (nbr != null) {
831 if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
832 // discard the packet.
833 return;
834 } else {
835 // process ls acknowledgements
836 Iterator itr = lsAckPacket.getLinkStateHeaders().iterator();
837 while (itr.hasNext()) {
838 LsaHeader lsRequest = (LsaHeader) itr.next();
839
840 OspfLsa ospfLsa =
841 (OspfLsa) nbr.getPendingReTxList().get(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
842 if (lsRequest != null && ospfLsa != null) {
843 String isSame = ((OspfLsdbImpl) ospfArea.database()).isNewerOrSameLsa(
844 lsRequest, (LsaHeader) ospfLsa);
845 if (isSame.equals("same")) {
846 nbr.getPendingReTxList().remove(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
847 }
848 }
849 }
850 }
851 }
852 }
853
854 /**
855 * Compares two Dd Packets to check whether its duplicate or not.
856 *
857 * @param receivedDPacket received DD packet from network.
858 * @param lastDdPacket Last DdPacket which we sent.
859 * @return true if it is a duplicate packet else false.
860 */
861 public boolean compareDdPackets(DdPacket receivedDPacket, DdPacket lastDdPacket) {
862 if (receivedDPacket.isInitialize() == lastDdPacket.isInitialize()) {
863 if (receivedDPacket.isMaster() == lastDdPacket.isMaster()) {
864 if (receivedDPacket.isMore() == lastDdPacket.isMore()) {
865 if (receivedDPacket.options() == lastDdPacket.options()) {
866 if (receivedDPacket.sequenceNo() == lastDdPacket.sequenceNo()) {
867 return true;
868 }
869 }
870 }
871 }
872 }
873 return false;
874 }
875
876 /**
877 * Closes the Netty channel.
878 *
879 * @param ctx the Channel Handler Context
880 */
881 void closeChannel(ChannelHandlerContext ctx) {
882 log.debug("OspfChannelHandler::closeChannel");
883 isClosed = true;
884 ctx.getChannel().close();
885 }
886
887 /**
888 * Starts the hello timer which sends hello packet every configured seconds.
889 *
890 * @param period the interval to run task
891 */
892 private void startHelloTimer(long period) {
893 log.debug("OSPFInterfaceChannelHandler::startHelloTimer");
894 exServiceHello = Executors.newSingleThreadScheduledExecutor();
895 helloTimerTask = new InternalHelloTimer();
896 final ScheduledFuture<?> helloHandle =
897 exServiceHello.scheduleAtFixedRate(helloTimerTask, delay, period, TimeUnit.SECONDS);
898 }
899
900 /**
901 * Stops the hello timer.
902 */
903 private void stopHelloTimer() {
904 log.debug("OSPFInterfaceChannelHandler::stopHelloTimer ");
905 exServiceHello.shutdown();
906 }
907
908 /**
909 * Starts the wait timer.
910 */
911 private void startWaitTimer() {
912 log.debug("OSPFNbr::startWaitTimer");
913 exServiceWait = Executors.newSingleThreadScheduledExecutor();
914 waitTimerTask = new InternalWaitTimer();
915 final ScheduledFuture<?> waitTimerHandle =
916 exServiceWait.schedule(waitTimerTask, ospfInterface.routerDeadIntervalTime(),
917 TimeUnit.SECONDS);
918 }
919
920 /**
921 * Stops the wait timer.
922 */
923 private void stopWaitTimer() {
924 log.debug("OSPFNbr::stopWaitTimer ");
925 exServiceWait.shutdown();
926 }
927
928 /**
929 * Starts the timer which waits for configured seconds and sends Delayed Ack Packet.
930 */
931 private void startDelayedAckTimer() {
932 if (!isDelayedAckTimerScheduled) {
933 log.debug("Started DelayedAckTimer...!!!");
934 exServiceDelayedAck = Executors.newSingleThreadScheduledExecutor();
935 delayedAckTimerTask = new InternalDelayedAckTimer();
936 final ScheduledFuture<?> delayAckHandle =
937 exServiceDelayedAck.scheduleAtFixedRate(delayedAckTimerTask, delayedAckTimerInterval,
938 delayedAckTimerInterval, TimeUnit.MILLISECONDS);
939 isDelayedAckTimerScheduled = true;
940 }
941 }
942
943 /**
944 * Stops the delayed acknowledge timer.
945 */
946 private void stopDelayedAckTimer() {
947 if (isDelayedAckTimerScheduled) {
948 log.debug("Stopped DelayedAckTimer...!!!");
949 isDelayedAckTimerScheduled = false;
950 exServiceDelayedAck.shutdown();
951 }
952 }
953
954 /**
955 * Performs DR election.
956 *
957 * @param ch Netty Channel instance.
958 * @throws Exception might throws exception
959 */
960 public void electRouter(Channel ch) throws Exception {
961
962 Ip4Address currentDr = ospfInterface.dr();
963 Ip4Address currentBdr = ospfInterface.bdr();
964 OspfInterfaceState oldState = ((OspfInterfaceImpl) ospfInterface).state();
965 OspfInterfaceState newState;
966
967 log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
968 currentDr, currentBdr);
969 List<OspfEligibleRouter> eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());
970
971 log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
972 OspfEligibleRouter electedBdr = electBdr(eligibleRouters);
973 OspfEligibleRouter electedDr = electDr(eligibleRouters, electedBdr);
974
975 ospfInterface.setBdr(electedBdr.getIpAddress());
976 ospfInterface.setDr(electedDr.getIpAddress());
977
978 if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
979 !electedBdr.getIpAddress().equals(currentBdr)) {
980 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
981 }
982
983 if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
984 !electedDr.getIpAddress().equals(currentDr)) {
985 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
986 }
987
988 if (((OspfInterfaceImpl) ospfInterface).state() != oldState &&
989 !(((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER &&
990 oldState.value() < OspfInterfaceState.DROTHER.value())) {
991 log.debug("Recalculating as the State is changed ");
992 log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
993 currentDr, currentBdr);
994 eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());
995
996 log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
997 electedBdr = electBdr(eligibleRouters);
998 electedDr = electDr(eligibleRouters, electedBdr);
999
1000 ospfInterface.setBdr(electedBdr.getIpAddress());
1001 ospfInterface.setDr(electedDr.getIpAddress());
1002 }
1003
1004 if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
1005 !electedBdr.getIpAddress().equals(currentBdr)) {
1006 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
1007 ospfArea.refreshArea(ospfInterface);
1008 }
1009
1010 if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
1011 !electedDr.getIpAddress().equals(currentDr)) {
1012 ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
1013 //Refresh Router Lsa & Network Lsa
1014 ospfArea.refreshArea(ospfInterface);
1015 }
1016
1017 if (currentDr != electedDr.getIpAddress() || currentBdr != electedBdr.getIpAddress()) {
1018 Set<String> negibhorIdList;
1019 negibhorIdList = ospfInterface.listOfNeighbors().keySet();
1020 for (String routerid : negibhorIdList) {
1021 OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerid);
1022 if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue()) {
1023 nbr.adjOk(ch);
1024 }
1025 }
1026 }
1027
1028 log.debug("OSPFInterfaceChannelHandler::electRouter -> ElectedDR: {}, ElectedBDR: {}",
1029 electedDr.getIpAddress(), electedBdr.getIpAddress());
1030 }
1031
1032
1033 /**
1034 * BDR Election process. Find the list of eligible router to participate in the process.
1035 *
1036 * @param electedDr router elected as DR.
1037 * @return list of eligible routers
1038 */
1039 public List<OspfEligibleRouter> calculateListOfEligibleRouters(OspfEligibleRouter electedDr) {
1040 log.debug("OSPFNbr::calculateListOfEligibleRouters ");
1041 Set<String> neighborIdList;
1042 List<OspfEligibleRouter> eligibleRouters = new ArrayList<>();
1043
1044 neighborIdList = ospfInterface.listOfNeighbors().keySet();
1045 for (String routerId : neighborIdList) {
1046 OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerId);
1047 if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue() &&
1048 nbr.routerPriority() > 0) {
1049 OspfEligibleRouter router = new OspfEligibleRouter();
1050 router.setIpAddress(nbr.neighborIpAddr());
1051 router.setRouterId(nbr.neighborId());
1052 router.setRouterPriority(nbr.routerPriority());
1053 if (nbr.neighborDr().equals(nbr.neighborIpAddr()) ||
1054 electedDr.getIpAddress().equals(nbr.neighborIpAddr())) {
1055 router.setIsDr(true);
1056 } else if (nbr.neighborBdr().equals(nbr.neighborIpAddr())) {
1057 router.setIsBdr(true);
1058 }
1059 eligibleRouters.add(router);
1060 }
1061 }
1062 // interface does not have states like two and all
1063 if (ospfInterface.routerPriority() > 0) {
1064 OspfEligibleRouter router = new OspfEligibleRouter();
1065 router.setIpAddress(ospfInterface.ipAddress());
1066 router.setRouterId(ospfArea.routerId());
1067 router.setRouterPriority(ospfInterface.routerPriority());
1068 if (ospfInterface.dr().equals(ospfInterface.ipAddress()) ||
1069 electedDr.getIpAddress().equals(ospfInterface.ipAddress())) {
1070 router.setIsDr(true);
1071 } else if (ospfInterface.bdr().equals(ospfInterface.ipAddress()) &&
1072 !ospfInterface.dr().equals(ospfInterface.ipAddress())) {
1073 router.setIsBdr(true);
1074 }
1075
1076 eligibleRouters.add(router);
1077 }
1078
1079 return eligibleRouters;
1080 }
1081
1082 /**
1083 * Based on router priority assigns BDR.
1084 *
1085 * @param eligibleRouters list of routers to participate in bdr election.
1086 * @return OSPF Eligible router instance.
1087 */
1088 public OspfEligibleRouter electBdr(List<OspfEligibleRouter> eligibleRouters) {
1089 log.debug("OSPFInterfaceChannelHandler::electBdr -> eligibleRouters: {}", eligibleRouters);
1090 List<OspfEligibleRouter> declaredAsBdr = new ArrayList<>();
1091 List<OspfEligibleRouter> notDrAndBdr = new ArrayList<>();
1092 for (OspfEligibleRouter router : eligibleRouters) {
1093 if (router.isBdr()) {
1094 declaredAsBdr.add(router);
1095 }
1096 if (!router.isBdr() && !router.isDr()) {
1097 notDrAndBdr.add(router);
1098 }
1099 }
1100
1101 OspfEligibleRouter electedBdr = new OspfEligibleRouter();
1102 if (!declaredAsBdr.isEmpty()) {
1103 if (declaredAsBdr.size() == 1) {
1104 electedBdr = declaredAsBdr.get(0);
1105 } else if (declaredAsBdr.size() > 1) {
1106 electedBdr = selectRouterBasedOnPriority(declaredAsBdr);
1107 }
1108 } else {
1109 if (notDrAndBdr.size() == 1) {
1110 electedBdr = notDrAndBdr.get(0);
1111 } else if (notDrAndBdr.size() > 1) {
1112 electedBdr = selectRouterBasedOnPriority(notDrAndBdr);
1113 }
1114 }
1115
1116 electedBdr.setIsBdr(true);
1117 electedBdr.setIsDr(false);
1118
1119 return electedBdr;
1120 }
1121
1122 /**
1123 * DR Election process.
1124 *
1125 * @param eligibleRouters list of eligible routers.
1126 * @param electedBdr Elected Bdr, OSPF eligible router instance.
1127 * @return OSPF eligible router instance.
1128 */
1129 public OspfEligibleRouter electDr(List<OspfEligibleRouter> eligibleRouters,
1130 OspfEligibleRouter electedBdr) {
1131
1132 List<OspfEligibleRouter> declaredAsDr = new ArrayList<>();
1133 for (OspfEligibleRouter router : eligibleRouters) {
1134 if (router.isDr()) {
1135 declaredAsDr.add(router);
1136 }
1137 }
1138
1139 OspfEligibleRouter electedDr = new OspfEligibleRouter();
1140 if (!declaredAsDr.isEmpty()) {
1141 if (declaredAsDr.size() == 1) {
1142 electedDr = declaredAsDr.get(0);
1143 } else if (eligibleRouters.size() > 1) {
1144 electedDr = selectRouterBasedOnPriority(declaredAsDr);
1145 }
1146 } else {
1147 electedDr = electedBdr;
1148 electedDr.setIsDr(true);
1149 electedDr.setIsBdr(false);
1150 }
1151
1152 return electedDr;
1153 }
1154
1155 /**
1156 * DR election process.
1157 *
1158 * @param routersList list of eligible routers.
1159 * @return OSPF eligible router instance.
1160 */
1161 public OspfEligibleRouter selectRouterBasedOnPriority(List<OspfEligibleRouter> routersList) {
1162
1163 OspfEligibleRouter initialRouter = routersList.get(0);
1164
1165 for (int i = 1; i < routersList.size(); i++) {
1166 OspfEligibleRouter router = routersList.get(i);
1167 if (router.getRouterPriority() > initialRouter.getRouterPriority()) {
1168 initialRouter = router;
1169 } else if (router.getRouterPriority() == initialRouter.getRouterPriority()) {
1170 try {
1171 //if (router.getIpAddress().toInt() > initialRouter.getIpAddress().toInt()) {
1172 if (OspfUtil.ipAddressToLong(router.getIpAddress().toString()) >
1173 OspfUtil.ipAddressToLong(initialRouter.getIpAddress().toString())) {
1174 initialRouter = router;
1175 }
1176 } catch (Exception e) {
1177 log.debug("OSPFInterfaceChannelHandler::selectRouterBasedOnPriority ->" +
1178 " eligibleRouters: {}", initialRouter);
1179 }
1180 }
1181 }
1182
1183 return initialRouter;
1184 }
1185
1186 /**
1187 * Adds device information.
1188 *
1189 * @param ospfRouter OSPF router instance
1190 */
1191 public void addDeviceInformation(OspfRouter ospfRouter) {
1192 controller.addDeviceDetails(ospfRouter);
1193 }
1194
1195 /**
1196 * removes device information.
1197 *
1198 * @param ospfRouter OSPF neighbor instance
1199 */
1200 public void removeDeviceInformation(OspfRouter ospfRouter) {
1201 controller.removeDeviceDetails(ospfRouter);
1202 }
1203
1204 /**
1205 * Adds link information.
1206 *
1207 * @param ospfRouter OSPF router instance
1208 * @param ospfLinkTed list link ted instances
1209 */
1210 public void addLinkInformation(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
1211 controller.addLinkDetails(ospfRouter, ospfLinkTed);
1212 }
1213
1214 /**
1215 * Removes link information.
1216 *
1217 * @param ospfNbr OSPF neighbor instance
1218 */
1219 public void removeLinkInformation(OspfNbr ospfNbr) {
1220 controller.removeLinkDetails(buildOspfRouterDetails(ospfNbr));
1221 }
1222
1223 /**
1224 * Builds router details.
1225 *
1226 * @param ospfNbr OSPF neighbor instance
1227 * @return OSPF router instance
1228 */
1229 private OspfRouter buildOspfRouterDetails(OspfNbr ospfNbr) {
1230 OspfRouter ospfRouter = new OspfRouterImpl();
1231 ospfRouter.setRouterIp(ospfNbr.neighborId());
1232 ospfRouter.setInterfaceId(ospfInterface.ipAddress());
1233 ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
1234
1235 ospfRouter.setDeviceTed(new OspfDeviceTedImpl());
1236
1237 return ospfRouter;
1238 }
1239
1240 /**
1241 * Represents a Hello task which sent a hello message every configured time interval.
1242 */
1243 private class InternalHelloTimer implements Runnable {
1244
1245 /**
1246 * Creates an instance of Hello Timer.
1247 */
1248 InternalHelloTimer() {
1249 }
1250
1251 @Override
1252 public void run() {
1253 if (!isClosed && channel != null && channel.isOpen() && channel.isConnected()) {
1254
1255 HelloPacket hellopacket = new HelloPacket();
1256 //Headers
1257 hellopacket.setOspfVer(OspfUtil.OSPF_VERSION);
1258 hellopacket.setOspftype(OspfPacketType.HELLO.value());
1259 hellopacket.setOspfPacLength(0); //will be modified while encoding
1260 hellopacket.setRouterId(ospfArea.routerId());
1261 hellopacket.setAreaId(ospfArea.areaId());
1262 hellopacket.setChecksum(0); //will be modified while encoding
1263 hellopacket.setAuthType(Integer.parseInt(ospfInterface.authType()));
1264 hellopacket.setAuthentication(Integer.parseInt(ospfInterface.authKey()));
1265 //Body
1266 hellopacket.setNetworkMask(ospfInterface.ipNetworkMask());
1267 hellopacket.setOptions(ospfArea.options());
1268 hellopacket.setHelloInterval(ospfInterface.helloIntervalTime());
1269 hellopacket.setRouterPriority(ospfInterface.routerPriority());
1270 hellopacket.setRouterDeadInterval(ospfInterface.routerDeadIntervalTime());
1271 hellopacket.setDr(ospfInterface.dr());
1272 hellopacket.setBdr(ospfInterface.bdr());
1273
1274 HashMap<String, OspfNbr> listOfNeighbors = ospfInterface.listOfNeighbors();
1275 Set<String> keys = listOfNeighbors.keySet();
1276 Iterator itr = keys.iterator();
1277 while (itr.hasNext()) {
1278 String nbrKey = (String) itr.next();
1279 OspfNbrImpl nbr = (OspfNbrImpl) listOfNeighbors.get(nbrKey);
1280 if (nbr.getState() != OspfNeighborState.DOWN) {
1281 hellopacket.addNeighbor(Ip4Address.valueOf(nbrKey));
1282 }
1283 }
1284 // build a hello Packet
1285 if (channel == null || !channel.isOpen() || !channel.isConnected()) {
1286 log.debug("Hello Packet not sent !!.. Channel Issue...");
1287 return;
1288 }
1289
1290 hellopacket.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
1291 ChannelFuture future = channel.write(hellopacket);
1292 if (future.isSuccess()) {
1293 log.debug("Hello Packet successfully sent !!");
1294 } else {
1295 future.awaitUninterruptibly();
1296 }
1297
1298 }
1299 }
1300 }
1301
1302 /**
1303 * Represents a Wait Timer task which waits the interface state to become WAITING.
1304 * It initiates DR election process.
1305 */
1306 private class InternalWaitTimer implements Runnable {
1307 Channel ch;
1308
1309 /**
1310 * Creates an instance of Wait Timer.
1311 */
1312 InternalWaitTimer() {
1313 this.ch = channel;
1314 }
1315
1316 @Override
1317 public void run() {
1318 log.debug("Wait timer expires...");
1319 if (ch != null && ch.isConnected()) {
1320 try {
1321 waitTimer(ch);
1322 } catch (Exception e) {
1323 log.debug("Exception at wait timer ...!!!");
1324 }
1325
1326 }
1327 }
1328 }
1329
1330 /**
1331 * Represents a task which sent a LS Acknowledge from the link state headers list.
1332 */
1333 private class InternalDelayedAckTimer implements Runnable {
1334 Channel ch;
1335
1336 /**
1337 * Creates an instance of Delayed acknowledge timer.
1338 */
1339 InternalDelayedAckTimer() {
1340 this.ch = channel;
1341 }
1342
1343 @Override
1344 public void run() {
1345 if (!((OspfInterfaceImpl) ospfInterface).linkStateHeaders().isEmpty()) {
1346 isDelayedAckTimerScheduled = true;
1347 if (ch != null && ch.isConnected()) {
1348
1349 List<LsaHeader> listOfLsaHeadersAcknowledged = new ArrayList<>();
1350 List<LsaHeader> listOfLsaHeaders = ((OspfInterfaceImpl) ospfInterface).linkStateHeaders();
1351 log.debug("Delayed Ack, Number of Lsa's to Ack {}", listOfLsaHeaders.size());
1352 Iterator itr = listOfLsaHeaders.iterator();
1353 while (itr.hasNext()) {
1354 LsAcknowledge ackContent = new LsAcknowledge();
1355 //Setting OSPF Header
1356 ackContent.setOspfVer(OspfUtil.OSPF_VERSION);
1357 ackContent.setOspftype(OspfPacketType.LSAACK.value());
1358 ackContent.setRouterId(ospfArea.routerId());
1359 ackContent.setAreaId(ospfArea.areaId());
1360 ackContent.setAuthType(OspfUtil.NOT_ASSIGNED);
1361 ackContent.setAuthentication(OspfUtil.NOT_ASSIGNED);
1362 ackContent.setOspfPacLength(OspfUtil.NOT_ASSIGNED);
1363 ackContent.setChecksum(OspfUtil.NOT_ASSIGNED);
1364 //limit to mtu
1365 int currentLength = OspfUtil.OSPF_HEADER_LENGTH;
1366 int maxSize = ospfInterface.mtu() -
1367 OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
1368 while (itr.hasNext()) {
1369 if ((currentLength + OspfUtil.LSA_HEADER_LENGTH) >= maxSize) {
1370 break;
1371 }
1372 LsaHeader lsaHeader = (LsaHeader) itr.next();
1373 ackContent.addLinkStateHeader(lsaHeader);
1374 currentLength = currentLength + OspfUtil.LSA_HEADER_LENGTH;
1375 listOfLsaHeadersAcknowledged.add(lsaHeader);
1376 log.debug("Delayed Ack, Added Lsa's to Ack {}", lsaHeader);
1377 }
1378
1379 log.debug("Delayed Ack, Number of Lsa's in LsAck packet {}",
1380 ackContent.getLinkStateHeaders().size());
1381
1382 //set the destination
1383 if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
1384 ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR
1385 || ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
1386 ackContent.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
1387 } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
1388 ackContent.setDestinationIp(OspfUtil.ALL_DROUTERS);
1389 }
1390 ch.write(ackContent);
1391 for (LsaHeader lsa : listOfLsaHeadersAcknowledged) {
1392 ((OspfInterfaceImpl) ospfInterface).linkStateHeaders().remove(lsa);
1393 ospfInterface.removeLsaFromNeighborMap(((OspfAreaImpl) ospfArea).getLsaKey(lsa));
1394 }
1395 }
1396 }
1397 }
1398 }
1399 }
1400}