Kiran Ramachandra
Committed by Thomas Vachuska

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

Change-Id: I592453c21440afa5240c74dc4e9e134f876c89b3
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.area;
17 +
18 +import com.fasterxml.jackson.annotation.JsonProperty;
19 +import com.google.common.base.MoreObjects;
20 +import com.google.common.base.Objects;
21 +import org.onlab.packet.Ip4Address;
22 +import org.onosproject.ospf.controller.LsaWrapper;
23 +import org.onosproject.ospf.controller.OspfArea;
24 +import org.onosproject.ospf.controller.OspfAreaAddressRange;
25 +import org.onosproject.ospf.controller.OspfInterface;
26 +import org.onosproject.ospf.controller.OspfLsa;
27 +import org.onosproject.ospf.controller.OspfLsaType;
28 +import org.onosproject.ospf.controller.OspfLsdb;
29 +import org.onosproject.ospf.controller.OspfNbr;
30 +import org.onosproject.ospf.controller.OspfNeighborState;
31 +import org.onosproject.ospf.controller.impl.OspfNbrImpl;
32 +import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
33 +import org.onosproject.ospf.protocol.lsa.LsaHeader;
34 +import org.onosproject.ospf.protocol.lsa.subtypes.OspfLsaLink;
35 +import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
36 +import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
37 +import org.onosproject.ospf.protocol.util.ChecksumCalculator;
38 +import org.onosproject.ospf.protocol.util.OspfInterfaceState;
39 +import org.onosproject.ospf.protocol.util.OspfParameters;
40 +import org.onosproject.ospf.protocol.util.OspfUtil;
41 +import org.slf4j.Logger;
42 +import org.slf4j.LoggerFactory;
43 +
44 +import java.net.InetAddress;
45 +import java.util.ArrayList;
46 +import java.util.Arrays;
47 +import java.util.Iterator;
48 +import java.util.List;
49 +import java.util.Map;
50 +
51 +/**
52 + * Representation an OSPF area and related information.
53 + */
54 +public class OspfAreaImpl implements OspfArea {
55 + private static final Logger log = LoggerFactory.getLogger(OspfAreaImpl.class);
56 + /**
57 + * Address ranges in order to aggregate routing information at area.
58 + * boundaries. Each address range is specified by an [address,mask] pair and
59 + * a status indication of either Advertise or DoNotAdvertise
60 + */
61 + private List<OspfAreaAddressRange> addressRanges;
62 + /**
63 + * This parameter indicates whether the area can carry data traffic that.
64 + * neither originates nor terminates in the area itself.
65 + */
66 + private boolean transitCapability;
67 + /**
68 + * Whether AS-external-LSAs will be flooded into/throughout the area.
69 + */
70 + private boolean externalRoutingCapability;
71 + /**
72 + * Indicates the cost of the default summary-LSA.
73 + */
74 + private int stubCost;
75 + /**
76 + * Represents a list of all router's interfaces associated with this area.
77 + */
78 + private List<OspfInterface> interfacesLst;
79 + /**
80 + * The LS Database for this area. It includes router-LSAs, network-LSAs and.
81 + * summary-LSAs. AS-external-LSAs are hold in the OSPF class itself.
82 + */
83 + private OspfLsdbImpl database;
84 + /**
85 + * A 32-bit number identifying the area.
86 + */
87 + private Ip4Address areaId;
88 + /**
89 + * Router ID.
90 + */
91 + private Ip4Address routerId;
92 + /**
93 + * Represents Options like external, opaque capabilities.
94 + */
95 + private int options;
96 + /**
97 + * Represents Opaque Enable or not.
98 + */
99 + private boolean isOpaqueEnable;
100 +
101 + /**
102 + * Creates an instance of area implementation.
103 + */
104 + public OspfAreaImpl() {
105 + database = new OspfLsdbImpl(this);
106 + }
107 +
108 + @Override
109 + public boolean equals(Object o) {
110 + if (this == o) {
111 + return true;
112 + }
113 + if (o == null || getClass() != o.getClass()) {
114 + return false;
115 + }
116 + OspfAreaImpl that = (OspfAreaImpl) o;
117 + return Objects.equal(areaId, that.areaId) &&
118 + Objects.equal(routerId, that.routerId) &&
119 + Objects.equal(addressRanges.size(), that.addressRanges.size()) &&
120 + Objects.equal(transitCapability, that.transitCapability) &&
121 + Objects.equal(externalRoutingCapability, that.externalRoutingCapability) &&
122 + Objects.equal(stubCost, that.stubCost) &&
123 + Objects.equal(interfacesLst.size(), that.interfacesLst.size()) &&
124 + Objects.equal(database, that.database);
125 + }
126 +
127 + @Override
128 + public int hashCode() {
129 + return Objects.hashCode(areaId, routerId, addressRanges, transitCapability, externalRoutingCapability,
130 + stubCost, interfacesLst, database);
131 + }
132 +
133 + /**
134 + * Gets the router id.
135 + *
136 + * @return router id
137 + */
138 + public Ip4Address routerId() {
139 + return routerId;
140 + }
141 +
142 + /**
143 + * Sets the router id.
144 + *
145 + * @param routerId router id
146 + */
147 + @JsonProperty("routerId")
148 + public void setRouterId(Ip4Address routerId) {
149 + this.routerId = routerId;
150 + }
151 +
152 + /**
153 + * Sets opaque enabled to true or false.
154 + *
155 + * @param isOpaqueEnable true if opaque enabled else false
156 + */
157 + @JsonProperty("isOpaqueEnable")
158 + public void setIsOpaqueEnabled(boolean isOpaqueEnable) {
159 + this.isOpaqueEnable = isOpaqueEnable;
160 + }
161 +
162 + /**
163 + * Gets is opaque enabled or not.
164 + *
165 + * @return true if opaque enabled else false
166 + */
167 + public boolean isOpaqueEnabled() {
168 + return this.isOpaqueEnable;
169 + }
170 +
171 + /**
172 + * Initializes link state database.
173 + */
174 + public void initializeDb() {
175 +
176 + database.initializeDb();
177 + }
178 +
179 + /**
180 + * Refreshes the OSPF area information .
181 + * Gets called as soon as the interface is down or neighbor full Router LSA is updated.
182 + *
183 + * @param ospfInterface OSPF interface instance
184 + */
185 + @Override
186 + public void refreshArea(OspfInterface ospfInterface) {
187 + OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
188 + log.debug("Inside refreshArea...!!!");
189 + //If interface state is DR build network LSA.
190 + if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
191 + if (ospfInterface.listOfNeighbors().size() > 0) {
192 + //Get the NetworkLsa
193 + NetworkLsa networkLsa = null;
194 + try {
195 + networkLsa = buildNetworkLsa(ospfInterface.ipAddress(), ospfInterface.ipNetworkMask());
196 + } catch (Exception e) {
197 + log.debug("Error while building NetworkLsa {}", e.getMessage());
198 + }
199 + //Add the NetworkLsa to lsdb
200 + database.addLsa(networkLsa, true, ospfInterface);
201 + addToOtherNeighborLsaTxList(networkLsa);
202 + } else {
203 + log.debug("No Neighbors hence not creating NetworkLSA...!!!");
204 + }
205 + }
206 + //Get the router LSA
207 + RouterLsa routerLsa = null;
208 + try {
209 + routerLsa = buildRouterLsa(ospfInterface);
210 + } catch (Exception e) {
211 + log.debug("Error while building RouterLsa {}", e.getMessage());
212 + }
213 + //Add the RouterLSA to lsdb
214 + database.addLsa(routerLsa, true, ospfInterface);
215 + addToOtherNeighborLsaTxList(routerLsa);
216 + }
217 +
218 + /**
219 + * Builds a network LSA.
220 + *
221 + * @param interfaceIp interface IP address
222 + * @param mask interface network mask
223 + * @return NetworkLsa instance
224 + * @throws Exception might throws exception
225 + */
226 + public NetworkLsa buildNetworkLsa(Ip4Address interfaceIp, Ip4Address mask) throws Exception {
227 + // generate the Router-LSA for this Area.
228 + NetworkLsa networkLsa = new NetworkLsa();
229 + networkLsa.setAdvertisingRouter(routerId);
230 + networkLsa.setLinkStateId(interfaceIp.toString());
231 + networkLsa.setLsType(OspfLsaType.NETWORK.value());
232 + networkLsa.setAge(1);
233 + networkLsa.setOptions(2);
234 + networkLsa.setNetworkMask(mask);
235 + //Adding our own router.
236 + networkLsa.addAttachedRouter(routerId());
237 + Iterator iter = interfacesLst.iterator();
238 + OspfInterfaceImpl ospfInterface = null;
239 + while (iter.hasNext()) {
240 + ospfInterface = (OspfInterfaceImpl) iter.next();
241 + if (ospfInterface.ipAddress().equals(interfaceIp)) {
242 + break;
243 + }
244 + }
245 + if (ospfInterface != null) {
246 + List<OspfNbr> neighborsInFullState = getNeighborsInFullState(ospfInterface);
247 + if (neighborsInFullState != null) {
248 + for (OspfNbr ospfnbr : neighborsInFullState) {
249 + networkLsa.addAttachedRouter(ospfnbr.neighborId());
250 + log.debug("Adding attached neighbor:: {}", ospfnbr.neighborId());
251 + }
252 + }
253 + }
254 + networkLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.NETWORK));
255 + //Find the byte length and add it in lsa object
256 + ChecksumCalculator checksum = new ChecksumCalculator();
257 + byte[] lsaBytes = networkLsa.asBytes();
258 + networkLsa.setLsPacketLen(lsaBytes.length);
259 + //Convert lsa object to byte again to reflect the packet length which we added.
260 + lsaBytes = networkLsa.asBytes();
261 + //find the checksum
262 + byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
263 + OspfUtil.LSAPACKET_CHECKSUM_POS1,
264 + OspfUtil.LSAPACKET_CHECKSUM_POS2);
265 + int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
266 + networkLsa.setLsCheckSum(checkSumVal);
267 + return networkLsa;
268 + }
269 +
270 + /**
271 + * Builds Router LSA.
272 + *
273 + * @param ospfInterface Interface instance
274 + * @return routerLsa Router LSA instance
275 + * @throws Exception might throws exception
276 + */
277 + public RouterLsa buildRouterLsa(OspfInterface ospfInterface) throws Exception {
278 + // generate the Router-LSA for this Area.
279 + RouterLsa routerLsa = new RouterLsa();
280 + routerLsa.setAdvertisingRouter(routerId);
281 + routerLsa.setLinkStateId(routerId.toString());
282 + routerLsa.setLsType(OspfLsaType.ROUTER.value());
283 + routerLsa.setAge(1);
284 + routerLsa.setOptions(options);
285 + routerLsa.setAreaBorderRouter(false);
286 + routerLsa.setAsBoundaryRouter(false);
287 + routerLsa.setVirtualEndPoint(false);
288 + buildLinkForRouterLsa(routerLsa, ospfInterface);
289 + routerLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.ROUTER));
290 + //Find the byte length and add it in lsa object
291 + ChecksumCalculator checksum = new ChecksumCalculator();
292 + byte[] lsaBytes = routerLsa.asBytes();
293 + routerLsa.setLsPacketLen(lsaBytes.length);
294 + //Convert lsa object to byte again to reflect the packet length whic we added.
295 + lsaBytes = routerLsa.asBytes();
296 + //find the checksum
297 + byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
298 + OspfUtil.LSAPACKET_CHECKSUM_POS1,
299 + OspfUtil.LSAPACKET_CHECKSUM_POS2);
300 + int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
301 + routerLsa.setLsCheckSum(checkSumVal);
302 + return routerLsa;
303 + }
304 +
305 + /**
306 + * Builds LSA link for router LSA.
307 + *
308 + * @param routerLsa router LSA instance
309 + * @param ospfInterface interface instance
310 + */
311 + private void buildLinkForRouterLsa(RouterLsa routerLsa, OspfInterface ospfInterface) {
312 + OspfInterfaceImpl nextInterface;
313 + Iterator interfaces = interfacesLst.iterator();
314 + while (interfaces.hasNext()) {
315 + nextInterface = (OspfInterfaceImpl) interfaces.next();
316 + if (nextInterface.state() == OspfInterfaceState.DOWN) {
317 + continue;
318 + } else if (nextInterface.state() == OspfInterfaceState.LOOPBACK) {
319 + OspfLsaLink link = new OspfLsaLink();
320 + link.setLinkData("-1");
321 + link.setLinkId(nextInterface.ipAddress().toString());
322 + link.setLinkType(3);
323 + link.setMetric(0);
324 + link.setTos(0);
325 + routerLsa.addRouterLink(link);
326 + routerLsa.incrementLinkNo();
327 + } else if (nextInterface.state() == OspfInterfaceState.POINT2POINT) {
328 + // adding all neighbour routers
329 + List<OspfNbr> neighborsInFullState = getNeighborsInFullState(nextInterface);
330 + if (neighborsInFullState != null) {
331 + log.debug("Adding OspfLsaLink ::neighborsInFullState {}, InterfaceIP: {}",
332 + neighborsInFullState.size(), nextInterface.ipAddress());
333 + for (OspfNbr ospfnbr : neighborsInFullState) {
334 + OspfLsaLink link = new OspfLsaLink();
335 + link.setLinkData(nextInterface.ipAddress().toString());
336 + link.setLinkId(ospfnbr.neighborId().toString());
337 + link.setLinkType(1);
338 + link.setMetric(0);
339 + link.setTos(0);
340 + routerLsa.addRouterLink(link);
341 + routerLsa.incrementLinkNo();
342 + log.debug("Added OspfLsaLink :: {}, neighborIP: {}, routerLinks: {}",
343 + ospfnbr.neighborId(), ospfnbr.neighborIpAddr(), routerLsa.noLink());
344 + }
345 + }
346 + // adding the self address
347 + OspfLsaLink link = new OspfLsaLink();
348 + link.setLinkData(nextInterface.ipNetworkMask().toString());
349 + link.setLinkId(nextInterface.ipAddress().toString());
350 + link.setLinkType(3);
351 + link.setMetric(0);
352 + link.setTos(0);
353 + routerLsa.addRouterLink(link);
354 + routerLsa.incrementLinkNo();
355 + } else {
356 + buildLinkForRouterLsaBroadcast(routerLsa, nextInterface);
357 + }
358 + }
359 + }
360 +
361 + /**
362 + * Builds LSA link for router LSA.
363 + *
364 + * @param routerLsa router LSA instance
365 + * @param ospfInterface interface instance
366 + */
367 + private void buildLinkForRouterLsaBroadcast(RouterLsa routerLsa, OspfInterface ospfInterface) {
368 + OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
369 + if (ospfInterfaceImpl.state() == OspfInterfaceState.WAITING) {
370 + OspfLsaLink link = new OspfLsaLink();
371 + link.setLinkData(ospfInterface.ipNetworkMask().toString());
372 + //Link id should be set to ip network number
373 + link.setLinkId(ospfInterface.ipAddress().toString());
374 + link.setLinkType(3);
375 + link.setMetric(0);
376 + link.setTos(0);
377 + routerLsa.addRouterLink(link);
378 + routerLsa.incrementLinkNo();
379 + } else if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
380 + OspfLsaLink link = new OspfLsaLink();
381 + link.setLinkData(ospfInterface.ipAddress().toString());
382 + link.setLinkId(ospfInterface.ipAddress().toString());
383 + link.setLinkType(2);
384 + link.setMetric(0);
385 + link.setTos(0);
386 + routerLsa.addRouterLink(link);
387 + routerLsa.incrementLinkNo();
388 + } else if (ospfInterfaceImpl.state() == OspfInterfaceState.BDR ||
389 + ospfInterfaceImpl.state() == OspfInterfaceState.DROTHER) {
390 + OspfLsaLink link = new OspfLsaLink();
391 + link.setLinkData(ospfInterface.ipAddress().toString());
392 + link.setLinkId(ospfInterface.dr().toString());
393 + link.setLinkType(2);
394 + link.setMetric(0);
395 + link.setTos(0);
396 + routerLsa.addRouterLink(link);
397 + routerLsa.incrementLinkNo();
398 + }
399 + }
400 +
401 + /**
402 + * Gets the area id.
403 + *
404 + * @return area id
405 + */
406 + public Ip4Address areaId() {
407 + return areaId;
408 + }
409 +
410 + /**
411 + * Sets the area id.
412 + *
413 + * @param areaId area id
414 + */
415 + @JsonProperty("areaId")
416 + public void setAreaId(Ip4Address areaId) {
417 + this.areaId = areaId;
418 + }
419 +
420 + /**
421 + * Gets address range.
422 + *
423 + * @return list of area address ranges
424 + */
425 + public List<OspfAreaAddressRange> addressRanges() {
426 + return addressRanges;
427 + }
428 +
429 + /**
430 + * Sets the area address ranges.
431 + *
432 + * @param addressRanges list of area address range
433 + */
434 + @JsonProperty("addressRange")
435 + public void setAddressRanges(List<OspfAreaAddressRange> addressRanges) {
436 + this.addressRanges = addressRanges;
437 + }
438 +
439 + /**
440 + * Gets is transit capable or not.
441 + *
442 + * @return true if transit capable, else false
443 + */
444 + public boolean isTransitCapability() {
445 + return transitCapability;
446 + }
447 +
448 + /**
449 + * Sets transit capability.
450 + *
451 + * @param transitCapability true if transit capable, else false
452 + */
453 + @JsonProperty("transitCapability")
454 + public void setTransitCapability(boolean transitCapability) {
455 + this.transitCapability = transitCapability;
456 + }
457 +
458 + /**
459 + * Gets external routing capability.
460 + *
461 + * @return true if external routing capable, else false
462 + */
463 + public boolean isExternalRoutingCapability() {
464 + return externalRoutingCapability;
465 + }
466 +
467 + /**
468 + * Sets external routing capability.
469 + *
470 + * @param externalRoutingCapability true if external routing capable, else false
471 + */
472 + @JsonProperty("externalRoutingCapability")
473 + public void setExternalRoutingCapability(boolean externalRoutingCapability) {
474 + this.externalRoutingCapability = externalRoutingCapability;
475 + }
476 +
477 + /**
478 + * Gets the stub cost.
479 + *
480 + * @return stub cost
481 + */
482 + public int stubCost() {
483 + return stubCost;
484 + }
485 +
486 + /**
487 + * Sets the stub cost.
488 + *
489 + * @param stubCost stub cost
490 + */
491 + @JsonProperty("stubCost")
492 + public void setStubCost(int stubCost) {
493 + this.stubCost = stubCost;
494 + }
495 +
496 + /**
497 + * Gets the list of interfaces in this area.
498 + *
499 + * @return list of interfaces
500 + */
501 + public List<OspfInterface> getInterfacesLst() {
502 + return interfacesLst;
503 + }
504 +
505 + /**
506 + * Sets the list of interfaces attached to the area.
507 + *
508 + * @param interfacesLst list of OspfInterface instances
509 + */
510 + @JsonProperty("interface")
511 + public void setInterfacesLst(List<OspfInterface> interfacesLst) {
512 + this.interfacesLst = interfacesLst;
513 + }
514 +
515 + /**
516 + * Checks all neighbors belonging to this area whether they are in state EXCHANGE or LOADING.
517 + * Return false if there is at least one, else return true. This Method is used by
518 + * "processReceivedLsa()" in the neighbor class.
519 + *
520 + * @return boolean indicating that there is no Neighbor in Database Exchange
521 + */
522 + public boolean noNeighborInLsaExchangeProcess() {
523 + OspfInterfaceImpl nextInterface;
524 + OspfNeighborState nextNeighborState;
525 + Iterator interfaces = interfacesLst.iterator();
526 + while (interfaces.hasNext()) {
527 + nextInterface = (OspfInterfaceImpl) interfaces.next();
528 + Iterator neighbors = nextInterface.listOfNeighbors().values().iterator();
529 + while (neighbors.hasNext()) {
530 + nextNeighborState = ((OspfNbrImpl) neighbors.next()).getState();
531 + if (nextNeighborState == OspfNeighborState.EXCHANGE ||
532 + nextNeighborState == OspfNeighborState.LOADING) {
533 + return false;
534 + }
535 + }
536 + }
537 + return true;
538 + }
539 +
540 + /**
541 + * Gets header of all types of LSAs.
542 + *
543 + * @param excludeMaxAgeLsa need to include(true) or exclude(false) maxage lsa's
544 + * @param isOpaquecapable need to include(true) or exclude(false) Type 10 Opaque lsa's
545 + * @return list of lsa header in the lsdb
546 + */
547 + public List getLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaquecapable) {
548 + return database.getAllLsaHeaders(excludeMaxAgeLsa, isOpaquecapable);
549 + }
550 +
551 + /**
552 + * Gets the LSA from LSDB based on the input.
553 + *
554 + * @param lsType type of lsa to form the key
555 + * @param linkStateID link state id to form the key
556 + * @param advertisingRouter advertising router to form the key
557 + * @return lsa wrapper instance which contains the Lsa
558 + * @throws Exception might throws exception
559 + */
560 + public LsaWrapper getLsa(int lsType, String linkStateID, String advertisingRouter) throws Exception {
561 + String lsaKey = lsType + "-" + linkStateID + "-" + advertisingRouter;
562 + if (lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA || lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
563 + lsType == OspfParameters.AS_OPAQUE_LSA) {
564 + byte[] linkStateAsBytes = InetAddress.getByName(linkStateID).getAddress();
565 + int opaqueType = linkStateAsBytes[0];
566 + int opaqueId = OspfUtil.byteToInteger(Arrays.copyOfRange(linkStateAsBytes, 1,
567 + linkStateAsBytes.length));
568 + lsaKey = lsType + "-" + opaqueType + opaqueId + "-" + advertisingRouter;
569 + }
570 + return database.findLsa(lsType, lsaKey);
571 + }
572 +
573 +
574 + /**
575 + * Checks whether an instance of the given LSA exists in the database belonging to this area.
576 + * If so return true else false.
577 + *
578 + * @param lookupLsa ospf LSA instance to lookup
579 + * @return LSA wrapper instance which contains the Lsa
580 + */
581 + public LsaWrapper lsaLookup(OspfLsa lookupLsa) {
582 + return database.lsaLookup((LsaHeader) lookupLsa);
583 + }
584 +
585 + /**
586 + * Checks whether an instance of the given LSA exists in the database belonging to this area.
587 + * If so return true else false.
588 + *
589 + * @param lsa1 OSPF LSA instance to compare
590 + * @param lsa2 OSPF LSA instance to compare
591 + * @return "same" if both instances are same, "latest" if lsa1 is latest, or "old" if lsa1 is old
592 + */
593 + public String isNewerOrSameLsa(OspfLsa lsa1, OspfLsa lsa2) {
594 + return database.isNewerOrSameLsa((LsaHeader) lsa1, (LsaHeader) lsa2);
595 + }
596 +
597 + /**
598 + * Methods gets called from ChannelHandler to add the received LSA to LSDB.
599 + *
600 + * @param ospfLsa OSPF LSA instance
601 + * @param ospfInterface OSPF interface instance
602 + */
603 + public void addLsa(OspfLsa ospfLsa, OspfInterface ospfInterface) throws Exception {
604 + //second param is false as lsa from network
605 + database.addLsa((LsaHeader) ospfLsa, false, ospfInterface);
606 + }
607 +
608 + /**
609 + * Methods gets called from ChannelHandler to add the received LSA to LSDB.
610 + *
611 + * @param ospfLsa OSPF LSA instance
612 + * @param isSelfOriginated true if the LSA is self originated. Else false
613 + * @param ospfInterface OSPF interface instance
614 + */
615 + public void addLsa(OspfLsa ospfLsa, boolean isSelfOriginated, OspfInterface ospfInterface)
616 + throws Exception {
617 + database.addLsa((LsaHeader) ospfLsa, isSelfOriginated, ospfInterface);
618 + }
619 +
620 + /**
621 + * Adds the LSA to maxAge bin.
622 + *
623 + * @param key key to add it to LSDB
624 + * @param wrapper LSA wrapper instance
625 + */
626 + public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
627 + database.addLsaToMaxAgeBin(key, wrapper);
628 + }
629 +
630 + /**
631 + * Sets router sequence number for router LSA.
632 + *
633 + * @param newSequenceNumber sequence number
634 + */
635 + public void setDbRouterSequenceNumber(long newSequenceNumber) {
636 + database.setRouterLsaSeqNo(newSequenceNumber);
637 + }
638 +
639 + /**
640 + * Methods gets called from ChannelHandler to delete the LSA.
641 + *
642 + * @param ospfLsa the LSA instance to delete
643 + */
644 + public void deleteLsa(LsaHeader ospfLsa) {
645 + database.deleteLsa(ospfLsa);
646 + }
647 +
648 + /**
649 + * Removes LSA from bin.
650 + *
651 + * @param lsaWrapper the LSA wrapper instance to delete
652 + */
653 + public void removeLsaFromBin(LsaWrapper lsaWrapper) {
654 + database.removeLsaFromBin(lsaWrapper);
655 + }
656 +
657 + @Override
658 + public String toString() {
659 + return MoreObjects.toStringHelper(getClass())
660 + .omitNullValues()
661 + .add("areaID", areaId)
662 + .add("stubCost", stubCost)
663 + .add("addressRanges", addressRanges)
664 + .add("interfacesLst", interfacesLst)
665 + .add("transitCapability", transitCapability)
666 + .add("externalRoutingCapability", externalRoutingCapability)
667 + .toString();
668 + }
669 +
670 + /**
671 + * Checks all Neighbors belonging to this Area whether they are in state lesser than the EXCHANGE.
672 + * <p>
673 + * Creates list of such neighbors
674 + * <p>
675 + * Returns list of neighbors who satisfy the conditions
676 + *
677 + * @param ospfInterface OSPF interface instance
678 + * @return List of interfaces having state lesser than exchange
679 + */
680 + public List<OspfNbr> getNeighborsInFullState(OspfInterface ospfInterface) {
681 +
682 + List<OspfNbr> listEligibleNeighbors = null;
683 + OspfNbrImpl ospfNeighbor = null;
684 + OspfNeighborState nextNeighborState;
685 + Iterator nbrInterface = ospfInterface.listOfNeighbors().values().iterator();
686 + while (nbrInterface.hasNext()) {
687 + ospfNeighbor = (OspfNbrImpl) nbrInterface.next();
688 + nextNeighborState = ospfNeighbor.getState();
689 + if (nextNeighborState.getValue() == OspfNeighborState.FULL.getValue()) {
690 + if (listEligibleNeighbors == null) {
691 + listEligibleNeighbors = new ArrayList<OspfNbr>();
692 + listEligibleNeighbors.add(ospfNeighbor);
693 + } else {
694 + listEligibleNeighbors.add(ospfNeighbor);
695 + }
696 + }
697 + }
698 + return listEligibleNeighbors;
699 + }
700 +
701 + /**
702 + * Gets the LSDB LSA key from LSA header.
703 + *
704 + * @param lsaHeader LSA header instance
705 + * @return key LSA key
706 + */
707 + public String getLsaKey(LsaHeader lsaHeader) {
708 + return database.getLsaKey(lsaHeader);
709 + }
710 +
711 + /**
712 + * Adds the received LSA in other neighbors tx list.
713 + *
714 + * @param recLsa LSA Header instance
715 + */
716 + public void addToOtherNeighborLsaTxList(LsaHeader recLsa) {
717 + //Add the received LSA in other neighbors retransmission list.
718 + log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList");
719 + List<OspfInterface> ospfInterfaces = getInterfacesLst();
720 + for (OspfInterface ospfInterfaceFromArea : ospfInterfaces) {
721 + Map neighbors = ospfInterfaceFromArea.listOfNeighbors();
722 + for (Object neighborIP : neighbors.keySet()) {
723 + OspfNbrImpl nbr = (OspfNbrImpl) neighbors.get(neighborIP);
724 + if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
725 + continue;
726 + }
727 + String key = database.getLsaKey(recLsa);
728 + if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING) {
729 + if (nbr.getLsReqList().containsKey(key)) {
730 + LsaWrapper lsWrapper = lsaLookup(recLsa);
731 + if (lsWrapper != null) {
732 + LsaHeader ownLSA = (LsaHeader) lsWrapper.ospfLsa();
733 + String status = isNewerOrSameLsa(recLsa, ownLSA);
734 + if (status.equals("old")) {
735 + continue;
736 + } else if (status.equals("same")) {
737 + log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
738 + "Removing lsa from reTxtList {}", key);
739 + nbr.getLsReqList().remove(key);
740 + continue;
741 + } else {
742 + log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
743 + "Removing lsa from reTxtList {}", key);
744 + nbr.getLsReqList().remove(key);
745 + }
746 + }
747 + }
748 + }
749 + if (recLsa.advertisingRouter().equals((String) neighborIP)) {
750 + continue;
751 + }
752 + if ((recLsa.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
753 + recLsa.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA)) {
754 + if (nbr.isOpaqueCapable()) {
755 + log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
756 + recLsa);
757 + nbr.getReTxList().put(key, recLsa);
758 + }
759 + } else {
760 + log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
761 + recLsa);
762 + nbr.getReTxList().put(key, recLsa);
763 + }
764 + }
765 + }
766 + }
767 +
768 + /**
769 + * Gets the options value.
770 + *
771 + * @return options value
772 + */
773 + public int options() {
774 + return options;
775 + }
776 +
777 + /**
778 + * Sets the options value.
779 + *
780 + * @param options options value
781 + */
782 + public void setOptions(int options) {
783 + this.options = options;
784 + }
785 +
786 + /**
787 + * Gets the opaque enabled options value.
788 + *
789 + * @return opaque enabled options value
790 + */
791 + public int opaqueEnabledOptions() {
792 + return Integer.parseInt(OspfParameters.OPAQUE_ENABLED_OPTION_VALUE, 2);
793 + }
794 +
795 + /**
796 + * Gets the lsdb instance for this area.
797 + *
798 + * @return lsdb instance
799 + */
800 + public OspfLsdb database() {
801 + return database;
802 + }
803 +}
...\ 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.impl;
17 +
18 +import org.jboss.netty.channel.Channel;
19 +import org.onlab.packet.Ip4Address;
20 +import org.onlab.util.Bandwidth;
21 +import org.onosproject.ospf.controller.DeviceInformation;
22 +import org.onosproject.ospf.controller.LinkInformation;
23 +import org.onosproject.ospf.controller.LsaWrapper;
24 +import org.onosproject.ospf.controller.OspfArea;
25 +import org.onosproject.ospf.controller.OspfDeviceTed;
26 +import org.onosproject.ospf.controller.OspfInterface;
27 +import org.onosproject.ospf.controller.OspfLinkTed;
28 +import org.onosproject.ospf.controller.OspfLsa;
29 +import org.onosproject.ospf.controller.OspfLsaType;
30 +import org.onosproject.ospf.controller.OspfLsdb;
31 +import org.onosproject.ospf.controller.OspfNbr;
32 +import org.onosproject.ospf.controller.OspfNeighborState;
33 +import org.onosproject.ospf.controller.OspfRouter;
34 +import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
35 +import org.onosproject.ospf.controller.area.OspfAreaImpl;
36 +import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
37 +import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
38 +import org.onosproject.ospf.controller.util.OspfInterfaceType;
39 +import org.onosproject.ospf.protocol.lsa.LsaHeader;
40 +import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
41 +import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10;
42 +import org.onosproject.ospf.protocol.lsa.types.TopLevelTlv;
43 +import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
44 +import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
45 +import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
46 +import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
47 +import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
48 +import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
49 +import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
50 +import org.onosproject.ospf.protocol.util.ChecksumCalculator;
51 +import org.onosproject.ospf.protocol.util.OspfInterfaceState;
52 +import org.onosproject.ospf.protocol.util.OspfPacketType;
53 +import org.onosproject.ospf.protocol.util.OspfParameters;
54 +import org.onosproject.ospf.protocol.util.OspfUtil;
55 +import org.slf4j.Logger;
56 +import org.slf4j.LoggerFactory;
57 +
58 +import java.util.ArrayList;
59 +import java.util.HashMap;
60 +import java.util.Hashtable;
61 +import java.util.Iterator;
62 +import java.util.LinkedHashMap;
63 +import java.util.List;
64 +import java.util.ListIterator;
65 +import java.util.Map;
66 +import java.util.Set;
67 +import java.util.concurrent.CopyOnWriteArrayList;
68 +import java.util.concurrent.Executors;
69 +import java.util.concurrent.ScheduledExecutorService;
70 +import java.util.concurrent.TimeUnit;
71 +
72 +/**
73 + * Represents an OSPF neighbor.
74 + * The first thing an OSPF router must do is find its neighbors and form adjacency.
75 + * Each neighbor that the router finds will be represented by this class.
76 + */
77 +public class OspfNbrImpl implements OspfNbr {
78 + private static final Logger log = LoggerFactory.getLogger(OspfNbrImpl.class);
79 + private OspfNeighborState state;
80 + private InternalRxmtDdPacket rxmtDdPacketTask;
81 + private InternalInactivityTimeCheck inActivityTimeCheckTask;
82 + private InternalFloodingTask floodingTask;
83 + private InternalRxmtLsrPacket rxmtLsrPacketTask;
84 + private ScheduledExecutorService exServiceRxmtLsr;
85 + private ScheduledExecutorService exServiceFlooding;
86 + private ScheduledExecutorService exServiceRxmtDDPacket;
87 + private ScheduledExecutorService exServiceInActivity;
88 +
89 + private boolean floodingTimerScheduled = false;
90 + private boolean rxmtLsrTimerScheduled = false;
91 + private boolean rxmtDdPacketTimerScheduled = false;
92 + private boolean inActivityTimerScheduled = false;
93 +
94 + /**
95 + * When the two neighbors are exchanging databases, they form a master/slave relationship.
96 + * The master sends the first Database Description Packet
97 + */
98 + private int isMaster;
99 +
100 + /**
101 + * The DD Sequence Number of the DD packet that is currently being sent to the neighbor.
102 + */
103 + private long ddSeqNum;
104 +
105 + /**
106 + * Another data structure for keeping information of the last received DD packet.
107 + */
108 + private DdPacket lastDdPacket;
109 +
110 + /**
111 + * Another data structure for keeping information of the last Sent DD packet.
112 + */
113 + private DdPacket lastSentDdPacket;
114 +
115 + /**
116 + * Another data structure for keeping information of the last Sent LSrequest packet.
117 + */
118 + private LsRequest lastSentLsrPacket;
119 +
120 + /**
121 + * The router ID of the Neighbor Router.
122 + */
123 + private Ip4Address neighborId;
124 +
125 + /**
126 + * The IP address of the neighboring router's interface to the attached network.
127 + */
128 + private Ip4Address neighborIpAddr;
129 +
130 + /**
131 + * The neighbor's IDEA of the designated router.
132 + */
133 + private Ip4Address neighborDr;
134 +
135 + /**
136 + * The neighbor's IDEA of the backup designated router.
137 + */
138 + private Ip4Address neighborBdr;
139 +
140 + private int routerPriority;
141 + private int routerDeadInterval;
142 +
143 + /**
144 + * The list of LSAs that have to be flooded.
145 + */
146 + private Map<String, OspfLsa> reTxList = new LinkedHashMap();
147 +
148 + /**
149 + * The list of LSAs that have been flooded but not yet acknowledged on this adjacency.
150 + */
151 + private Map<String, OspfLsa> pendingReTxList = new LinkedHashMap();
152 +
153 + /**
154 + * List of LSAs which are failed to received ACK.
155 + */
156 + private Map failedTxList = new HashMap();
157 +
158 + /**
159 + * The complete list of LSAs that make up the area link-state database, at the moment the.
160 + * neighbor goes into Database Exchange state (EXCHANGE).
161 + */
162 + private List<LsaHeader> ddSummaryList = new CopyOnWriteArrayList();
163 +
164 + /**
165 + * LSA Request List from Neighbor.
166 + */
167 + private Hashtable lsReqList = new Hashtable();
168 +
169 + /**
170 + * The optional OSPF capabilities supported by the neighbor.
171 + */
172 + private int options;
173 + private boolean isOpaqueCapable;
174 +
175 + /**
176 + * A link to the OSPF-Interface this Neighbor belongs to.
177 + */
178 + private OspfInterface ospfInterface;
179 +
180 + /**
181 + * A link to the OSPF-Area this Neighbor Data Structure belongs to.
182 + */
183 + private OspfArea ospfArea;
184 + private OspfInterfaceChannelHandler handler;
185 + private List<TopLevelTlv> topLevelTlvs = new ArrayList<>();
186 + private List<DeviceInformation> deviceInformationList = new ArrayList<>();
187 +
188 + private TopologyForDeviceAndLink topologyForDeviceAndLink;
189 +
190 + /**
191 + * Creates an instance of Neighbor.
192 + *
193 + * @param paramOspfArea OSPF Area instance
194 + * @param paramOspfInterface OSPF interface instance
195 + * @param ipAddr IP address
196 + * @param routerId router id
197 + * @param options options
198 + * @param handler channel handler instance
199 + * @param topologyForDeviceAndLinkCommon topology for device and link instance
200 + */
201 + public OspfNbrImpl(OspfArea paramOspfArea, OspfInterface paramOspfInterface,
202 + Ip4Address ipAddr, Ip4Address routerId, int options,
203 + OspfInterfaceChannelHandler handler, TopologyForDeviceAndLink topologyForDeviceAndLinkCommon) {
204 + this.ospfArea = paramOspfArea;
205 + this.ospfInterface = paramOspfInterface;
206 + state = OspfNeighborState.DOWN;
207 + isMaster = OspfUtil.NOT_MASTER;
208 + ddSeqNum = OspfUtil.createRandomNumber();
209 + neighborIpAddr = ipAddr;
210 + neighborId = routerId;
211 + this.options = options;
212 + lastDdPacket = new DdPacket();
213 + routerDeadInterval = paramOspfInterface.routerDeadIntervalTime();
214 + this.handler = handler;
215 + this.topologyForDeviceAndLink = topologyForDeviceAndLinkCommon;
216 + }
217 +
218 + /**
219 + * Gets the IP address of this neighbor.
220 + *
221 + * @return the IP address of this neighbor
222 + */
223 + public Ip4Address neighborIpAddr() {
224 + return neighborIpAddr;
225 + }
226 +
227 + /**
228 + * Gets the neighbor is opaque enabled or not.
229 + *
230 + * @return true if the neighbor is opaque enabled else false.
231 + */
232 + public boolean isOpaqueCapable() {
233 + return isOpaqueCapable;
234 + }
235 +
236 + /**
237 + * Sets the neighbor is opaque enabled or not.
238 + *
239 + * @param isOpaqueCapable true if the neighbor is opaque enabledelse false
240 + */
241 + public void setIsOpaqueCapable(boolean isOpaqueCapable) {
242 + this.isOpaqueCapable = isOpaqueCapable;
243 + }
244 +
245 + /**
246 + * Have seen a Neighbor, but the Neighbor doesn't know about me.
247 + *
248 + * @param ospfHello Hello Packet instance
249 + * @param channel netty channel instance
250 + */
251 + public void oneWayReceived(OspfMessage ospfHello, Channel channel) {
252 + log.debug("OSPFNbr::oneWayReceived...!!!");
253 + stopInactivityTimeCheck();
254 + startInactivityTimeCheck();
255 +
256 + if (state == OspfNeighborState.ATTEMPT) {
257 + state = OspfNeighborState.INIT;
258 + } else if (state == OspfNeighborState.DOWN) {
259 + state = OspfNeighborState.INIT;
260 + }
261 +
262 + if (state.getValue() >= OspfNeighborState.TWOWAY.getValue()) {
263 + state = OspfNeighborState.INIT;
264 + failedTxList.clear();
265 + ddSummaryList.clear();
266 + lsReqList.clear();
267 + }
268 + }
269 +
270 + /**
271 + * Called when a DD OSPFMessage is received while state was INIT.
272 + *
273 + * @param ospfMessage ospf message instance
274 + * @param channel netty channel instance
275 + * @throws Exception might throws exception
276 + */
277 + public void twoWayReceived(OspfMessage ospfMessage, Channel channel) throws Exception {
278 + log.debug("OSPFNbr::twoWayReceived...!!!");
279 + stopInactivityTimeCheck();
280 + startInactivityTimeCheck();
281 + startFloodingTimer(channel);
282 +
283 + OspfPacketHeader packet = (OspfPacketHeader) ospfMessage;
284 + if (state.getValue() <= OspfNeighborState.TWOWAY.getValue()) {
285 + if (formAdjacencyOrNot()) {
286 + state = OspfNeighborState.EXSTART;
287 +
288 + ddSeqNum++;
289 + DdPacket ddPacket = new DdPacket();
290 + // seting OSPF Header
291 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
292 + ddPacket.setOspftype(OspfPacketType.DD.value());
293 + ddPacket.setRouterId(ospfArea.routerId());
294 + ddPacket.setAreaId(ospfArea.areaId());
295 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
296 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
297 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
298 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
299 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
300 + if (isOpaqueEnabled) {
301 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
302 + } else {
303 + ddPacket.setOptions(ospfArea.options());
304 + }
305 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
306 + ddPacket.setIsMore(OspfUtil.MORE_SET);
307 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
308 + ddPacket.setImtu(ospfInterface.mtu());
309 + ddPacket.setSequenceNo(ddSeqNum);
310 +
311 + setLastSentDdPacket(ddPacket);
312 + rxmtDdPacketTask = new InternalRxmtDdPacket(channel);
313 + startRxMtDdTimer(channel);
314 + //setting destination ip
315 + ddPacket.setDestinationIp(packet.sourceIp());
316 + channel.write(ddPacket);
317 + } else {
318 + state = OspfNeighborState.TWOWAY;
319 + }
320 + }
321 + }
322 +
323 + /**
324 + * Checks whether to form adjacency or not.
325 + *
326 + * @return true indicates form adjacency, else false
327 + */
328 + private boolean formAdjacencyOrNot() {
329 + boolean formAdjacency = false;
330 +
331 + if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
332 + formAdjacency = true;
333 + } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
334 + if (ospfInterface.ipAddress().equals(this.neighborDr) ||
335 + ospfInterface.ipAddress().equals(this.neighborBdr)) {
336 + formAdjacency = true;
337 + } else if (neighborBdr.equals(neighborIpAddr) ||
338 + neighborDr.equals(neighborIpAddr)) {
339 + formAdjacency = true;
340 + }
341 + }
342 +
343 + log.debug("FormAdjacencyOrNot - neighborDR: {}, neighborBDR: {}, neighborIPAddr: {}, formAdjacencyOrNot {}",
344 + neighborDr, neighborBdr, neighborIpAddr, formAdjacency);
345 +
346 + return formAdjacency;
347 + }
348 +
349 + /**
350 + * At this point Master/Slave relationship is definitely established.
351 + * DD sequence numbers have been exchanged.
352 + * This is the begin of sending/receiving of DD OSPFMessages.
353 + *
354 + * @param ospfMessage OSPF message instance
355 + * @param neighborIsMaster neighbor is master or slave
356 + * @param payload contains the LSAs to add in Dd Packet
357 + * @param ch netty channel instance
358 + * @throws Exception might throws exception
359 + */
360 + public void negotiationDone(OspfMessage ospfMessage,
361 + boolean neighborIsMaster, List payload, Channel ch) throws Exception {
362 + stopRxMtDdTimer();
363 + OspfPacketHeader packet = (OspfPacketHeader) ospfMessage;
364 + DdPacket ddPacketForCheck = (DdPacket) packet;
365 + if (ddPacketForCheck.isOpaqueCapable()) {
366 + OspfLsdb database = ospfArea.database();
367 + List opaqueLsas = database.getAllLsaHeaders(true, true);
368 + Iterator iterator = opaqueLsas.iterator();
369 + while (iterator.hasNext()) {
370 + OspfLsa ospfLsa = (OspfLsa) iterator.next();
371 + if (ospfLsa.getOspfLsaType() == OspfLsaType.AREA_LOCAL_OPAQUE_LSA) {
372 + OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa;
373 + topLevelTlvs = opaqueLsa10.topLevelValues();
374 + }
375 + }
376 + }
377 + if (state == OspfNeighborState.EXSTART) {
378 + state = OspfNeighborState.EXCHANGE;
379 + boolean excludeMaxAgeLsa = true;
380 + //list of contents of area wise LSA
381 + ddSummaryList = (CopyOnWriteArrayList) ospfArea.getLsaHeaders(excludeMaxAgeLsa, isOpaqueCapable);
382 +
383 + if (neighborIsMaster) {
384 + processLsas(payload);
385 + // ...construct new DD Packet...
386 + DdPacket ddPacket = new DdPacket();
387 + // setting OSPF Header
388 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
389 + ddPacket.setOspftype(OspfPacketType.DD.value());
390 + ddPacket.setRouterId(ospfArea.routerId());
391 + ddPacket.setAreaId(ospfArea.areaId());
392 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
393 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
394 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
395 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
396 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
397 + if (isOpaqueEnabled && isOpaqueCapable) {
398 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
399 + } else {
400 + ddPacket.setOptions(ospfArea.options());
401 + }
402 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
403 + ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
404 + ddPacket.setIsMaster(OspfUtil.NOT_MASTER);
405 + ddPacket.setImtu(ospfInterface.mtu());
406 + ddPacket.setSequenceNo(ddSeqNum);
407 + //setting the destination
408 + ddPacket.setDestinationIp(packet.sourceIp());
409 + setLastSentDdPacket(ddPacket);
410 + getIsMoreBit();
411 +
412 + ch.write(lastSentDdPacket());
413 + } else {
414 + // process LSA Vector's List, Add it to LSRequestList.
415 + processLsas(payload);
416 + DdPacket ddPacket = new DdPacket();
417 + // setting OSPF Header
418 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
419 + ddPacket.setOspftype(OspfPacketType.DD.value());
420 + ddPacket.setRouterId(ospfArea.routerId());
421 + ddPacket.setAreaId(ospfArea.areaId());
422 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
423 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
424 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
425 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
426 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
427 + if (isOpaqueEnabled && isOpaqueCapable) {
428 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
429 + } else {
430 + ddPacket.setOptions(ospfArea.options());
431 + }
432 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
433 + ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
434 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
435 + ddPacket.setImtu(ospfInterface.mtu());
436 + ddPacket.setSequenceNo(ddSeqNum);
437 + setLastSentDdPacket(ddPacket);
438 + getIsMoreBit();
439 + ddPacket.setDestinationIp(packet.sourceIp());
440 + ch.write(lastSentDdPacket());
441 + startRxMtDdTimer(ch);
442 + }
443 + }
444 + }
445 +
446 + /**
447 + * Process the LSA Headers received in the last received Database Description OSPFMessage.
448 + *
449 + * @param ddPayload LSA headers to process
450 + * @throws Exception might throws exception
451 + */
452 + public void processLsas(List ddPayload) throws Exception {
453 + log.debug("OSPFNbr::processLsas...!!!");
454 + OspfLsa nextLsa;
455 + Iterator lsas = ddPayload.iterator();
456 + while (lsas.hasNext()) {
457 + nextLsa = (OspfLsa) lsas.next();
458 + // check LSA Type.
459 + if (((nextLsa.getOspfLsaType().value() > OspfLsaType.EXTERNAL_LSA.value()) &&
460 + (nextLsa.getOspfLsaType().value() < OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
461 + (nextLsa.getOspfLsaType().value() > OspfLsaType.AS_OPAQUE_LSA.value())) {
462 + // unknown lsType found!
463 + seqNumMismatch("LS Type found was unknown.");
464 + return;
465 + }
466 +
467 + if ((nextLsa.getOspfLsaType() == OspfLsaType.EXTERNAL_LSA) &&
468 + !ospfArea.isExternalRoutingCapability()) {
469 + // LSA is external and the Area has no external lsa capability
470 + seqNumMismatch("External LSA found although area is stub.");
471 + return;
472 + }
473 +
474 + LsaWrapper lsaHasInstance = ospfArea.lsaLookup(nextLsa);
475 + if (lsaHasInstance == null) {
476 + lsReqList.put(((OspfAreaImpl) ospfArea).getLsaKey((LsaHeader) nextLsa), nextLsa);
477 + } else {
478 + String isNew = ((OspfAreaImpl) ospfArea).isNewerOrSameLsa(nextLsa,
479 + lsaHasInstance.ospfLsa());
480 + if (isNew.equals("latest")) {
481 + lsReqList.put(((OspfAreaImpl) ospfArea).getLsaKey((LsaHeader) nextLsa), nextLsa);
482 + }
483 + }
484 + }
485 + }
486 +
487 + /**
488 + * Handles sequence number mis match event.
489 + *
490 + * @param reason a string represents the mismatch reason
491 + * @return OSPF message instance
492 + * @throws Exception might throws exception
493 + */
494 + public OspfMessage seqNumMismatch(String reason) throws Exception {
495 + log.debug("OSPFNbr::seqNumMismatch...{} ", reason);
496 + stopRxMtDdTimer();
497 +
498 + if (state.getValue() >= OspfNeighborState.EXCHANGE.getValue()) {
499 + /* if (state == OspfNeighborState.FULL) {
500 + ospfArea.refreshArea(ospfInterface);
501 + }*/
502 +
503 + state = OspfNeighborState.EXSTART;
504 + lsReqList.clear();
505 + ddSummaryList.clear();
506 + //increment the dd sequence number
507 + ddSeqNum++;
508 +
509 + DdPacket ddPacket = new DdPacket();
510 + // seting OSPF Header
511 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
512 + ddPacket.setOspftype(OspfPacketType.DD.value());
513 + ddPacket.setRouterId(ospfArea.routerId());
514 + ddPacket.setAreaId(ospfArea.areaId());
515 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
516 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
517 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
518 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
519 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
520 + if (isOpaqueEnabled) {
521 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
522 + } else {
523 + ddPacket.setOptions(ospfArea.options());
524 + }
525 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
526 + ddPacket.setIsMore(OspfUtil.MORE_SET);
527 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
528 + ddPacket.setImtu(ospfInterface.mtu());
529 + ddPacket.setSequenceNo(ddSeqNum);
530 +
531 + setLastSentDdPacket(ddPacket);
532 + //setting destination ip
533 + ddPacket.setDestinationIp(neighborIpAddr());
534 + setLastSentDdPacket(ddPacket);
535 +
536 + return ddPacket;
537 + }
538 +
539 + return null;
540 + }
541 +
542 + /**
543 + * Called if a LS Request has been received for an LSA which is not contained in the database.
544 + * This indicates an error in the Database Exchange process.
545 + * Actions to be performed are the same as in seqNumMismatch.
546 + * In addition, stop the possibly activated re transmission timer.
547 + *
548 + * @param ch netty channel instance
549 + */
550 + public void badLSReq(Channel ch) throws Exception {
551 + log.debug("OSPFNbr::badLSReq...!!!");
552 +
553 + if (state.getValue() >= OspfNeighborState.EXCHANGE.getValue()) {
554 + if (state == OspfNeighborState.FULL) {
555 + ospfArea.refreshArea(ospfInterface);
556 + }
557 +
558 + stopRxMtDdTimer();
559 + state = OspfNeighborState.EXSTART;
560 +
561 + lsReqList.clear();
562 + ddSummaryList.clear();
563 + reTxList.clear();
564 + //increment the dd sequence number
565 + isMaster = OspfUtil.IS_MASTER;
566 + ddSeqNum++;
567 + DdPacket ddPacket = new DdPacket();
568 + // seting OSPF Header
569 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
570 + ddPacket.setOspftype(OspfPacketType.DD.value());
571 + ddPacket.setRouterId(ospfArea.routerId());
572 + ddPacket.setAreaId(ospfArea.areaId());
573 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
574 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
575 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
576 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
577 +
578 + // setting DD Body
579 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
580 + if (isOpaqueEnabled && this.isOpaqueCapable) {
581 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
582 + } else {
583 + ddPacket.setOptions(ospfArea.options());
584 + }
585 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
586 + ddPacket.setIsMore(OspfUtil.MORE_SET);
587 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
588 + ddPacket.setImtu(ospfInterface.mtu());
589 + ddPacket.setSequenceNo(ddSeqNum);
590 +
591 + rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
592 + startRxMtDdTimer(ch);
593 +
594 + //setting destination ip
595 + ddPacket.setDestinationIp(neighborIpAddr());
596 + setLastSentDdPacket(ddPacket);
597 + ch.write(ddPacket);
598 + }
599 + }
600 +
601 + /**
602 + * Called if state is EXCHANGE. This method is executed every time a DD Packets arrives.
603 + * When the last Packet arrives, it transfers the state into LOADING or FULL
604 + *
605 + * @param neighborIsMaster true if neighbor is master else false
606 + * @param dataDescPkt DdPacket instance
607 + * @param ch netty channel instance
608 + * @throws Exception might throws exception
609 + */
610 + public void processDdPacket(boolean neighborIsMaster, DdPacket dataDescPkt,
611 + Channel ch) throws Exception {
612 + log.debug("OSPFNbr::neighborIsMaster.{}", neighborIsMaster);
613 +
614 + if (!neighborIsMaster) {
615 + stopRxMtDdTimer();
616 + ddSeqNum++;
617 + processLsas(dataDescPkt.getLsaHeaderList());
618 + if ((ddSummaryList.isEmpty()) &&
619 + (dataDescPkt.isMore() == OspfUtil.MORE_NOTSET)) {
620 + log.debug(
621 + "OSPFNbr::ddSummaryList is empty and dataDescPkt.isMore is zero..!!!");
622 + // generate the neighbor event ExchangeDone.
623 + exchangeDone(dataDescPkt, ch);
624 + } else {
625 + log.debug("OSPFNbr::ddSummaryList is present...!!!");
626 + // send a new Database Description Packet to the slave.
627 + DdPacket ddPacket = new DdPacket();
628 + // seting OSPF Header
629 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
630 + ddPacket.setOspftype(OspfPacketType.DD.value());
631 + ddPacket.setRouterId(ospfArea.routerId());
632 + ddPacket.setAreaId(ospfArea.areaId());
633 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
634 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
635 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
636 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
637 + // setting DD Body
638 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
639 + if (isOpaqueEnabled && isOpaqueCapable) {
640 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
641 + } else {
642 + ddPacket.setOptions(ospfArea.options());
643 + }
644 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
645 + ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
646 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
647 + ddPacket.setImtu(ospfInterface.mtu());
648 + ddPacket.setSequenceNo(ddSeqNum);
649 +
650 + setLastSentDdPacket(ddPacket);
651 + getIsMoreBit();
652 + //Set the destination IP Address
653 + ddPacket.setDestinationIp(dataDescPkt.sourceIp());
654 + ch.write(lastSentDdPacket());
655 +
656 + startRxMtDdTimer(ch);
657 + }
658 + } else {
659 + log.debug("OSPFNbr::neighborIsMaster is master...!!!");
660 + ddSeqNum = dataDescPkt.sequenceNo();
661 + processLsas(dataDescPkt.getLsaHeaderList());
662 +
663 + DdPacket ddPacket = new DdPacket();
664 + // seting OSPF Header
665 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
666 + ddPacket.setOspftype(OspfPacketType.DD.value());
667 + ddPacket.setRouterId(ospfArea.routerId());
668 + ddPacket.setAreaId(ospfArea.areaId());
669 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
670 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
671 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
672 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
673 + // setting DD Body
674 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
675 + if (isOpaqueEnabled && this.isOpaqueCapable) {
676 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
677 + } else {
678 + ddPacket.setOptions(ospfArea.options());
679 + }
680 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_NOTSET);
681 + ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
682 + ddPacket.setIsMaster(OspfUtil.NOT_MASTER);
683 + ddPacket.setImtu(ospfInterface.mtu());
684 + ddPacket.setSequenceNo(ddSeqNum);
685 + setLastSentDdPacket(ddPacket);
686 + getIsMoreBit();
687 +
688 + if ((ddPacket.isMore() == OspfUtil.MORE_NOTSET) &&
689 + (dataDescPkt.isMore() == OspfUtil.MORE_NOTSET)) {
690 + // generate the neighbor event ExchangeDone.
691 + exchangeDone(dataDescPkt, ch);
692 + }
693 +
694 + ddPacket.setDestinationIp(dataDescPkt.sourceIp());
695 + ch.write(ddPacket);
696 + }
697 + }
698 +
699 + /**
700 + * Sets the more bit in stored, last sent DdPacket.
701 + */
702 + private void getIsMoreBit() {
703 + DdPacket ddPacket = lastSentDdPacket();
704 + int count = ddSummaryList.size();
705 +
706 + if (!ddSummaryList.isEmpty()) {
707 + Iterator itr = ddSummaryList.iterator();
708 + int currentLength = OspfUtil.DD_HEADER_LENGTH;
709 + int maxSize = ospfInterface.mtu() - OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
710 + while (itr.hasNext()) {
711 + if ((currentLength + OspfUtil.LSA_HEADER_LENGTH) > maxSize) {
712 + break;
713 + }
714 +
715 + LsaHeader lsaHeader = (LsaHeader) itr.next();
716 + ddPacket.addLsaHeader(lsaHeader);
717 + currentLength = currentLength + OspfUtil.LSA_HEADER_LENGTH;
718 + ddSummaryList.remove(lsaHeader);
719 + count--;
720 + }
721 +
722 + if (count > 0) {
723 + ddPacket.setIsMore(OspfUtil.MORE_SET);
724 + } else {
725 + ddPacket.setIsMore(OspfUtil.MORE_NOTSET);
726 + }
727 + }
728 +
729 + setLastSentDdPacket(ddPacket);
730 + }
731 +
732 + /**
733 + * At this point, the router has sent and received an entire sequence of DD packets.
734 + * Now it must be determined whether the new state is FULL, or LS Request packets
735 + * have to be send.
736 + *
737 + * @param message OSPF message instance
738 + * @param ch netty channel handler
739 + */
740 + public void exchangeDone(OspfMessage message, Channel ch) {
741 + log.debug("OSPFNbr::exchangeDone...!!!");
742 + stopRxMtDdTimer();
743 +
744 + OspfPacketHeader header = (OspfPacketHeader) message;
745 +
746 + if (state == OspfNeighborState.EXCHANGE) {
747 + if (lsReqList.isEmpty()) {
748 + state = OspfNeighborState.FULL;
749 + //handler.addDeviceInformation(this);
750 + //handler.addLinkInformation(this, topLevelTlvs);
751 + } else {
752 + state = OspfNeighborState.LOADING;
753 + LsRequest lsRequest = buildLsRequest();
754 + //Setting the destination address
755 + lsRequest.setDestinationIp(header.sourceIp());
756 + ch.write(lsRequest);
757 +
758 + setLastSentLsrPacket(lsRequest);
759 + startRxMtLsrTimer(ch);
760 + }
761 + }
762 + }
763 +
764 + /**
765 + * Builds LS Request.
766 + *
767 + * @return ls request instance
768 + */
769 + private LsRequest buildLsRequest() {
770 + //send link state request packet to neighbor
771 + //for recent lsa's which are not received in exchange state
772 + LsRequest lsRequest = new LsRequest();
773 + lsRequest.setOspfVer(OspfUtil.OSPF_VERSION);
774 + lsRequest.setOspftype(OspfPacketType.LSREQUEST.value());
775 + lsRequest.setRouterId(ospfArea.routerId());
776 + lsRequest.setAreaId(ospfArea.areaId());
777 + lsRequest.setAuthType(OspfUtil.NOT_ASSIGNED);
778 + lsRequest.setAuthentication(OspfUtil.NOT_ASSIGNED);
779 + lsRequest.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
780 + lsRequest.setChecksum(OspfUtil.NOT_ASSIGNED);
781 +
782 + Set lsaKeys = lsReqList.keySet();
783 + Iterator itr = lsaKeys.iterator();
784 +
785 + int currentLength = OspfUtil.OSPF_HEADER_LENGTH;
786 + int maxSize = ospfInterface.mtu() -
787 + OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
788 +
789 + while (itr.hasNext()) {
790 + if ((currentLength + OspfUtil.LSREQUEST_LENGTH) >= maxSize) {
791 + break;
792 + }
793 + LsRequestPacket lsRequestPacket = new LsRequestPacket();
794 +
795 + String key = ((String) itr.next());
796 + String[] lsaKey = key.split("-");
797 + OspfLsa lsa = (OspfLsa) lsReqList.get(key);
798 +
799 + lsRequestPacket.setLsType(Integer.valueOf(lsaKey[0]));
800 + lsRequestPacket.setOwnRouterId(lsaKey[2]);
801 +
802 + if (((lsa.getOspfLsaType().value() == OspfLsaType.AREA_LOCAL_OPAQUE_LSA.value()) ||
803 + (lsa.getOspfLsaType().value() == OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
804 + (lsa.getOspfLsaType().value() == OspfLsaType.AS_OPAQUE_LSA.value())) {
805 + OpaqueLsaHeader header = (OpaqueLsaHeader) lsa;
806 + byte[] opaqueIdBytes = OspfUtil.convertToTwoBytes(header.opaqueId());
807 + lsRequestPacket.setLinkStateId(header.opaqueType() + "." + "0" + "." + opaqueIdBytes[0]
808 + + "." + opaqueIdBytes[1]);
809 + } else {
810 + lsRequestPacket.setLinkStateId(lsaKey[1]);
811 + }
812 +
813 + lsRequest.addLinkStateRequests(lsRequestPacket);
814 + currentLength = currentLength + OspfUtil.LSREQUEST_LENGTH;
815 + }
816 +
817 + return lsRequest;
818 + }
819 +
820 + /**
821 + * Determines whether an adjacency should be established/maintained with the neighbor or not.
822 + *
823 + * @param ch netty channel instance
824 + */
825 + public void adjOk(Channel ch) {
826 + log.debug("OSPFNbr::adjOk...!!!");
827 + if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
828 + if (state == OspfNeighborState.TWOWAY) {
829 + if (formAdjacencyOrNot()) {
830 + state = OspfNeighborState.EXSTART;
831 + //check for sequence number in lsdb
832 + ddSeqNum++;
833 +
834 + DdPacket ddPacket = new DdPacket();
835 + // seting OSPF Header
836 + ddPacket.setOspfVer(OspfUtil.OSPF_VERSION);
837 + ddPacket.setOspftype(OspfPacketType.DD.value());
838 + ddPacket.setRouterId(ospfArea.routerId());
839 + ddPacket.setAreaId(ospfArea.areaId());
840 + ddPacket.setAuthType(OspfUtil.NOT_ASSIGNED);
841 + ddPacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
842 + ddPacket.setOspfPacLength(OspfUtil.NOT_ASSIGNED);
843 + ddPacket.setChecksum(OspfUtil.NOT_ASSIGNED);
844 +
845 + // setting DD Body
846 + boolean isOpaqueEnabled = ospfArea.isOpaqueEnabled();
847 + if (isOpaqueEnabled && this.isOpaqueCapable) {
848 + ddPacket.setOptions(ospfArea.opaqueEnabledOptions());
849 + } else {
850 + ddPacket.setOptions(ospfArea.options());
851 + }
852 + ddPacket.setIsInitialize(OspfUtil.INITIALIZE_SET);
853 + ddPacket.setIsMore(OspfUtil.MORE_SET);
854 + ddPacket.setIsMaster(OspfUtil.IS_MASTER);
855 + ddPacket.setImtu(ospfInterface.mtu());
856 + ddPacket.setSequenceNo(ddSeqNum);
857 + rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
858 + startRxMtDdTimer(ch);
859 + //setting destination ip
860 + ddPacket.setDestinationIp(neighborIpAddr());
861 + setLastSentDdPacket(ddPacket);
862 + ch.write(ddPacket);
863 + }
864 + } else if (state.getValue() >= OspfNeighborState.EXSTART.getValue()) {
865 + if (!formAdjacencyOrNot()) {
866 + state = OspfNeighborState.TWOWAY;
867 + lsReqList.clear();
868 + ddSummaryList.clear();
869 + reTxList.clear();
870 + }
871 + }
872 + }
873 + }
874 +
875 + /**
876 + * LS Update Packet has been received while state was EXCHANGE or LOADING.
877 + * Examine the received LSAs, check whether they were requested or not and process
878 + * them accordingly. Therefore use method "processReceivedLsa" for further treatment.
879 + *
880 + * @param lsUpdPkt LS Update Packet received while Neighbor state was EXCHANGE or
881 + * LOADING
882 + * @param ch netty channel instance
883 + * @throws Exception might throws exception
884 + */
885 + public void processLsUpdate(LsUpdate lsUpdPkt, Channel ch) throws Exception {
886 + stopRxMtLsrTimer();
887 + log.debug("OSPFNbr::processLsUpdate...!!!");
888 +
889 + List lsaList = lsUpdPkt.getLsaList();
890 + if (!lsaList.isEmpty()) {
891 + Iterator itr = lsaList.iterator();
892 +
893 + while (itr.hasNext()) {
894 + LsaHeader lsaHeader = (LsaHeader) itr.next();
895 + String key = ((OspfAreaImpl) ospfArea).getLsaKey(lsaHeader);
896 +
897 + if (lsReqList.containsKey(key)) {
898 + boolean removeIt;
899 + removeIt = processReceivedLsa(lsaHeader, false, ch,
900 + lsUpdPkt.sourceIp());
901 + if (removeIt) {
902 + lsReqList.remove(key);
903 + }
904 + } else {
905 + // LSA was received via Flooding
906 + processReceivedLsa(lsaHeader, true, ch,
907 + lsUpdPkt.sourceIp());
908 + }
909 + }
910 +
911 + if (lsReqList.isEmpty() && (state == OspfNeighborState.LOADING)) {
912 + // loading complete
913 + loadingDone();
914 + } else {
915 + stopRxMtLsrTimer();
916 + LsRequest lsRequest = buildLsRequest();
917 + lsRequest.setDestinationIp(lsUpdPkt.sourceIp());
918 + setLastSentLsrPacket(lsRequest);
919 +
920 + startRxMtLsrTimer(ch);
921 + }
922 + }
923 + }
924 +
925 + /***
926 + * Method gets called when no more ls request list and moving to FULL State.
927 + *
928 + * @throws Exception might throws exception
929 + */
930 + public void loadingDone() throws Exception {
931 + stopRxMtLsrTimer();
932 + stopRxMtDdTimer();
933 + log.debug("OSPFNbr::loadingDone...!!!");
934 + state = OspfNeighborState.FULL;
935 + ospfArea.refreshArea(ospfInterface);
936 + }
937 +
938 + /**
939 + * Adds device and link.
940 + *
941 + * @param topologyForDeviceAndLink topology for device and link instance
942 + */
943 + private void callDeviceAndLinkAdding(TopologyForDeviceAndLink topologyForDeviceAndLink) {
944 + Map<String, DeviceInformation> deviceInformationMap = topologyForDeviceAndLink.deviceInformationMap();
945 + Map<String, LinkInformation> linkInformationMap = topologyForDeviceAndLink.linkInformationMap();
946 + OspfRouter ospfRouter = new OspfRouterImpl();
947 + log.debug("Device Information in list format along with size {}", deviceInformationMap.size());
948 + for (String key : deviceInformationMap.keySet()) {
949 + DeviceInformation value = deviceInformationMap.get(key);
950 + ospfRouter.setRouterIp(value.routerId());
951 + ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
952 + ospfRouter.setNeighborRouterId(value.deviceId());
953 + OspfDeviceTed ospfDeviceTed = new OspfDeviceTedImpl();
954 + List<Ip4Address> ip4Addresses = value.interfaceId();
955 + ospfDeviceTed.setIpv4RouterIds(ip4Addresses);
956 + ospfRouter.setDeviceTed(ospfDeviceTed);
957 + ospfRouter.setOpaque(ospfArea.isOpaqueEnabled());
958 + if (value.isDr()) {
959 + ospfRouter.setDr(value.isDr());
960 + } else {
961 + ospfRouter.setDr(false);
962 + }
963 + int size = value.interfaceId().size();
964 + for (int i = 0; i < size; i++) {
965 + ospfRouter.setInterfaceId(value.interfaceId().get(i));
966 + }
967 + if (value.isAlreadyCreated()) {
968 + removeDeviceDetails(value.routerId());
969 + OspfRouter ospfRouter1 = new OspfRouterImpl();
970 + ospfRouter1.setRouterIp(value.routerId());
971 + ospfRouter1.setInterfaceId(ospfInterface.ipAddress());
972 + ospfRouter1.setAreaIdOfInterface(ospfArea.areaId());
973 + ospfRouter1.setDeviceTed(new OspfDeviceTedImpl());
974 + topologyForDeviceAndLink.removeLinks(value.routerId());
975 + handler.removeDeviceInformation(ospfRouter1);
976 + }
977 + handler.addDeviceInformation(ospfRouter);
978 + }
979 + for (Map.Entry<String, LinkInformation> entry : linkInformationMap.entrySet()) {
980 + String key = entry.getKey();
981 + LinkInformation value = entry.getValue();
982 + OspfRouter ospfRouterForLink = new OspfRouterImpl();
983 + ospfRouterForLink.setInterfaceId(value.interfaceIp());
984 + ospfRouterForLink.setAreaIdOfInterface(ospfArea.areaId());
985 + ospfRouterForLink.setOpaque(ospfArea.isOpaqueEnabled());
986 + OspfLinkTed ospfLinkTed =
987 + topologyForDeviceAndLink.getOspfLinkTedHashMap(value.linkDestinationId().toString());
988 + if (ospfLinkTed == null) {
989 + ospfLinkTed = new OspfLinkTedImpl();
990 + ospfLinkTed.setMaximumLink(Bandwidth.bps(0));
991 + ospfLinkTed.setMaxReserved(Bandwidth.bps(0));
992 + ospfLinkTed.setTeMetric(0);
993 + }
994 +
995 + if (!value.isLinkSrcIdNotRouterId()) {
996 + ospfRouterForLink.setRouterIp(value.linkSourceId());
997 + ospfRouterForLink.setNeighborRouterId(value.linkDestinationId());
998 + try {
999 + handler.addLinkInformation(ospfRouterForLink, ospfLinkTed);
1000 + log.debug("LinkId, LinkSrc , LinkDest , LinkInterface values are : "
1001 + + value.linkId() + " , " + value.linkSourceId() + " , "
1002 + + value.linkDestinationId() + " , "
1003 + + value.interfaceIp());
1004 + } catch (Exception e) {
1005 + log.debug("Got Exception : {}", e.getMessage());
1006 + }
1007 + }
1008 + }
1009 + }
1010 +
1011 + // RFC 2328 Section 13 - partly as flooding procedure
1012 +
1013 + /**
1014 + * Processes the received Lsa.
1015 + *
1016 + * @param recLsa received Lsa
1017 + * @param receivedViaFlooding received via flooding or not
1018 + * @param ch channel instance
1019 + * @param sourceIp source of this Lsa
1020 + * @return true to remove it from lsReqList else false
1021 + * @throws Exception might throws exception
1022 + */
1023 + public boolean processReceivedLsa(LsaHeader recLsa,
1024 + boolean receivedViaFlooding, Channel ch, Ip4Address sourceIp)
1025 + throws Exception {
1026 + log.debug("OSPFNbr::processReceivedLsa(recLsa, recievedViaFlooding, ch)...!!!");
1027 +
1028 + //Validate the lsa checksum RFC 2328 13 (1)
1029 + ChecksumCalculator checkSum = new ChecksumCalculator();
1030 + if (!checkSum.isValidLsaCheckSum(recLsa,
1031 + recLsa.getOspfLsaType().value(),
1032 + OspfUtil.LSAPACKET_CHECKSUM_POS1,
1033 + OspfUtil.LSAPACKET_CHECKSUM_POS2)) {
1034 + log.debug("Checksum mismatch. Received LSA packet type {} ",
1035 + recLsa.lsType());
1036 +
1037 + return true;
1038 + }
1039 +
1040 + //If LSA type is unknown discard the lsa RFC 2328 13(2)
1041 + if (((recLsa.getOspfLsaType().value() > OspfLsaType.EXTERNAL_LSA.value()) &&
1042 + (recLsa.getOspfLsaType().value() < OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value())) ||
1043 + (recLsa.getOspfLsaType().value() > OspfLsaType.AS_OPAQUE_LSA.value())) {
1044 + return true;
1045 + }
1046 +
1047 + //If LSA type is external & the area is configured as stub area discard the lsa RFC 2328 13(3)
1048 + if ((recLsa.getOspfLsaType() == OspfLsaType.EXTERNAL_LSA) &&
1049 + (!ospfArea.isExternalRoutingCapability())) // to determine how to store options
1050 + {
1051 + return true;
1052 + }
1053 +
1054 + //if lsa age is equal to maxage && instance is not in lsdb && none of neighbors are in exchange
1055 + // or loading state
1056 + // Acknowledge the receipt by sending LSAck to the sender. 2328 13(4)
1057 + if ((recLsa.age() == OspfParameters.MAXAGE) &&
1058 + (ospfArea.lsaLookup(recLsa) == null) &&
1059 + ospfArea.noNeighborInLsaExchangeProcess()) {
1060 + // RFC 2328 Section 13. (4)
1061 + // Because the LSA was not yet requested, it is treated as a flooded LSA and thus
1062 + // acknowledged.
1063 + directAcknowledge(recLsa, ch, sourceIp);
1064 + return true;
1065 + }
1066 +
1067 + String key = ((OspfAreaImpl) ospfArea).getLsaKey(recLsa);
1068 + LsaWrapper lsWrapper = ospfArea.lsaLookup(recLsa);
1069 + String status = isNullorLatest(lsWrapper, recLsa);
1070 + //Section 13 (5)
1071 + if (status.equals("isNullorLatest")) {
1072 +
1073 + if (recLsa.lsType() == OspfLsaType.ROUTER.value() && recLsa.advertisingRouter().equals(
1074 + ospfArea.routerId())) {
1075 + if (recLsa.lsSequenceNo() > ((LsaWrapperImpl) lsWrapper).lsaHeader().lsSequenceNo()) {
1076 + ospfArea.setDbRouterSequenceNumber(recLsa.lsSequenceNo() + 1);
1077 + processSelfOriginatedLsa();
1078 + }
1079 +
1080 + if (recLsa.age() == OspfParameters.MAXAGE) {
1081 + ((LsaWrapperImpl) lsWrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
1082 + //remove from db & bin, add the lsa to MaxAge bin.
1083 + ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
1084 + lsWrapper).lsaHeader()), lsWrapper);
1085 + ospfArea.removeLsaFromBin(lsWrapper);
1086 + }
1087 +
1088 + return true;
1089 + } else if (recLsa.lsType() == OspfLsaType.NETWORK.value() && isLinkStateMatchesOwnRouterId(
1090 + recLsa.linkStateId())) {
1091 + // if we are not DR or if origination router ID not equal to our router ID //either
1092 + // DR state changed or our router ID was changed
1093 + //set LSAge = MaxAge
1094 + //flood the LSA
1095 + if (((OspfInterfaceImpl) ospfInterface).state() != OspfInterfaceState.DR ||
1096 + !recLsa.advertisingRouter().equals(
1097 + ospfArea.routerId())) {
1098 + if (lsWrapper != null) {
1099 + ((LsaWrapperImpl) lsWrapper).lsaHeader().setAge(OspfParameters.MAXAGE);
1100 + //remove from bin, add the lsa to MaxAge bin.
1101 + ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
1102 + lsWrapper).lsaHeader()), lsWrapper);
1103 + ospfArea.removeLsaFromBin(lsWrapper);
1104 + } else {
1105 + recLsa.setAge(OspfParameters.MAXAGE);
1106 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
1107 + }
1108 + }
1109 +
1110 + return true;
1111 + } else {
1112 + if (recLsa.age() == OspfParameters.MAXAGE) {
1113 + ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
1114 + //remove from db & bin, add the lsa to MaxAge bin.
1115 + if (lsWrapper != null) {
1116 + lsWrapper.setLsaAgeReceived(OspfParameters.MAXAGE);
1117 + ospfArea.addLsaToMaxAgeBin(((OspfAreaImpl) ospfArea).getLsaKey(((LsaWrapperImpl)
1118 + lsWrapper).lsaHeader()), lsWrapper);
1119 + ospfArea.removeLsaFromBin(lsWrapper);
1120 + } else {
1121 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
1122 + }
1123 +
1124 + return true;
1125 + } else {
1126 + ospfArea.addLsa(recLsa, ospfInterface);
1127 + log.debug("Inside addLsaMethod");
1128 + topologyForDeviceAndLink.addLocalDevice(recLsa, ospfInterface, ospfArea);
1129 + callDeviceAndLinkAdding(topologyForDeviceAndLink);
1130 + log.debug("Adding to lsdb interface State {}", ((OspfInterfaceImpl) ospfInterface).state().value());
1131 + // should not send any acknowledge if flooded out on receiving interface
1132 + if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.BDR.value()) {
1133 + if (neighborDr.equals(sourceIp)) {
1134 + log.debug("Adding for delayed ack {}", recLsa);
1135 + ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
1136 + }
1137 + } else {
1138 + log.debug("Adding for delayed ack {}", recLsa);
1139 + ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
1140 + }
1141 +
1142 + if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.DR.value() ||
1143 + ((OspfInterfaceImpl) ospfInterface).state().value() ==
1144 + OspfInterfaceState.POINT2POINT.value()) {
1145 + ((OspfAreaImpl) ospfArea).addToOtherNeighborLsaTxList(recLsa);
1146 + }
1147 + }
1148 +
1149 + }
1150 + }
1151 + // RFC 2328 Section 13 (6)
1152 + if (lsReqList.contains(key)) {
1153 + badLSReq(ch);
1154 + }
1155 + if (status.equals("same")) { //13 (7)
1156 + if (pendingReTxList.containsKey(key)) {
1157 + pendingReTxList.remove(key);
1158 + if (((OspfInterfaceImpl) ospfInterface).state().value() == OspfInterfaceState.BDR.value()) {
1159 + if (neighborDr.equals(recLsa.advertisingRouter())) {
1160 + ((OspfInterfaceImpl) ospfInterface).addLsaHeaderForDelayAck(recLsa);
1161 + }
1162 + }
1163 + } else {
1164 + directAcknowledge(recLsa, ch, sourceIp);
1165 + return true;
1166 + }
1167 + } else if (status.equals("old")) { // section 13 - point 8
1168 + if ((recLsa.lsSequenceNo() == OspfParameters.MAXSEQUENCENUMBER) &&
1169 + (recLsa.age() == OspfParameters.MAXAGE)) {
1170 + // section 13 - point 8
1171 + // simple discard the received LSA -
1172 + return true;
1173 + } else {
1174 + // respond back with the same LSA
1175 + //Using flood LSA to sent the LSUpdate back to advertising router
1176 + int diff = Math.abs(lsWrapper.lsaAgeReceived() - recLsa.age());
1177 + if (diff > OspfParameters.MINLSARRIVAL) {
1178 + sendLsa(((LsaWrapperImpl) lsWrapper).lsaHeader(), sourceIp, ch);
1179 + }
1180 + }
1181 + }
1182 + callDeviceAndLinkAdding(topologyForDeviceAndLink);
1183 + return true;
1184 + }
1185 +
1186 + /**
1187 + * Checks Link State ID is equal to one of the router's own IP interface addresses.
1188 + *
1189 + * @param linkStateId link state id
1190 + * @return true if link state matches or false
1191 + */
1192 + private boolean isLinkStateMatchesOwnRouterId(String linkStateId) {
1193 + boolean isLinkStateMatches = false;
1194 + List<OspfInterface> interfaceLst = ospfArea.getInterfacesLst();
1195 + for (OspfInterface ospfInterface : interfaceLst) {
1196 + if (ospfInterface.ipAddress().toString().equals(linkStateId)) {
1197 + isLinkStateMatches = true;
1198 + break;
1199 + }
1200 + }
1201 +
1202 + return isLinkStateMatches;
1203 + }
1204 +
1205 + /**
1206 + * RFC 2328 Section 13 (5).
1207 + *
1208 + * @param lsWrapper ls wrapper instance
1209 + * @param recLsa received LSA instance
1210 + * @return returns a string status
1211 + */
1212 + public String isNullorLatest(LsaWrapper lsWrapper, LsaHeader recLsa) {
1213 +
1214 +
1215 + if (lsWrapper != null) {
1216 + LsaHeader ownLsa = (LsaHeader) lsWrapper.ospfLsa();
1217 + String status = ospfArea.isNewerOrSameLsa(recLsa, ownLsa);
1218 +
1219 + if (status.equals("latest")) {
1220 + return "isNullorLatest";
1221 + } else {
1222 + return status;
1223 + }
1224 + } else {
1225 + return "isNullorLatest";
1226 + }
1227 + }
1228 +
1229 + /**
1230 + * RFC 2328 section 13.4
1231 + * Processing self-originated LSAs.
1232 + *
1233 + * @throws Exception might throws exception
1234 + */
1235 + public void processSelfOriginatedLsa() throws Exception {
1236 + ospfArea.refreshArea(ospfInterface);
1237 + }
1238 +
1239 + /**
1240 + * Sends the LSA to destination address.
1241 + *
1242 + * @param lsa LSA instance to sent
1243 + * @param destination destination IP address
1244 + * @param ch netty channel instance
1245 + */
1246 + public void sendLsa(LsaHeader lsa, Ip4Address destination, Channel ch) {
1247 + if (lsa == null) {
1248 + return;
1249 + }
1250 +
1251 + LsUpdate responseLsUpdate = new LsUpdate();
1252 + // seting OSPF Header
1253 + responseLsUpdate.setOspfVer(OspfUtil.OSPF_VERSION);
1254 + responseLsUpdate.setOspftype(OspfPacketType.LSUPDATE.value());
1255 + responseLsUpdate.setRouterId(ospfArea.routerId());
1256 + responseLsUpdate.setAreaId(ospfArea.areaId());
1257 + responseLsUpdate.setAuthType(OspfUtil.NOT_ASSIGNED);
1258 + responseLsUpdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
1259 + responseLsUpdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
1260 + responseLsUpdate.setChecksum(OspfUtil.NOT_ASSIGNED);
1261 + responseLsUpdate.setNumberOfLsa(1);
1262 + responseLsUpdate.addLsa(lsa);
1263 +
1264 + //setting the destination.
1265 + responseLsUpdate.setDestinationIp(destination);
1266 + ch.write(responseLsUpdate);
1267 + }
1268 +
1269 + /**
1270 + * Sends a direct Acknowledgment for a particular LSA to the Neighbor.
1271 + *
1272 + * @param ackLsa LSA instance
1273 + * @param ch netty channel instance
1274 + * @param sourceIp source IP address
1275 + */
1276 + public void directAcknowledge(LsaHeader ackLsa, Channel ch, Ip4Address sourceIp) {
1277 + log.debug("OSPFNbr::directAcknowledge...!!!");
1278 +
1279 + LsAcknowledge ackContent = new LsAcknowledge();
1280 + // seting OSPF Header
1281 + ackContent.setOspfVer(OspfUtil.OSPF_VERSION);
1282 + ackContent.setOspftype(OspfPacketType.LSAACK.value());
1283 + ackContent.setRouterId(ospfArea.routerId());
1284 + ackContent.setAreaId(ospfArea.areaId());
1285 + ackContent.setAuthType(OspfUtil.NOT_ASSIGNED);
1286 + ackContent.setAuthentication(OspfUtil.NOT_ASSIGNED);
1287 + ackContent.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
1288 + ackContent.setChecksum(OspfUtil.NOT_ASSIGNED);
1289 + ackContent.addLinkStateHeader(ackLsa);
1290 + //setting the destination IP
1291 + ackContent.setDestinationIp(sourceIp);
1292 + ch.write(ackContent);
1293 + }
1294 +
1295 + /**
1296 + * Called when neighbor is down.
1297 + *
1298 + * @throws Exception might throws exception
1299 + */
1300 + public void neighborDown() throws Exception {
1301 + log.debug("Neighbor Down {} and NeighborId {}", neighborIpAddr,
1302 + neighborId);
1303 + stopInactivityTimeCheck();
1304 + stopRxMtDdTimer();
1305 + stopRxMtLsrTimer();
1306 +
1307 + if (floodingTimerScheduled) {
1308 + stopFloodingTimer();
1309 + floodingTimerScheduled = false;
1310 + }
1311 +
1312 + state = OspfNeighborState.DOWN;
1313 + ospfArea.refreshArea(ospfInterface);
1314 + lsReqList.clear();
1315 + ddSummaryList.clear();
1316 + if (neighborIpAddr.equals(neighborBdr) ||
1317 + neighborIpAddr.equals(neighborDr)) {
1318 + handler.neighborChange();
1319 + }
1320 + log.debug("Neighbor Went Down : "
1321 + + this.neighborIpAddr + " , " + this.neighborId);
1322 + removeDeviceDetails(this.neighborId);
1323 + OspfRouter ospfRouter = new OspfRouterImpl();
1324 + ospfRouter.setRouterIp(this.neighborId());
1325 + ospfRouter.setInterfaceId(ospfInterface.ipAddress());
1326 + ospfRouter.setAreaIdOfInterface(ospfArea.areaId());
1327 + ospfRouter.setDeviceTed(new OspfDeviceTedImpl());
1328 + handler.removeDeviceInformation(ospfRouter);
1329 + removeDeviceDetails(this.neighborIpAddr);
1330 + OspfRouter ospfRouter1 = new OspfRouterImpl();
1331 + ospfRouter1.setRouterIp(this.neighborIpAddr);
1332 + ospfRouter1.setInterfaceId(ospfInterface.ipAddress());
1333 + ospfRouter1.setAreaIdOfInterface(ospfArea.areaId());
1334 + ospfRouter1.setDeviceTed(new OspfDeviceTedImpl());
1335 + handler.removeDeviceInformation(ospfRouter1);
1336 + handler.removeLinkInformation(this);
1337 + callDeviceAndLinkAdding(topologyForDeviceAndLink);
1338 + }
1339 +
1340 + /**
1341 + * Removes device details.
1342 + *
1343 + * @param routerId router id
1344 + */
1345 + private void removeDeviceDetails(Ip4Address routerId) {
1346 + String key = "device:" + routerId;
1347 + topologyForDeviceAndLink.removeDeviceInformationMap(key);
1348 + topologyForDeviceAndLink.removeLinks(routerId);
1349 + }
1350 +
1351 + /**
1352 + * Starts the inactivity timer.
1353 + */
1354 + private void startInactivityTimeCheck() {
1355 + if (!inActivityTimerScheduled) {
1356 + log.debug("OSPFNbr::startInactivityTimeCheck");
1357 + inActivityTimeCheckTask = new InternalInactivityTimeCheck();
1358 + exServiceInActivity = Executors.newSingleThreadScheduledExecutor();
1359 + exServiceInActivity.scheduleAtFixedRate(inActivityTimeCheckTask, routerDeadInterval,
1360 + routerDeadInterval, TimeUnit.SECONDS);
1361 + inActivityTimerScheduled = true;
1362 + }
1363 + }
1364 +
1365 + /**
1366 + * Stops the inactivity timer.
1367 + */
1368 + private void stopInactivityTimeCheck() {
1369 + if (inActivityTimerScheduled) {
1370 + log.debug("OSPFNbr::stopInactivityTimeCheck ");
1371 + exServiceInActivity.shutdown();
1372 + inActivityTimerScheduled = false;
1373 + }
1374 + }
1375 +
1376 + /**
1377 + * Starts the flooding timer.
1378 + *
1379 + * @param channel channel instance
1380 + */
1381 + public void startFloodingTimer(Channel channel) {
1382 +
1383 + if (!floodingTimerScheduled) {
1384 + log.debug("OSPFNbr::startFloodingTimer");
1385 + floodingTask = new InternalFloodingTask(channel);
1386 + exServiceFlooding = Executors.newSingleThreadScheduledExecutor();
1387 + //Run every 5 seconds.
1388 + exServiceFlooding.scheduleAtFixedRate(floodingTask, OspfParameters.START_NOW,
1389 + OspfParameters.MINLSINTERVAL, TimeUnit.SECONDS);
1390 + floodingTimerScheduled = true;
1391 + }
1392 + }
1393 +
1394 + /**
1395 + * Stops the flooding timer.
1396 + */
1397 + private void stopFloodingTimer() {
1398 + if (floodingTimerScheduled) {
1399 + log.debug("OSPFNbr::stopFloodingTimer ");
1400 + exServiceFlooding.shutdown();
1401 + floodingTimerScheduled = false;
1402 + }
1403 + }
1404 +
1405 + /**
1406 + * Starts the Dd Retransmission executor task.
1407 + *
1408 + * @param ch netty channel instance
1409 + */
1410 + private void startRxMtDdTimer(Channel ch) {
1411 + if (!rxmtDdPacketTimerScheduled) {
1412 + long retransmitInterval = ospfInterface.reTransmitInterval();
1413 + rxmtDdPacketTask = new InternalRxmtDdPacket(ch);
1414 + exServiceRxmtDDPacket = Executors.newSingleThreadScheduledExecutor();
1415 + exServiceRxmtDDPacket.scheduleAtFixedRate(rxmtDdPacketTask, retransmitInterval,
1416 + retransmitInterval, TimeUnit.SECONDS);
1417 + rxmtDdPacketTimerScheduled = true;
1418 + }
1419 + }
1420 +
1421 + /**
1422 + * Stops the Dd Retransmission executor task.
1423 + */
1424 + private void stopRxMtDdTimer() {
1425 + if (rxmtDdPacketTimerScheduled) {
1426 + exServiceRxmtDDPacket.shutdown();
1427 + rxmtDdPacketTimerScheduled = false;
1428 + }
1429 + }
1430 +
1431 + /**
1432 + * Starts Ls request retransmission executor task.
1433 + *
1434 + * @param ch Netty channel instance
1435 + */
1436 + private void startRxMtLsrTimer(Channel ch) {
1437 + if (!rxmtLsrTimerScheduled) {
1438 + log.debug("OSPFNbr::startRxMtLsrTimer...!!!");
1439 + long retransmitIntrvl = ospfInterface.reTransmitInterval();
1440 + rxmtLsrPacketTask = new InternalRxmtLsrPacket(ch);
1441 + exServiceRxmtLsr = Executors.newSingleThreadScheduledExecutor();
1442 + exServiceRxmtLsr.scheduleAtFixedRate(rxmtLsrPacketTask, retransmitIntrvl,
1443 + retransmitIntrvl, TimeUnit.SECONDS);
1444 + rxmtLsrTimerScheduled = true;
1445 + }
1446 + }
1447 +
1448 + /**
1449 + * Stops Ls request retransmission executor task.
1450 + */
1451 + private void stopRxMtLsrTimer() {
1452 + if (rxmtLsrTimerScheduled) {
1453 + exServiceRxmtLsr.shutdown();
1454 + rxmtLsrTimerScheduled = false;
1455 + }
1456 + }
1457 +
1458 + /**
1459 + * Gets the last sent DdPacket.
1460 + *
1461 + * @return DdPacket instance
1462 + */
1463 + public DdPacket lastDdPacket() {
1464 + return lastDdPacket;
1465 + }
1466 +
1467 + /**
1468 + * Sets the last sent DdPacket.
1469 + *
1470 + * @param lastDdPacket DdPacket instance
1471 + */
1472 + public void setLastDdPacket(DdPacket lastDdPacket) {
1473 + this.lastDdPacket = lastDdPacket;
1474 + }
1475 +
1476 + /**
1477 + * Gets neighbor id.
1478 + *
1479 + * @return neighbor id
1480 + */
1481 + public Ip4Address neighborId() {
1482 + return neighborId;
1483 + }
1484 +
1485 + /**
1486 + * Sets the neighbor id.
1487 + *
1488 + * @param neighborId neighbor id
1489 + */
1490 + public void setNeighborId(Ip4Address neighborId) {
1491 + this.neighborId = neighborId;
1492 + }
1493 +
1494 + /**
1495 + * Gets the neighbor DR address.
1496 + *
1497 + * @return neighbor DR address
1498 + */
1499 + public Ip4Address neighborDr() {
1500 + return neighborDr;
1501 + }
1502 +
1503 + /**
1504 + * Sets the neighbor DR address.
1505 + *
1506 + * @param neighborDr neighbor DR address
1507 + */
1508 + public void setNeighborDr(Ip4Address neighborDr) {
1509 + this.neighborDr = neighborDr;
1510 + }
1511 +
1512 + /**
1513 + * Gets the neighbor BDR address.
1514 + *
1515 + * @return neighbor BDR address
1516 + */
1517 + public Ip4Address neighborBdr() {
1518 + return neighborBdr;
1519 + }
1520 +
1521 + /**
1522 + * Sets the neighbor BDR address.
1523 + *
1524 + * @param neighborBdr neighbor BDR address
1525 + */
1526 + public void setNeighborBdr(Ip4Address neighborBdr) {
1527 + this.neighborBdr = neighborBdr;
1528 + }
1529 +
1530 + /**
1531 + * Gets router priority.
1532 + *
1533 + * @return router priority
1534 + */
1535 + public int routerPriority() {
1536 + return routerPriority;
1537 + }
1538 +
1539 + /**
1540 + * Sets router priority.
1541 + *
1542 + * @param routerPriority router priority
1543 + */
1544 + public void setRouterPriority(int routerPriority) {
1545 + this.routerPriority = routerPriority;
1546 + }
1547 +
1548 + /**
1549 + * Gets the options value.
1550 + *
1551 + * @return options value
1552 + */
1553 + public int options() {
1554 + return options;
1555 + }
1556 +
1557 + /**
1558 + * Sets the options value.
1559 + *
1560 + * @param options options value
1561 + */
1562 + public void setOptions(int options) {
1563 + this.options = options;
1564 + }
1565 +
1566 + /**
1567 + * Gets the DD sequence number.
1568 + *
1569 + * @return DD sequence number
1570 + */
1571 + public long ddSeqNum() {
1572 + return ddSeqNum;
1573 + }
1574 +
1575 + /**
1576 + * Sets the DD sequence number.
1577 + *
1578 + * @param ddSeqNum DD sequence number
1579 + */
1580 + public void setDdSeqNum(long ddSeqNum) {
1581 + this.ddSeqNum = ddSeqNum;
1582 + }
1583 +
1584 + /**
1585 + * Gets neighbor is master or not.
1586 + *
1587 + * @return true if neighbor is master else false
1588 + */
1589 + public int isMaster() {
1590 + return isMaster;
1591 + }
1592 +
1593 + /**
1594 + * Gets the last sent DD Packet.
1595 + *
1596 + * @return last sent DD Packet
1597 + */
1598 + public DdPacket lastSentDdPacket() {
1599 + return lastSentDdPacket;
1600 + }
1601 +
1602 + /**
1603 + * Sets the last sent DD Packet.
1604 + *
1605 + * @param lastSentDdPacket last sent DD Packet
1606 + */
1607 + public void setLastSentDdPacket(DdPacket lastSentDdPacket) {
1608 + this.lastSentDdPacket = lastSentDdPacket;
1609 + }
1610 +
1611 + /**
1612 + * Gets the last sent Ls Request Packet.
1613 + *
1614 + * @return last sent Ls Request Packet
1615 + */
1616 + public LsRequest getLastSentLsrPacket() {
1617 + return lastSentLsrPacket;
1618 + }
1619 +
1620 + /**
1621 + * Sets the last sent Ls Request Packet.
1622 + *
1623 + * @param lastSentLsrPacket last sent Ls Request Packet
1624 + */
1625 + public void setLastSentLsrPacket(LsRequest lastSentLsrPacket) {
1626 + this.lastSentLsrPacket = lastSentLsrPacket;
1627 + }
1628 +
1629 + /**
1630 + * Gets the neighbors state.
1631 + *
1632 + * @return neighbors state
1633 + */
1634 + public OspfNeighborState getState() {
1635 + return state;
1636 + }
1637 +
1638 + /**
1639 + * Sets the neighbors state.
1640 + *
1641 + * @param state neighbors state
1642 + */
1643 + public void setState(OspfNeighborState state) {
1644 + this.state = state;
1645 + }
1646 +
1647 + /**
1648 + * Sets neighbor is master or not.
1649 + *
1650 + * @param isMaster neighbor is master or not
1651 + */
1652 + public void setIsMaster(int isMaster) {
1653 + this.isMaster = isMaster;
1654 + }
1655 +
1656 + /**
1657 + * Gets the ls request list.
1658 + *
1659 + * @return ls request list
1660 + */
1661 + public Hashtable getLsReqList() {
1662 + return lsReqList;
1663 + }
1664 +
1665 + /**
1666 + * Gets the reTxList instance.
1667 + *
1668 + * @return reTxList instance
1669 + */
1670 + public Map getReTxList() {
1671 + return reTxList;
1672 + }
1673 +
1674 + /**
1675 + * Gets the pending re transmit list.
1676 + *
1677 + * @return pendingReTxList instance
1678 + */
1679 + public Map<String, OspfLsa> getPendingReTxList() {
1680 + return pendingReTxList;
1681 + }
1682 +
1683 +
1684 + /**
1685 + * Represents a Task which will do an inactivity time check.
1686 + */
1687 + private class InternalInactivityTimeCheck implements Runnable {
1688 + /**
1689 + * Constructor.
1690 + */
1691 + InternalInactivityTimeCheck() {
1692 + }
1693 +
1694 + @Override
1695 + public void run() {
1696 + try {
1697 + log.debug("Neighbor Not Heard till the past router dead interval .");
1698 + neighborDown();
1699 + } catch (Exception e) {
1700 + log.debug("Exception at inactivity time check...!!!");
1701 + }
1702 + }
1703 + }
1704 +
1705 + /**
1706 + * Task which re transmits DdPacket every configured time interval.
1707 + */
1708 + private class InternalRxmtDdPacket implements Runnable {
1709 + Channel ch;
1710 +
1711 + /**
1712 + * Creates an instance or Re transmit DD packet timer.
1713 + *
1714 + * @param ch netty channel instance
1715 + */
1716 + InternalRxmtDdPacket(Channel ch) {
1717 + this.ch = ch;
1718 + }
1719 +
1720 + @Override
1721 + public void run() {
1722 + if ((ch != null) && ch.isConnected()) {
1723 + DdPacket ddPacket = lastSentDdPacket();
1724 + ch.write(ddPacket);
1725 + log.debug("Re-Transmit DD Packet .");
1726 + } else {
1727 + log.debug(
1728 + "Re-Transmit DD Packet failed. Channel not connected..");
1729 + }
1730 + }
1731 + }
1732 +
1733 + /**
1734 + * Task which re transmits Ls request Packet every configured time interval.
1735 + */
1736 + private class InternalRxmtLsrPacket implements Runnable {
1737 + Channel ch;
1738 +
1739 + /**
1740 + * Creates an instance or Re transmit LS Request packet timer.
1741 + *
1742 + * @param ch netty channel instance
1743 + */
1744 + InternalRxmtLsrPacket(Channel ch) {
1745 + this.ch = ch;
1746 + }
1747 +
1748 + @Override
1749 + public void run() {
1750 + if ((ch != null) && ch.isConnected()) {
1751 + LsRequest lsrPacket = getLastSentLsrPacket();
1752 + ch.write(lsrPacket);
1753 + log.debug("Re-Transmit LSRequest Packet .");
1754 + } else {
1755 + log.debug(
1756 + "Re-Transmit LSRequest failed. Channel not connected..");
1757 + }
1758 + }
1759 + }
1760 +
1761 + /**
1762 + * Task which transmits Ls update Packet based on the re transmit list.
1763 + * every configured time interval.
1764 + */
1765 + private class InternalFloodingTask implements Runnable {
1766 + Channel channel;
1767 +
1768 + /**
1769 + * Creates an instance or Flooding task.
1770 + *
1771 + * @param ch netty channel instance
1772 + */
1773 + InternalFloodingTask(Channel ch) {
1774 + this.channel = ch;
1775 + }
1776 +
1777 + @Override
1778 + public void run() {
1779 + if ((channel != null) && channel.isConnected()) {
1780 +
1781 + if ((pendingReTxList != null) && (pendingReTxList.size() > 0)) {
1782 + List<LsUpdate> lsUpdateList = buildLsUpdate(pendingReTxList);
1783 +
1784 + for (LsUpdate lsupdate : lsUpdateList) {
1785 + //Pending for acknowledge directly sent it to neighbor
1786 + lsupdate.setDestinationIp(neighborIpAddr);
1787 + channel.write(lsupdate);
1788 + }
1789 + }
1790 +
1791 + if ((reTxList != null) && (reTxList.size() > 0)) {
1792 + List<LsUpdate> lsUpdateList = buildLsUpdate(reTxList);
1793 +
1794 + for (LsUpdate lsupdate : lsUpdateList) {
1795 + //set the destination
1796 + if ((((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR) ||
1797 + (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT)) {
1798 + lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
1799 + } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER ||
1800 + (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR)) {
1801 + lsupdate.setDestinationIp(neighborDr);
1802 + }
1803 + channel.write(lsupdate);
1804 + }
1805 + }
1806 + }
1807 + }
1808 +
1809 + /**
1810 + * Builds the LsUpdate for flooding.
1811 + *
1812 + * @param txList list contains LSAs
1813 + * @return list of LsUpdate instances
1814 + */
1815 + private List buildLsUpdate(Map<String, OspfLsa> txList) {
1816 + List<LsUpdate> lsUpdateList = new ArrayList<>();
1817 + ListIterator itr = new ArrayList(txList.keySet()).listIterator();
1818 + while (itr.hasNext()) {
1819 + LsUpdate lsupdate = new LsUpdate();
1820 + // seting OSPF Header
1821 + lsupdate.setOspfVer(OspfUtil.OSPF_VERSION);
1822 + lsupdate.setOspftype(OspfPacketType.LSUPDATE.value());
1823 + lsupdate.setRouterId(ospfArea.routerId());
1824 + lsupdate.setAreaId(ospfArea.areaId());
1825 + lsupdate.setAuthType(OspfUtil.NOT_ASSIGNED);
1826 + lsupdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
1827 + lsupdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
1828 + lsupdate.setChecksum(OspfUtil.NOT_ASSIGNED);
1829 +
1830 + //limit to mtu
1831 + int currentLength = OspfUtil.OSPF_HEADER_LENGTH + OspfUtil.FOUR_BYTES;
1832 + int maxSize = ospfInterface.mtu() -
1833 + OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
1834 +
1835 + int noLsa = 0;
1836 + while (itr.hasNext()) {
1837 +
1838 + String key = (String) itr.next();
1839 + OspfLsa lsa = txList.get(key);
1840 + if ((lsa.age() + OspfParameters.INFTRA_NS_DELAY) >= OspfParameters.MAXAGE) {
1841 + ((LsaHeader) lsa.lsaHeader()).setAge(OspfParameters.MAXAGE);
1842 + } else {
1843 + ((LsaHeader) lsa.lsaHeader()).setAge(lsa.age() + OspfParameters.INFTRA_NS_DELAY);
1844 + }
1845 +
1846 + if ((currentLength + ((LsaHeader) lsa.lsaHeader()).lsPacketLen()) >= maxSize) {
1847 + itr.previous();
1848 + break;
1849 + }
1850 + log.debug("FloodingTimer::LSA Type::{}, Header: {}, LSA: {}", lsa.getOspfLsaType(),
1851 + lsa.lsaHeader(), lsa);
1852 +
1853 + if (lsa != null) {
1854 + lsupdate.addLsa(lsa);
1855 + noLsa++;
1856 + currentLength = currentLength + ((LsaHeader) lsa.lsaHeader()).lsPacketLen();
1857 + }
1858 + log.debug("FloodingTimer::Removing key {}", key);
1859 + if (txList.equals(reTxList)) {
1860 + reTxList.remove(key);
1861 + pendingReTxList.put(key, lsa);
1862 + }
1863 + }
1864 + //set number of lsa's
1865 + lsupdate.setNumberOfLsa(noLsa);
1866 + lsUpdateList.add(lsupdate);
1867 + }
1868 + return lsUpdateList;
1869 + }
1870 + }
1871 +}
...\ 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.onosproject.ospf.controller.LsaBin;
20 +import org.onosproject.ospf.controller.LsaWrapper;
21 +import org.onosproject.ospf.controller.LsdbAge;
22 +import org.onosproject.ospf.controller.OspfArea;
23 +import org.onosproject.ospf.controller.OspfInterface;
24 +import org.onosproject.ospf.controller.OspfLsaType;
25 +import org.onosproject.ospf.controller.OspfLsdb;
26 +import org.onosproject.ospf.controller.area.OspfAreaImpl;
27 +import org.onosproject.ospf.protocol.lsa.LsaHeader;
28 +import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
29 +import org.onosproject.ospf.protocol.util.OspfParameters;
30 +import org.slf4j.Logger;
31 +import org.slf4j.LoggerFactory;
32 +
33 +import java.util.HashMap;
34 +import java.util.Iterator;
35 +import java.util.List;
36 +import java.util.Map;
37 +import java.util.concurrent.CopyOnWriteArrayList;
38 +
39 +/**
40 + * Represents the Link State Database.
41 + */
42 +public class OspfLsdbImpl implements OspfLsdb {
43 + private static final Logger log = LoggerFactory.getLogger(OspfLsdbImpl.class);
44 + private Map routerLsas = new HashMap();
45 + private Map networkLsas = new HashMap();
46 + private Map summaryLsas = new HashMap();
47 + private Map asbrSummaryLSAs = new HashMap();
48 + private Map opaque9Lsas = new HashMap();
49 + private Map opaque10Lsas = new HashMap();
50 + private Map opaque11Lsas = new HashMap();
51 + private Map externalLsas = new HashMap();
52 + private long routerLsaSeqNo = OspfParameters.STARTLSSEQUENCENUM;
53 + private long networkLsaSeqNo = OspfParameters.STARTLSSEQUENCENUM;
54 + private LsdbAge lsdbAge = null;
55 + private OspfArea ospfArea = null;
56 +
57 +
58 + /**
59 + * Creates an instance of OSPF LSDB.
60 + *
61 + * @param ospfArea area instance
62 + */
63 + public OspfLsdbImpl(OspfArea ospfArea) {
64 + this.ospfArea = ospfArea;
65 + lsdbAge = new LsdbAgeImpl(ospfArea);
66 + }
67 +
68 + @Override
69 + public boolean equals(Object o) {
70 + if (this == o) {
71 + return true;
72 + }
73 + if (o == null || getClass() != o.getClass()) {
74 + return false;
75 + }
76 + OspfLsdbImpl that = (OspfLsdbImpl) o;
77 + return Objects.equal(routerLsas.size(), that.routerLsas.size()) &&
78 + Objects.equal(networkLsas.size(), that.networkLsas.size()) &&
79 + Objects.equal(summaryLsas.size(), that.summaryLsas.size()) &&
80 + Objects.equal(asbrSummaryLSAs.size(), that.asbrSummaryLSAs.size()) &&
81 + Objects.equal(lsdbAge, that.lsdbAge) &&
82 + Objects.equal(routerLsaSeqNo, that.routerLsaSeqNo) &&
83 + Objects.equal(networkLsaSeqNo, that.networkLsaSeqNo);
84 + }
85 +
86 + @Override
87 + public int hashCode() {
88 + return Objects.hashCode(routerLsas, networkLsas, summaryLsas, asbrSummaryLSAs, lsdbAge,
89 + routerLsaSeqNo, networkLsaSeqNo);
90 + }
91 +
92 + /**
93 + * Initializes the link state database.
94 + */
95 + public void initializeDb() {
96 + lsdbAge.startDbAging();
97 + }
98 +
99 + /**
100 + * Returns all LSA Headers (Router and Summary) in a Vector.
101 + *
102 + * @param excludeMaxAgeLsa exclude the max age LSAs
103 + * @param isOpaqueCapable is opaque capable or not
104 + * @return List of LSA headers
105 + */
106 + public List getAllLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaqueCapable) {
107 + List summList = new CopyOnWriteArrayList();
108 + addLsaToHeaderList(summList, excludeMaxAgeLsa, routerLsas);
109 + addLsaToHeaderList(summList, excludeMaxAgeLsa, networkLsas);
110 + addLsaToHeaderList(summList, excludeMaxAgeLsa, summaryLsas);
111 + addLsaToHeaderList(summList, excludeMaxAgeLsa, asbrSummaryLSAs);
112 + addLsaToHeaderList(summList, excludeMaxAgeLsa, externalLsas);
113 + if (isOpaqueCapable) {
114 + addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque9Lsas);
115 + addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque10Lsas);
116 + addLsaToHeaderList(summList, excludeMaxAgeLsa, opaque11Lsas);
117 + }
118 +
119 + return summList;
120 + }
121 +
122 + /**
123 + * Adds the LSAs to summary list.
124 + *
125 + * @param summList summary list
126 + * @param excludeMaxAgeLsa exclude max age LSA
127 + * @param lsaMap map of LSA
128 + */
129 + private void addLsaToHeaderList(List summList, boolean excludeMaxAgeLsa, Map lsaMap) {
130 + Iterator slotVals = lsaMap.values().iterator();
131 + while (slotVals.hasNext()) {
132 + LsaWrapper wrapper = (LsaWrapper) slotVals.next();
133 + if (excludeMaxAgeLsa) {
134 + //if current age of lsa is max age or lsa present in Max Age bin
135 + if (wrapper.currentAge() != OspfParameters.MAXAGE &&
136 + lsdbAge.getMaxAgeBin().ospfLsa(((OspfAreaImpl)
137 + ospfArea).getLsaKey(((LsaWrapperImpl) wrapper).lsaHeader())) == null) {
138 + addToList(wrapper, summList);
139 + }
140 + } else {
141 + addToList(wrapper, summList);
142 + }
143 + }
144 + }
145 +
146 + /**
147 + * Adds the LSWrapper to summary list.
148 + *
149 + * @param wrapper LSA wrapper instance
150 + * @param summList LSA summary list
151 + */
152 + private void addToList(LsaWrapper wrapper, List summList) {
153 + LsaHeader header = (LsaHeader) wrapper.ospfLsa();
154 + //set the current age
155 + header.setAge(wrapper.currentAge());
156 + summList.add(header);
157 + }
158 +
159 + /**
160 + * Gets the LSDB LSA key from Lsa Header.
161 + *
162 + * @param lsaHeader LSA header instance
163 + * @return key
164 + */
165 + public String getLsaKey(LsaHeader lsaHeader) {
166 + String lsaKey = "";
167 + switch (lsaHeader.lsType()) {
168 + case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
169 + case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
170 + case OspfParameters.AS_OPAQUE_LSA:
171 + OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
172 + lsaKey = lsaHeader.lsType() + "-" + header.opaqueType() + header.opaqueId() + "-" +
173 + lsaHeader.advertisingRouter();
174 + break;
175 + case OspfParameters.ROUTER:
176 + case OspfParameters.NETWORK:
177 + case OspfParameters.ASBR_SUMMARY:
178 + case OspfParameters.SUMMARY:
179 + case OspfParameters.EXTERNAL_LSA:
180 + lsaKey = lsaHeader.lsType() + "-" + lsaHeader.linkStateId() + "-" +
181 + lsaHeader.advertisingRouter();
182 + break;
183 + default:
184 + log.debug("Unknown LSA type..!!!");
185 + break;
186 + }
187 +
188 + return lsaKey;
189 + }
190 +
191 + /**
192 + * Gets wrapper instance in LSDB.
193 + *
194 + * @param lsaHeader LSA header instance.
195 + * @return LSA Wrapper instance.
196 + */
197 + public LsaWrapper lsaLookup(LsaHeader lsaHeader) {
198 +
199 + return findLsa(lsaHeader.lsType(), getLsaKey(lsaHeader));
200 + }
201 +
202 + /**
203 + * Finds the LSA from appropriate maps.
204 + *
205 + * @param lsType type of LSA
206 + * @param lsaKey key
207 + * @return LSA wrapper object
208 + */
209 + public LsaWrapper findLsa(int lsType, String lsaKey) {
210 + LsaWrapper lsaWrapper = null;
211 +
212 + switch (lsType) {
213 + case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
214 + lsaWrapper = (LsaWrapper) opaque9Lsas.get(lsaKey);
215 + break;
216 + case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
217 + lsaWrapper = (LsaWrapper) opaque10Lsas.get(lsaKey);
218 + break;
219 + case OspfParameters.AS_OPAQUE_LSA:
220 + lsaWrapper = (LsaWrapper) opaque11Lsas.get(lsaKey);
221 + break;
222 + case OspfParameters.ROUTER:
223 + lsaWrapper = (LsaWrapper) routerLsas.get(lsaKey);
224 + break;
225 + case OspfParameters.NETWORK:
226 + lsaWrapper = (LsaWrapper) networkLsas.get(lsaKey);
227 + break;
228 + case OspfParameters.ASBR_SUMMARY:
229 + lsaWrapper = (LsaWrapper) asbrSummaryLSAs.get(lsaKey);
230 + break;
231 + case OspfParameters.SUMMARY:
232 + lsaWrapper = (LsaWrapper) summaryLsas.get(lsaKey);
233 + break;
234 + case OspfParameters.EXTERNAL_LSA:
235 + lsaWrapper = (LsaWrapper) externalLsas.get(lsaKey);
236 + break;
237 + default:
238 + log.debug("Unknown LSA type..!!!");
239 + break;
240 + }
241 +
242 + //set the current age
243 + if (lsaWrapper != null) {
244 + //set the current age
245 + ((LsaWrapperImpl) lsaWrapper).lsaHeader().setAge(lsaWrapper.currentAge());
246 + ((LsaHeader) lsaWrapper.ospfLsa()).setAge(lsaWrapper.currentAge());
247 + }
248 +
249 + return lsaWrapper;
250 + }
251 +
252 +
253 + /**
254 + * Installs a new self-originated LSA if possible.
255 + * Return true if installing was successful else false.
256 + *
257 + * @param newLsa LSA header instance
258 + * @param isSelfOriginated is self originated or not
259 + * @param ospfInterface OSPF interface instance
260 + * @return true if successfully added
261 + */
262 + public boolean addLsa(LsaHeader newLsa, boolean isSelfOriginated, OspfInterface ospfInterface) {
263 +
264 + LsaWrapperImpl lsaWrapper = new LsaWrapperImpl();
265 + lsaWrapper.setLsaType(newLsa.getOspfLsaType());
266 + lsaWrapper.setOspfLsa(newLsa);
267 + lsaWrapper.setLsaHeader(newLsa);
268 + lsaWrapper.setLsaAgeReceived(newLsa.age());
269 + lsaWrapper.setAgeCounterWhenReceived(lsdbAge.getAgeCounter());
270 + lsaWrapper.setIsSelfOriginated(isSelfOriginated);
271 + lsaWrapper.setIsSelfOriginated(isSelfOriginated);
272 + lsaWrapper.setOspfInterface(ospfInterface);
273 + lsaWrapper.setLsdbAge(lsdbAge);
274 + addLsa(lsaWrapper);
275 +
276 + log.debug("Added LSA In LSDB: {}", newLsa);
277 +
278 + return true;
279 + }
280 +
281 + /**
282 + * Installs a new self-originated LSA if possible.
283 + * Return true if installing was successful else false.
284 + * Adding LSA In cases
285 + * 1) New Self Originated LSA based on change in topology
286 + * 2) New Self Originated LSA because of LSRefresh
287 + * 2) New LSA received via Link State Update Packet
288 + *
289 + * @param newLsa LSA wrapper instance
290 + * @return true if added successfully
291 + */
292 + private boolean addLsa(LsaWrapper newLsa) {
293 + // adding an LSA - verify if it's old or new
294 + // verify min failed
295 + // to verify if it's a new LSA or updating the old LSA .
296 + // fetch the LSA Type
297 + // verify if the LSA age is ! Max Age
298 + // a) it is received during the flooding process (Section 13)
299 + // b) it is originated by the router itself (Section 12.4)
300 + // start aging .
301 + String key = getLsaKey(((LsaWrapperImpl) newLsa).lsaHeader());
302 + //Remove the lsa from bin if exist. we will be adding it in new bin based on the current age.
303 + removeLsaFromBin(lsaLookup(((LsaWrapperImpl) newLsa).lsaHeader()));
304 +
305 + switch (((LsaWrapperImpl) newLsa).lsaHeader().lsType()) {
306 +
307 + case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
308 + opaque9Lsas.put(key, newLsa);
309 + break;
310 + case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
311 + opaque10Lsas.put(key, newLsa);
312 + break;
313 + case OspfParameters.AS_OPAQUE_LSA:
314 + opaque11Lsas.put(key, newLsa);
315 + break;
316 + case OspfParameters.ROUTER:
317 + routerLsas.put(key, newLsa);
318 + break;
319 + case OspfParameters.NETWORK:
320 + networkLsas.put(key, newLsa);
321 + break;
322 + case OspfParameters.ASBR_SUMMARY:
323 + asbrSummaryLSAs.put(key, newLsa);
324 + break;
325 + case OspfParameters.SUMMARY:
326 + summaryLsas.put(key, newLsa);
327 + break;
328 + case OspfParameters.EXTERNAL_LSA:
329 + externalLsas.put(key, newLsa);
330 + break;
331 + default:
332 + log.debug("Unknown LSA type to add..!!!");
333 + break;
334 + }
335 + //add it to bin
336 + Integer binNumber = lsdbAge.age2Bin(((LsaWrapperImpl) newLsa).lsaHeader().age());
337 + LsaBin lsaBin = lsdbAge.getLsaBin(binNumber);
338 + if (lsaBin != null) {
339 + //remove from existing
340 + newLsa.setBinNumber(binNumber);
341 + lsaBin.addOspfLsa(key, newLsa);
342 + lsdbAge.addLsaBin(binNumber, lsaBin);
343 + log.debug("Added Type {} LSA to LSDB and LSABin[{}], Age of LSA {}", newLsa.lsaType(),
344 + binNumber, ((LsaWrapperImpl) newLsa).lsaHeader().age());
345 + }
346 +
347 + return false;
348 + }
349 +
350 + /**
351 + * Adds the LSA to maxAge bin.
352 + *
353 + * @param key key
354 + * @param wrapper LSA wrapper instance
355 + */
356 + public void addLsaToMaxAgeBin(String key, Object wrapper) {
357 + lsdbAge.addLsaToMaxAgeBin(key, (LsaWrapper) wrapper);
358 + }
359 +
360 + /**
361 + * Removes LSA from Bin.
362 + *
363 + * @param lsaWrapper LSA wrapper instance
364 + */
365 + public void removeLsaFromBin(Object lsaWrapper) {
366 + if (lsaWrapper != null) {
367 + lsdbAge.removeLsaFromBin((LsaWrapper) lsaWrapper);
368 + }
369 + }
370 +
371 + /**
372 + * RFC 2328 - Section 13.1. Determining which LSA is newer.
373 + *
374 + * @param lsa1 LSA instance
375 + * @param lsa2 LSA instance
376 + * @return string status
377 + */
378 + public String isNewerOrSameLsa(LsaHeader lsa1, LsaHeader lsa2) {
379 + if (lsa1.lsSequenceNo() > lsa2.lsSequenceNo()) {
380 + return "latest";
381 + } else if (lsa1.lsSequenceNo() < lsa2.lsSequenceNo()) {
382 + return "old";
383 + } else if (lsa1.lsSequenceNo() == lsa2.lsSequenceNo()) {
384 + if (lsa1.lsCheckSum() > lsa2.lsCheckSum()) {
385 + return "latest";
386 + } else if (lsa1.lsCheckSum() < lsa2.lsCheckSum()) {
387 + return "old";
388 + } else if (lsa1.lsCheckSum() == lsa2.lsCheckSum()) {
389 + if (lsa1.age() == lsa2.age()) {
390 + return "same";
391 + } else if (lsa1.age() == OspfParameters.MAXAGE) {
392 + return "latest";
393 + } else if (lsa2.age() == OspfParameters.MAXAGE) {
394 + return "old";
395 + } else if (OspfParameters.MAXAGEDIFF == (lsa1.age() - lsa2.age())) {
396 + if (lsa1.age() < lsa2.age()) {
397 + return "latest";
398 + } else {
399 + return "old";
400 + }
401 + } else {
402 + return "same";
403 + }
404 + }
405 + }
406 +
407 + return "";
408 + }
409 +
410 + /**
411 + * Gets the sequence number.
412 + *
413 + * @param lsaType type of LSA
414 + * @return sequence number
415 + */
416 + public long getLsSequenceNumber(OspfLsaType lsaType) {
417 + switch (lsaType) {
418 + case ROUTER:
419 + return routerLsaSeqNo++;
420 + case NETWORK:
421 + return networkLsaSeqNo++;
422 + default:
423 + return OspfParameters.STARTLSSEQUENCENUM;
424 + }
425 + }
426 +
427 + /**
428 + * Deletes the given LSA.
429 + *
430 + * @param lsaHeader LSA header instance
431 + */
432 + public void deleteLsa(LsaHeader lsaHeader) {
433 +
434 + String lsaKey = getLsaKey(lsaHeader);
435 + switch (lsaHeader.lsType()) {
436 + case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
437 + opaque9Lsas.remove(lsaKey);
438 + break;
439 + case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
440 + opaque10Lsas.remove(lsaKey);
441 + break;
442 + case OspfParameters.AS_OPAQUE_LSA:
443 + opaque11Lsas.remove(lsaKey);
444 + break;
445 + case OspfParameters.ROUTER:
446 + routerLsas.remove(lsaKey);
447 + break;
448 + case OspfParameters.NETWORK:
449 + networkLsas.remove(lsaKey);
450 + break;
451 + case OspfParameters.ASBR_SUMMARY:
452 + asbrSummaryLSAs.remove(lsaKey);
453 + break;
454 + case OspfParameters.SUMMARY:
455 + summaryLsas.remove(lsaKey);
456 + break;
457 + case OspfParameters.EXTERNAL_LSA:
458 + externalLsas.remove(lsaKey);
459 + break;
460 + default:
461 + log.debug("Unknown LSA type to delete..!!!");
462 + break;
463 + }
464 + }
465 +
466 + /**
467 + * Sets sequence number.
468 + *
469 + * @param routerLsaSeqNo sequence number
470 + */
471 + public void setRouterLsaSeqNo(long routerLsaSeqNo) {
472 + this.routerLsaSeqNo = routerLsaSeqNo;
473 + }
474 +
475 + /**
476 + * Sets sequence number.
477 + *
478 + * @param networkLsaSeqNo sequence number
479 + */
480 + public void setNetworkLsaSeqNo(long networkLsaSeqNo) {
481 + this.networkLsaSeqNo = networkLsaSeqNo;
482 + }
483 +}
...\ No newline at end of file ...\ No newline at end of file