Committed by
Thomas Vachuska
ONOS-2740,ONOS-2741,from ONOS-3032 - to ONOS 3071 , OSPF Protocol Implementation
Change-Id: I592453c21440afa5240c74dc4e9e134f876c89b3
Showing
3 changed files
with
3157 additions
and
0 deletions
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 |
-
Please register or login to post a comment