Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame^] | 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 | } |