Kiran Ramachandra
Committed by Thomas Vachuska

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

Change-Id: I8955ca10bf966c7b3917a3f3a41037abce87f1c5
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
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 + */
16 +
17 +package org.onosproject.ospf.controller.impl;
18 +
19 +import org.apache.felix.scr.annotations.Reference;
20 +import org.apache.felix.scr.annotations.ReferenceCardinality;
21 +import org.jboss.netty.channel.Channel;
22 +import org.jboss.netty.channel.ChannelFuture;
23 +import org.jboss.netty.channel.ChannelHandlerContext;
24 +import org.jboss.netty.channel.ChannelStateEvent;
25 +import org.jboss.netty.channel.ExceptionEvent;
26 +import org.jboss.netty.channel.MessageEvent;
27 +import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
28 +import org.jboss.netty.handler.timeout.ReadTimeoutException;
29 +import org.onlab.packet.Ip4Address;
30 +import org.onosproject.ospf.controller.LsaWrapper;
31 +import org.onosproject.ospf.controller.OspfArea;
32 +import org.onosproject.ospf.controller.OspfInterface;
33 +import org.onosproject.ospf.controller.OspfLinkTed;
34 +import org.onosproject.ospf.controller.OspfLsa;
35 +import org.onosproject.ospf.controller.OspfNbr;
36 +import org.onosproject.ospf.controller.OspfNeighborState;
37 +import org.onosproject.ospf.controller.OspfRouter;
38 +import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
39 +import org.onosproject.ospf.controller.area.OspfAreaImpl;
40 +import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
41 +import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
42 +import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
43 +import org.onosproject.ospf.controller.util.OspfEligibleRouter;
44 +import org.onosproject.ospf.controller.util.OspfInterfaceType;
45 +import org.onosproject.ospf.exceptions.OspfParseException;
46 +import org.onosproject.ospf.protocol.lsa.LsaHeader;
47 +import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
48 +import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
49 +import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
50 +import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
51 +import org.onosproject.ospf.protocol.ospfpacket.types.HelloPacket;
52 +import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
53 +import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
54 +import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
55 +import org.onosproject.ospf.protocol.util.ChecksumCalculator;
56 +import org.onosproject.ospf.protocol.util.OspfInterfaceState;
57 +import org.onosproject.ospf.protocol.util.OspfPacketType;
58 +import org.onosproject.ospf.protocol.util.OspfParameters;
59 +import org.onosproject.ospf.protocol.util.OspfUtil;
60 +import org.slf4j.Logger;
61 +import org.slf4j.LoggerFactory;
62 +
63 +import java.io.IOException;
64 +import java.nio.channels.ClosedChannelException;
65 +import java.util.ArrayList;
66 +import java.util.HashMap;
67 +import java.util.Iterator;
68 +import java.util.List;
69 +import java.util.ListIterator;
70 +import java.util.Set;
71 +import java.util.concurrent.Executors;
72 +import java.util.concurrent.RejectedExecutionException;
73 +import java.util.concurrent.ScheduledExecutorService;
74 +import java.util.concurrent.ScheduledFuture;
75 +import 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 + */
81 +public 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) {
261 + processOSPFMessage(ospfMessage, ctx);
262 + }
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...!!");
270 + processOSPFMessage(ospfMessage, ctx);
271 + }
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 + */
283 + public void processOSPFMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
284 + log.debug("OspfChannelHandler::processOSPFMessage...!!!");
285 +
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 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
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 + */
16 +package org.onosproject.ospf.controller.lsdb;
17 +
18 +import org.jboss.netty.channel.Channel;
19 +import org.onosproject.ospf.controller.LsaWrapper;
20 +import org.onosproject.ospf.controller.OspfArea;
21 +import org.onosproject.ospf.controller.OspfInterface;
22 +import org.onosproject.ospf.controller.OspfLsaType;
23 +import org.onosproject.ospf.controller.area.OspfAreaImpl;
24 +import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
25 +import org.onosproject.ospf.protocol.lsa.LsaHeader;
26 +import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
27 +import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
28 +import org.onosproject.ospf.protocol.util.ChecksumCalculator;
29 +import org.onosproject.ospf.protocol.util.OspfInterfaceState;
30 +import org.onosproject.ospf.protocol.util.OspfParameters;
31 +import org.onosproject.ospf.protocol.util.OspfUtil;
32 +import org.slf4j.Logger;
33 +import org.slf4j.LoggerFactory;
34 +
35 +import java.util.concurrent.BlockingQueue;
36 +
37 +/**
38 + * Consumes LSA from the Queue and processes it.
39 + * Its a producer consumer implementation using Blocking queue.
40 + */
41 +public class LsaQueueConsumer implements Runnable {
42 + private static final Logger log = LoggerFactory.getLogger(LsaQueueConsumer.class);
43 + private BlockingQueue queue = null;
44 + private Channel channel;
45 + private OspfArea ospfArea;
46 +
47 + /**
48 + * Creates an instance of LSA queue consumer.
49 + *
50 + * @param queue queue instance
51 + * @param channel netty channel instance
52 + * @param ospfArea OSPF area instance
53 + */
54 + public LsaQueueConsumer(BlockingQueue queue, Channel channel, OspfArea ospfArea) {
55 + this.queue = queue;
56 + this.channel = channel;
57 + this.ospfArea = ospfArea;
58 + }
59 +
60 + /**
61 + * Threads run method.
62 + */
63 + public void run() {
64 + log.debug("LSAQueueConsumer:run...!!!");
65 + try {
66 + while (true) {
67 + if (!queue.isEmpty()) {
68 + LsaWrapper wrapper = (LsaWrapper) queue.take();
69 + String lsaProcessing = wrapper.lsaProcessing();
70 + switch (lsaProcessing) {
71 + case OspfParameters.VERIFYCHECKSUM:
72 + log.debug("LSAQueueConsumer: Message - " + OspfParameters.VERIFYCHECKSUM + " consumed.");
73 + processVerifyChecksum(wrapper);
74 + break;
75 + case OspfParameters.REFRESHLSA:
76 + log.debug("LSAQueueConsumer: Message - " + OspfParameters.REFRESHLSA + " consumed.");
77 + processRefreshLsa(wrapper);
78 + break;
79 + case OspfParameters.MAXAGELSA:
80 + log.debug("LSAQueueConsumer: Message - " + OspfParameters.MAXAGELSA + " consumed.");
81 + processMaxAgeLsa(wrapper);
82 + break;
83 + default:
84 + log.debug("Unknown command to process the LSA in queue ...!!!");
85 + break;
86 + }
87 + }
88 + }
89 +
90 + } catch (Exception e) {
91 + log.debug("Error::LSAQueueConsumer::{}", e.getMessage());
92 + }
93 + }
94 +
95 + /**
96 + * Processes verify checksum - checkAges.
97 + *
98 + * @param wrapper LSA wrapper instance
99 + */
100 + private void processVerifyChecksum(LsaWrapper wrapper) throws Exception {
101 + ChecksumCalculator checkSum = new ChecksumCalculator();
102 + if (!checkSum.isValidLsaCheckSum(wrapper.ospfLsa(), ((LsaWrapperImpl) wrapper).lsaHeader().lsType(),
103 + OspfUtil.LSAPACKET_CHECKSUM_POS1,
104 + OspfUtil.LSAPACKET_CHECKSUM_POS2)) {
105 + log.debug("LSAQueueConsumer::Checksum mismatch. Received LSA packet type {} ",
106 + ((LsaWrapperImpl) wrapper).lsaHeader().lsType());
107 +
108 + //Checksum Invalid
109 + //RFC 2328 Restart the Router.
110 + //Currently we are not restarting. We are not handling this case.
111 + }
112 + }
113 +
114 + /**
115 + * Process refresh LSA.
116 + *
117 + * @param wrapper LSA wrapper instance
118 + */
119 + private void processRefreshLsa(LsaWrapper wrapper) throws Exception {
120 + if (wrapper.isSelfOriginated()) { //self originated
121 + //set the destination
122 + OspfInterface ospfInterface = wrapper.ospfInterface();
123 + if (ospfInterface != null) {
124 + LsaHeader header = ((LsaWrapperImpl) wrapper).lsaHeader();
125 + header.setAge(wrapper.currentAge());
126 + if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR) {
127 + if (header.lsType() == OspfLsaType.ROUTER.value()) {
128 + RouterLsa routerLsa = ((OspfAreaImpl) ospfArea).buildRouterLsa(ospfInterface);
129 + ((OspfAreaImpl) ospfArea).addLsa(routerLsa, true, ospfInterface);
130 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(routerLsa);
131 + } else if (header.lsType() == OspfLsaType.NETWORK.value()) {
132 + if (ospfInterface.listOfNeighbors().size() > 0) {
133 + NetworkLsa networkLsa = ((OspfAreaImpl) ospfArea).buildNetworkLsa(
134 + ospfInterface.ipAddress(), ospfInterface.ipNetworkMask());
135 + ospfArea.addLsa(networkLsa, true, ospfInterface);
136 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(networkLsa);
137 + }
138 + }
139 + }
140 +
141 + if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
142 + ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT ||
143 + ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
144 + ospfArea.refreshArea(ospfInterface);
145 + }
146 + log.debug("LSAQueueConsumer: processRefreshLsa - Flooded SelfOriginated LSA {}",
147 + ((LsaWrapperImpl) wrapper).lsaHeader());
148 + }
149 + }
150 + }
151 +
152 + /**
153 + * Process max age LSA.
154 + *
155 + * @param wrapper LSA wrapper instance
156 + */
157 + private void processMaxAgeLsa(LsaWrapper wrapper) {
158 + //set the destination
159 + OspfInterface ospfInterface = wrapper.ospfInterface();
160 + if (ospfInterface != null) {
161 + LsaHeader header = (LsaHeader) wrapper.ospfLsa().lsaHeader();
162 + header.setAge(OspfParameters.MAXAGE);
163 + ((LsaWrapperImpl) wrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
164 + if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
165 + ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
166 + //remove from db
167 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(((LsaWrapperImpl) wrapper).lsaHeader());
168 + ((OspfAreaImpl) ospfArea).deleteLsa(((LsaWrapperImpl) wrapper).lsaHeader());
169 + } else {
170 + ((OspfAreaImpl) ospfArea).deleteLsa(((LsaWrapperImpl) wrapper).lsaHeader());
171 + }
172 + log.debug("LSAQueueConsumer: processMaxAgeLsa - Flooded SelfOriginated-Max Age LSA {}",
173 + ((LsaWrapperImpl) wrapper).lsaHeader());
174 + }
175 + }
176 +
177 + /**
178 + * Sets the channel.
179 + *
180 + * @param channel channel instance
181 + */
182 + public void setChannel(Channel channel) {
183 + this.channel = channel;
184 + }
185 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
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 + */
16 +package org.onosproject.ospf.controller.lsdb;
17 +
18 +import com.google.common.base.Objects;
19 +import org.jboss.netty.channel.Channel;
20 +import org.onosproject.ospf.controller.LsaBin;
21 +import org.onosproject.ospf.controller.LsaWrapper;
22 +import org.onosproject.ospf.controller.LsdbAge;
23 +import org.onosproject.ospf.controller.OspfArea;
24 +import org.onosproject.ospf.controller.area.OspfAreaImpl;
25 +import org.onosproject.ospf.protocol.util.OspfParameters;
26 +import org.slf4j.Logger;
27 +import org.slf4j.LoggerFactory;
28 +
29 +import java.util.Map;
30 +import java.util.concurrent.ArrayBlockingQueue;
31 +import java.util.concurrent.BlockingQueue;
32 +import java.util.concurrent.ConcurrentHashMap;
33 +import java.util.concurrent.Executors;
34 +import java.util.concurrent.ScheduledExecutorService;
35 +import java.util.concurrent.TimeUnit;
36 +
37 +/**
38 + * Representation of LSDB Aging process.
39 + */
40 +public class LsdbAgeImpl implements LsdbAge {
41 +
42 + private static final Logger log =
43 + LoggerFactory.getLogger(LsdbAgeImpl.class);
44 + protected int ageCounter = 0;
45 + private InternalAgeTimer dbAgeTimer;
46 + private ScheduledExecutorService exServiceage;
47 + // creating age bins of MAXAGE
48 + private Map<Integer, LsaBin> ageBins = new ConcurrentHashMap<>(OspfParameters.MAXAGE);
49 + private LsaBin maxAgeBin = new LsaBinImpl(OspfParameters.MAXAGE);
50 + private int ageCounterRollOver = 0;
51 + private Channel channel = null;
52 + private LsaQueueConsumer queueConsumer = null;
53 + private BlockingQueue<LsaWrapper> lsaQueue = new ArrayBlockingQueue(1024);
54 + private OspfArea ospfArea = null;
55 +
56 +
57 + /**
58 + * Creates an instance of LSDB age.
59 + *
60 + * @param ospfArea OSPF area instance
61 + */
62 + public LsdbAgeImpl(OspfArea ospfArea) {
63 + // create LSBin's in the HashMap.
64 + for (int i = 0; i < OspfParameters.MAXAGE; i++) {
65 + LsaBin lsaBin = new LsaBinImpl(i);
66 + ageBins.put(i, lsaBin);
67 + }
68 + this.ospfArea = ospfArea;
69 + }
70 +
71 + @Override
72 + public boolean equals(Object o) {
73 + if (this == o) {
74 + return true;
75 + }
76 + if (o == null || getClass() != o.getClass()) {
77 + return false;
78 + }
79 + LsdbAgeImpl that = (LsdbAgeImpl) o;
80 + return Objects.equal(ageBins, that.ageBins) &&
81 + Objects.equal(ageCounter, that.ageCounter) &&
82 + Objects.equal(ageCounterRollOver, that.ageCounterRollOver) &&
83 + Objects.equal(lsaQueue, lsaQueue);
84 + }
85 +
86 + @Override
87 + public int hashCode() {
88 + return Objects.hashCode(ageBins, ageCounter, ageCounterRollOver, lsaQueue);
89 + }
90 +
91 + /**
92 + * Adds LSA to bin.
93 + *
94 + * @param binKey key to store in bin
95 + * @param lsaBin LSA bin instance
96 + */
97 + public void addLsaBin(Integer binKey, LsaBin lsaBin) {
98 + if (!ageBins.containsKey(binKey)) {
99 + ageBins.put(binKey, lsaBin);
100 + }
101 + }
102 +
103 + /**
104 + * Gets LSA from Bin.
105 + *
106 + * @param binKey key
107 + * @return bin instance
108 + */
109 + public LsaBin getLsaBin(Integer binKey) {
110 +
111 + return ageBins.get(binKey);
112 + }
113 +
114 + /**
115 + * Adds the LSA to maxAge bin.
116 + *
117 + * @param key key
118 + * @param wrapper wrapper instance
119 + */
120 + public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
121 + maxAgeBin.addOspfLsa(key, wrapper);
122 + }
123 +
124 + /**
125 + * Removes LSA from Bin.
126 + *
127 + * @param lsaWrapper wrapper instance
128 + */
129 + public void removeLsaFromBin(LsaWrapper lsaWrapper) {
130 + if (ageBins.containsKey(lsaWrapper.binNumber())) {
131 + LsaBin lsaBin = ageBins.get(lsaWrapper.binNumber());
132 + lsaBin.removeOspfLsa(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
133 + lsaWrapper).lsaHeader()), lsaWrapper);
134 + }
135 + }
136 +
137 + /**
138 + * Starts the aging timer and queue consumer.
139 + */
140 + public void startDbAging() {
141 + startDbAgeTimer();
142 + queueConsumer = new LsaQueueConsumer(lsaQueue, channel, ospfArea);
143 + new Thread(queueConsumer).start();
144 + }
145 +
146 +
147 + /**
148 + * Gets called every 1 second as part of the timer.
149 + */
150 + public void ageLsaAndFlood() {
151 + //every 5 mins checksum validation
152 + checkAges();
153 + //every 30 mins - flood LSA
154 + refreshLsa();
155 + //every 60 mins - flood LSA
156 + maxAgeLsa();
157 +
158 + if (ageCounter == OspfParameters.MAXAGE) {
159 + ageCounter = 0;
160 + ageCounterRollOver++;
161 + } else {
162 + //increment age bin
163 + ageCounter++;
164 + }
165 + }
166 +
167 + /**
168 + * If the LSA have completed the MaxAge - they are moved called stop aging and flooded.
169 + */
170 + public void maxAgeLsa() {
171 + if (ageCounter == 0) {
172 + return;
173 + }
174 + //Get from Age Bins
175 + LsaBin lsaBin = ageBins.get(ageCounter - 1);
176 + if (lsaBin == null) {
177 + return;
178 + }
179 + Map lsaBinMap = lsaBin.listOfLsa();
180 + for (Object key : lsaBinMap.keySet()) {
181 + LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
182 + if (lsa.currentAge() == OspfParameters.MAXAGE) {
183 + lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
184 + log.debug("Lsa picked for maxage flooding. Age Counter: {}, AgeCounterRollover: {}, " +
185 + "AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
186 + ageCounter, ageCounterRollOver, lsa.currentAge(), lsa.lsaType(), key);
187 + //add it to lsaQueue for processing
188 + try {
189 + lsaQueue.put(lsa);
190 + //remove from bin
191 + lsaBin.removeOspfLsa((String) key, lsa);
192 + } catch (InterruptedException e) {
193 + log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
194 + }
195 + }
196 + }
197 +
198 + //Get from maxAgeBin
199 + Map lsaMaxAgeBinMap = maxAgeBin.listOfLsa();
200 + for (Object key : lsaMaxAgeBinMap.keySet()) {
201 + LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get((String) key);
202 + lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
203 + log.debug("Lsa picked for maxage flooding. Age Counter: {}, LSA Type: {}, LSA Key: {}",
204 + ageCounter, lsa.lsaType(), key);
205 + //add it to lsaQueue for processing
206 + try {
207 + lsaQueue.put(lsa);
208 + //remove from bin
209 + maxAgeBin.removeOspfLsa((String) key, lsa);
210 + } catch (InterruptedException e) {
211 + log.debug("Error::LSDBAge::maxAgeLsa::{}", e.getMessage());
212 + }
213 + }
214 + }
215 +
216 +
217 + /*
218 + * If the LSA is in age bin of 1800 - it's pushed into refresh list.
219 + */
220 + public void refreshLsa() {
221 + int binNumber;
222 + if (ageCounter < OspfParameters.LSREFRESHTIME) {
223 + binNumber = ageCounter + OspfParameters.LSREFRESHTIME;
224 + } else {
225 + binNumber = ageCounter - OspfParameters.LSREFRESHTIME;
226 + }
227 + LsaBin lsaBin = ageBins.get(binNumber);
228 + if (lsaBin == null) {
229 + return;
230 + }
231 + Map lsaBinMap = lsaBin.listOfLsa();
232 + for (Object key : lsaBinMap.keySet()) {
233 + LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
234 + try {
235 + if (lsa.isSelfOriginated()) {
236 + log.debug("Lsa picked for refreshLsa. binNumber: {}, LSA Type: {}, LSA Key: {}",
237 + binNumber, lsa.lsaType(), key);
238 + lsa.setLsaProcessing(OspfParameters.REFRESHLSA);
239 + lsaQueue.put(lsa);
240 + //remove from bin
241 + lsaBin.removeOspfLsa((String) key, lsa);
242 + }
243 + } catch (InterruptedException e) {
244 + log.debug("Error::LSDBAge::refreshLsa::{}", e.getMessage());
245 + }
246 + }
247 + }
248 +
249 + /**
250 + * Verify the checksum for the LSAs who are in bins of 300 and it's multiples.
251 + */
252 + public void checkAges() {
253 + //evry 5 min age counter + multiples of 300
254 + for (int age = OspfParameters.CHECKAGE; age < OspfParameters.MAXAGE;
255 + age += OspfParameters.CHECKAGE) {
256 + LsaBin lsaBin = ageBins.get(age2Bin(age));
257 + if (lsaBin == null) {
258 + continue;
259 + }
260 + Map lsaBinMap = lsaBin.listOfLsa();
261 + for (Object key : lsaBinMap.keySet()) {
262 + LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
263 + lsa.setLsaProcessing(OspfParameters.VERIFYCHECKSUM);
264 + try {
265 + lsaQueue.put(lsa);
266 + } catch (InterruptedException e) {
267 + log.debug("Error::LSDBAge::checkAges::{}", e.getMessage());
268 + }
269 + }
270 + }
271 + }
272 +
273 +
274 + /**
275 + * Starts DB age timer method start the aging task.
276 + */
277 + private void startDbAgeTimer() {
278 + log.debug("OSPFNbr::startWaitTimer");
279 + dbAgeTimer = new InternalAgeTimer();
280 + //from 1 sec
281 + exServiceage = Executors.newSingleThreadScheduledExecutor();
282 + exServiceage.scheduleAtFixedRate(dbAgeTimer, OspfParameters.AGECOUNTER,
283 + OspfParameters.AGECOUNTER, TimeUnit.SECONDS);
284 + }
285 +
286 + /**
287 + * Stops the aging task.
288 + */
289 + private void stopDbAgeTimer() {
290 + log.debug("OSPFNbr::stopWaitTimer ");
291 + exServiceage.shutdown();
292 + }
293 +
294 +
295 + /**
296 + * Gets the netty channel.
297 + *
298 + * @return netty channel
299 + */
300 + public Channel getChannel() {
301 + return channel;
302 + }
303 +
304 + /**
305 + * Sets the netty channel.
306 + *
307 + * @param channel netty channel
308 + */
309 + public void setChannel(Channel channel) {
310 +
311 + this.channel = channel;
312 + if (queueConsumer != null) {
313 + queueConsumer.setChannel(channel);
314 + }
315 + }
316 +
317 + /**
318 + * Gets the age counter.
319 + *
320 + * @return ageCounter
321 + */
322 + public int getAgeCounter() {
323 + return ageCounter;
324 + }
325 +
326 + /**
327 + * Gets the age counter roll over value.
328 + *
329 + * @return the age counter roll over value
330 + */
331 + public int getAgeCounterRollOver() {
332 + return ageCounterRollOver;
333 + }
334 +
335 + /**
336 + * Gets the max age bin.
337 + *
338 + * @return lsa bin instance
339 + */
340 + public LsaBin getMaxAgeBin() {
341 + return maxAgeBin;
342 + }
343 +
344 + /**
345 + * Gets the bin number.
346 + *
347 + * @param x Can be either age or ageCounter
348 + * @return bin number.
349 + */
350 + public int age2Bin(int x) {
351 + if (x <= ageCounter) {
352 + return (ageCounter - x);
353 + } else {
354 + return ((OspfParameters.MAXAGE - 1) + (ageCounter - x));
355 + }
356 + }
357 +
358 + /**
359 + * Runnable task which runs every second and calls aging process.
360 + */
361 + private class InternalAgeTimer implements Runnable {
362 +
363 + /**
364 + * Constructor.
365 + */
366 + InternalAgeTimer() {
367 + log.debug("Starts::LsdbAge::AgeTimer...!!! ");
368 + }
369 +
370 + @Override
371 + public void run() {
372 + ageLsaAndFlood();
373 + }
374 + }
375 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2016 Open Networking Laboratory
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 + */
16 +
17 +/**
18 + * Implementation of the OSPF controller.
19 + */
20 +package org.onosproject.ospf.controller;
...\ No newline at end of file ...\ No newline at end of file