Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 1 | /* |
Brian O'Connor | a09fe5b | 2017-08-03 21:12:30 -0700 | [diff] [blame] | 2 | * Copyright 2016-present Open Networking Foundation |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 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; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 24 | import org.onosproject.ospf.controller.OspfInterface; |
| 25 | import org.onosproject.ospf.controller.OspfLsa; |
| 26 | import org.onosproject.ospf.controller.OspfLsaType; |
| 27 | import org.onosproject.ospf.controller.OspfLsdb; |
| 28 | import org.onosproject.ospf.controller.OspfNbr; |
| 29 | import org.onosproject.ospf.controller.OspfNeighborState; |
| 30 | import org.onosproject.ospf.controller.impl.OspfNbrImpl; |
| 31 | import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl; |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 32 | import org.onosproject.ospf.exceptions.OspfParseException; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 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; |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 45 | import java.net.UnknownHostException; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 46 | import java.util.ArrayList; |
| 47 | import java.util.Arrays; |
| 48 | import java.util.Iterator; |
| 49 | import java.util.List; |
| 50 | import java.util.Map; |
| 51 | |
| 52 | /** |
| 53 | * Representation an OSPF area and related information. |
| 54 | */ |
| 55 | public class OspfAreaImpl implements OspfArea { |
| 56 | private static final Logger log = LoggerFactory.getLogger(OspfAreaImpl.class); |
| 57 | /** |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 58 | * Whether AS-external-LSAs will be flooded into/throughout the area. |
| 59 | */ |
| 60 | private boolean externalRoutingCapability; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 61 | |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 62 | /** |
| 63 | * Represents a list of all router's interfaces associated with this area. |
| 64 | */ |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 65 | private List<OspfInterface> ospfInterfaceList; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 66 | /** |
| 67 | * The LS Database for this area. It includes router-LSAs, network-LSAs and. |
| 68 | * summary-LSAs. AS-external-LSAs are hold in the OSPF class itself. |
| 69 | */ |
| 70 | private OspfLsdbImpl database; |
| 71 | /** |
| 72 | * A 32-bit number identifying the area. |
| 73 | */ |
| 74 | private Ip4Address areaId; |
| 75 | /** |
| 76 | * Router ID. |
| 77 | */ |
| 78 | private Ip4Address routerId; |
| 79 | /** |
| 80 | * Represents Options like external, opaque capabilities. |
| 81 | */ |
| 82 | private int options; |
| 83 | /** |
| 84 | * Represents Opaque Enable or not. |
| 85 | */ |
| 86 | private boolean isOpaqueEnable; |
| 87 | |
| 88 | /** |
| 89 | * Creates an instance of area implementation. |
| 90 | */ |
| 91 | public OspfAreaImpl() { |
| 92 | database = new OspfLsdbImpl(this); |
| 93 | } |
| 94 | |
| 95 | @Override |
| 96 | public boolean equals(Object o) { |
| 97 | if (this == o) { |
| 98 | return true; |
| 99 | } |
| 100 | if (o == null || getClass() != o.getClass()) { |
| 101 | return false; |
| 102 | } |
| 103 | OspfAreaImpl that = (OspfAreaImpl) o; |
| 104 | return Objects.equal(areaId, that.areaId) && |
| 105 | Objects.equal(routerId, that.routerId) && |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 106 | Objects.equal(externalRoutingCapability, that.externalRoutingCapability) && |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 107 | Objects.equal(ospfInterfaceList.size(), that.ospfInterfaceList.size()) && |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 108 | Objects.equal(database, that.database); |
| 109 | } |
| 110 | |
| 111 | @Override |
| 112 | public int hashCode() { |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 113 | return Objects.hashCode(areaId, routerId, externalRoutingCapability, |
| 114 | ospfInterfaceList, database); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Gets the router id. |
| 119 | * |
| 120 | * @return router id |
| 121 | */ |
| 122 | public Ip4Address routerId() { |
| 123 | return routerId; |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Sets the router id. |
| 128 | * |
| 129 | * @param routerId router id |
| 130 | */ |
| 131 | @JsonProperty("routerId") |
| 132 | public void setRouterId(Ip4Address routerId) { |
| 133 | this.routerId = routerId; |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * Sets opaque enabled to true or false. |
| 138 | * |
| 139 | * @param isOpaqueEnable true if opaque enabled else false |
| 140 | */ |
| 141 | @JsonProperty("isOpaqueEnable") |
| 142 | public void setIsOpaqueEnabled(boolean isOpaqueEnable) { |
| 143 | this.isOpaqueEnable = isOpaqueEnable; |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Gets is opaque enabled or not. |
| 148 | * |
| 149 | * @return true if opaque enabled else false |
| 150 | */ |
| 151 | public boolean isOpaqueEnabled() { |
| 152 | return this.isOpaqueEnable; |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Initializes link state database. |
| 157 | */ |
| 158 | public void initializeDb() { |
| 159 | |
| 160 | database.initializeDb(); |
| 161 | } |
| 162 | |
| 163 | /** |
| 164 | * Refreshes the OSPF area information . |
| 165 | * Gets called as soon as the interface is down or neighbor full Router LSA is updated. |
| 166 | * |
| 167 | * @param ospfInterface OSPF interface instance |
| 168 | */ |
| 169 | @Override |
| 170 | public void refreshArea(OspfInterface ospfInterface) { |
| 171 | OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface; |
| 172 | log.debug("Inside refreshArea...!!!"); |
| 173 | //If interface state is DR build network LSA. |
| 174 | if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) { |
| 175 | if (ospfInterface.listOfNeighbors().size() > 0) { |
| 176 | //Get the NetworkLsa |
| 177 | NetworkLsa networkLsa = null; |
| 178 | try { |
| 179 | networkLsa = buildNetworkLsa(ospfInterface.ipAddress(), ospfInterface.ipNetworkMask()); |
| 180 | } catch (Exception e) { |
| 181 | log.debug("Error while building NetworkLsa {}", e.getMessage()); |
| 182 | } |
| 183 | //Add the NetworkLsa to lsdb |
| 184 | database.addLsa(networkLsa, true, ospfInterface); |
| 185 | addToOtherNeighborLsaTxList(networkLsa); |
| 186 | } else { |
| 187 | log.debug("No Neighbors hence not creating NetworkLSA...!!!"); |
| 188 | } |
| 189 | } |
| 190 | //Get the router LSA |
| 191 | RouterLsa routerLsa = null; |
| 192 | try { |
| 193 | routerLsa = buildRouterLsa(ospfInterface); |
| 194 | } catch (Exception e) { |
| 195 | log.debug("Error while building RouterLsa {}", e.getMessage()); |
| 196 | } |
| 197 | //Add the RouterLSA to lsdb |
| 198 | database.addLsa(routerLsa, true, ospfInterface); |
| 199 | addToOtherNeighborLsaTxList(routerLsa); |
| 200 | } |
| 201 | |
| 202 | /** |
| 203 | * Builds a network LSA. |
| 204 | * |
| 205 | * @param interfaceIp interface IP address |
| 206 | * @param mask interface network mask |
| 207 | * @return NetworkLsa instance |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 208 | * @throws OspfParseException might throws exception |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 209 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 210 | public NetworkLsa buildNetworkLsa(Ip4Address interfaceIp, Ip4Address mask) throws OspfParseException { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 211 | // generate the Router-LSA for this Area. |
| 212 | NetworkLsa networkLsa = new NetworkLsa(); |
| 213 | networkLsa.setAdvertisingRouter(routerId); |
| 214 | networkLsa.setLinkStateId(interfaceIp.toString()); |
| 215 | networkLsa.setLsType(OspfLsaType.NETWORK.value()); |
| 216 | networkLsa.setAge(1); |
| 217 | networkLsa.setOptions(2); |
| 218 | networkLsa.setNetworkMask(mask); |
| 219 | //Adding our own router. |
| 220 | networkLsa.addAttachedRouter(routerId()); |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 221 | Iterator iter = ospfInterfaceList.iterator(); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 222 | OspfInterfaceImpl ospfInterface = null; |
| 223 | while (iter.hasNext()) { |
| 224 | ospfInterface = (OspfInterfaceImpl) iter.next(); |
| 225 | if (ospfInterface.ipAddress().equals(interfaceIp)) { |
| 226 | break; |
| 227 | } |
| 228 | } |
| 229 | if (ospfInterface != null) { |
| 230 | List<OspfNbr> neighborsInFullState = getNeighborsInFullState(ospfInterface); |
| 231 | if (neighborsInFullState != null) { |
| 232 | for (OspfNbr ospfnbr : neighborsInFullState) { |
| 233 | networkLsa.addAttachedRouter(ospfnbr.neighborId()); |
| 234 | log.debug("Adding attached neighbor:: {}", ospfnbr.neighborId()); |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | networkLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.NETWORK)); |
| 239 | //Find the byte length and add it in lsa object |
| 240 | ChecksumCalculator checksum = new ChecksumCalculator(); |
| 241 | byte[] lsaBytes = networkLsa.asBytes(); |
| 242 | networkLsa.setLsPacketLen(lsaBytes.length); |
| 243 | //Convert lsa object to byte again to reflect the packet length which we added. |
| 244 | lsaBytes = networkLsa.asBytes(); |
| 245 | //find the checksum |
| 246 | byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes, |
| 247 | OspfUtil.LSAPACKET_CHECKSUM_POS1, |
| 248 | OspfUtil.LSAPACKET_CHECKSUM_POS2); |
| 249 | int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum); |
| 250 | networkLsa.setLsCheckSum(checkSumVal); |
| 251 | return networkLsa; |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Builds Router LSA. |
| 256 | * |
| 257 | * @param ospfInterface Interface instance |
| 258 | * @return routerLsa Router LSA instance |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 259 | * @throws OspfParseException might throws exception |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 260 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 261 | public RouterLsa buildRouterLsa(OspfInterface ospfInterface) throws OspfParseException { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 262 | // generate the Router-LSA for this Area. |
| 263 | RouterLsa routerLsa = new RouterLsa(); |
| 264 | routerLsa.setAdvertisingRouter(routerId); |
| 265 | routerLsa.setLinkStateId(routerId.toString()); |
| 266 | routerLsa.setLsType(OspfLsaType.ROUTER.value()); |
| 267 | routerLsa.setAge(1); |
| 268 | routerLsa.setOptions(options); |
| 269 | routerLsa.setAreaBorderRouter(false); |
| 270 | routerLsa.setAsBoundaryRouter(false); |
| 271 | routerLsa.setVirtualEndPoint(false); |
| 272 | buildLinkForRouterLsa(routerLsa, ospfInterface); |
| 273 | routerLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.ROUTER)); |
| 274 | //Find the byte length and add it in lsa object |
| 275 | ChecksumCalculator checksum = new ChecksumCalculator(); |
| 276 | byte[] lsaBytes = routerLsa.asBytes(); |
| 277 | routerLsa.setLsPacketLen(lsaBytes.length); |
Frank Wang | d8ab096 | 2017-08-11 11:09:30 +0800 | [diff] [blame] | 278 | //Convert lsa object to byte again to reflect the packet length which we added. |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 279 | lsaBytes = routerLsa.asBytes(); |
| 280 | //find the checksum |
| 281 | byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes, |
| 282 | OspfUtil.LSAPACKET_CHECKSUM_POS1, |
| 283 | OspfUtil.LSAPACKET_CHECKSUM_POS2); |
| 284 | int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum); |
| 285 | routerLsa.setLsCheckSum(checkSumVal); |
| 286 | return routerLsa; |
| 287 | } |
| 288 | |
| 289 | /** |
| 290 | * Builds LSA link for router LSA. |
| 291 | * |
| 292 | * @param routerLsa router LSA instance |
| 293 | * @param ospfInterface interface instance |
| 294 | */ |
| 295 | private void buildLinkForRouterLsa(RouterLsa routerLsa, OspfInterface ospfInterface) { |
| 296 | OspfInterfaceImpl nextInterface; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 297 | Iterator interfaces = ospfInterfaceList.iterator(); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 298 | while (interfaces.hasNext()) { |
| 299 | nextInterface = (OspfInterfaceImpl) interfaces.next(); |
| 300 | if (nextInterface.state() == OspfInterfaceState.DOWN) { |
| 301 | continue; |
| 302 | } else if (nextInterface.state() == OspfInterfaceState.LOOPBACK) { |
| 303 | OspfLsaLink link = new OspfLsaLink(); |
| 304 | link.setLinkData("-1"); |
| 305 | link.setLinkId(nextInterface.ipAddress().toString()); |
| 306 | link.setLinkType(3); |
| 307 | link.setMetric(0); |
| 308 | link.setTos(0); |
| 309 | routerLsa.addRouterLink(link); |
| 310 | routerLsa.incrementLinkNo(); |
| 311 | } else if (nextInterface.state() == OspfInterfaceState.POINT2POINT) { |
| 312 | // adding all neighbour routers |
| 313 | List<OspfNbr> neighborsInFullState = getNeighborsInFullState(nextInterface); |
| 314 | if (neighborsInFullState != null) { |
| 315 | log.debug("Adding OspfLsaLink ::neighborsInFullState {}, InterfaceIP: {}", |
| 316 | neighborsInFullState.size(), nextInterface.ipAddress()); |
| 317 | for (OspfNbr ospfnbr : neighborsInFullState) { |
| 318 | OspfLsaLink link = new OspfLsaLink(); |
| 319 | link.setLinkData(nextInterface.ipAddress().toString()); |
| 320 | link.setLinkId(ospfnbr.neighborId().toString()); |
| 321 | link.setLinkType(1); |
| 322 | link.setMetric(0); |
| 323 | link.setTos(0); |
| 324 | routerLsa.addRouterLink(link); |
| 325 | routerLsa.incrementLinkNo(); |
| 326 | log.debug("Added OspfLsaLink :: {}, neighborIP: {}, routerLinks: {}", |
| 327 | ospfnbr.neighborId(), ospfnbr.neighborIpAddr(), routerLsa.noLink()); |
| 328 | } |
| 329 | } |
| 330 | // adding the self address |
| 331 | OspfLsaLink link = new OspfLsaLink(); |
| 332 | link.setLinkData(nextInterface.ipNetworkMask().toString()); |
| 333 | link.setLinkId(nextInterface.ipAddress().toString()); |
| 334 | link.setLinkType(3); |
| 335 | link.setMetric(0); |
| 336 | link.setTos(0); |
| 337 | routerLsa.addRouterLink(link); |
| 338 | routerLsa.incrementLinkNo(); |
| 339 | } else { |
| 340 | buildLinkForRouterLsaBroadcast(routerLsa, nextInterface); |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | /** |
| 346 | * Builds LSA link for router LSA. |
| 347 | * |
| 348 | * @param routerLsa router LSA instance |
| 349 | * @param ospfInterface interface instance |
| 350 | */ |
| 351 | private void buildLinkForRouterLsaBroadcast(RouterLsa routerLsa, OspfInterface ospfInterface) { |
| 352 | OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface; |
| 353 | if (ospfInterfaceImpl.state() == OspfInterfaceState.WAITING) { |
| 354 | OspfLsaLink link = new OspfLsaLink(); |
| 355 | link.setLinkData(ospfInterface.ipNetworkMask().toString()); |
| 356 | //Link id should be set to ip network number |
| 357 | link.setLinkId(ospfInterface.ipAddress().toString()); |
| 358 | link.setLinkType(3); |
| 359 | link.setMetric(0); |
| 360 | link.setTos(0); |
| 361 | routerLsa.addRouterLink(link); |
| 362 | routerLsa.incrementLinkNo(); |
| 363 | } else if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) { |
| 364 | OspfLsaLink link = new OspfLsaLink(); |
| 365 | link.setLinkData(ospfInterface.ipAddress().toString()); |
| 366 | link.setLinkId(ospfInterface.ipAddress().toString()); |
| 367 | link.setLinkType(2); |
| 368 | link.setMetric(0); |
| 369 | link.setTos(0); |
| 370 | routerLsa.addRouterLink(link); |
| 371 | routerLsa.incrementLinkNo(); |
| 372 | } else if (ospfInterfaceImpl.state() == OspfInterfaceState.BDR || |
| 373 | ospfInterfaceImpl.state() == OspfInterfaceState.DROTHER) { |
| 374 | OspfLsaLink link = new OspfLsaLink(); |
| 375 | link.setLinkData(ospfInterface.ipAddress().toString()); |
| 376 | link.setLinkId(ospfInterface.dr().toString()); |
| 377 | link.setLinkType(2); |
| 378 | link.setMetric(0); |
| 379 | link.setTos(0); |
| 380 | routerLsa.addRouterLink(link); |
| 381 | routerLsa.incrementLinkNo(); |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | /** |
| 386 | * Gets the area id. |
| 387 | * |
| 388 | * @return area id |
| 389 | */ |
| 390 | public Ip4Address areaId() { |
| 391 | return areaId; |
| 392 | } |
| 393 | |
| 394 | /** |
| 395 | * Sets the area id. |
| 396 | * |
| 397 | * @param areaId area id |
| 398 | */ |
| 399 | @JsonProperty("areaId") |
| 400 | public void setAreaId(Ip4Address areaId) { |
| 401 | this.areaId = areaId; |
| 402 | } |
| 403 | |
| 404 | /** |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 405 | * Gets external routing capability. |
| 406 | * |
| 407 | * @return true if external routing capable, else false |
| 408 | */ |
| 409 | public boolean isExternalRoutingCapability() { |
| 410 | return externalRoutingCapability; |
| 411 | } |
| 412 | |
| 413 | /** |
| 414 | * Sets external routing capability. |
| 415 | * |
| 416 | * @param externalRoutingCapability true if external routing capable, else false |
| 417 | */ |
| 418 | @JsonProperty("externalRoutingCapability") |
| 419 | public void setExternalRoutingCapability(boolean externalRoutingCapability) { |
| 420 | this.externalRoutingCapability = externalRoutingCapability; |
| 421 | } |
| 422 | |
| 423 | /** |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 424 | * Gets the list of interfaces in this area. |
| 425 | * |
| 426 | * @return list of interfaces |
| 427 | */ |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 428 | public List<OspfInterface> ospfInterfaceList() { |
| 429 | return ospfInterfaceList; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Sets the list of interfaces attached to the area. |
| 434 | * |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 435 | * @param ospfInterfaceList list of OspfInterface instances |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 436 | */ |
| 437 | @JsonProperty("interface") |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 438 | public void setOspfInterfaceList(List<OspfInterface> ospfInterfaceList) { |
| 439 | this.ospfInterfaceList = ospfInterfaceList; |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | /** |
| 443 | * Checks all neighbors belonging to this area whether they are in state EXCHANGE or LOADING. |
| 444 | * Return false if there is at least one, else return true. This Method is used by |
| 445 | * "processReceivedLsa()" in the neighbor class. |
| 446 | * |
| 447 | * @return boolean indicating that there is no Neighbor in Database Exchange |
| 448 | */ |
| 449 | public boolean noNeighborInLsaExchangeProcess() { |
| 450 | OspfInterfaceImpl nextInterface; |
| 451 | OspfNeighborState nextNeighborState; |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 452 | Iterator interfaces = ospfInterfaceList.iterator(); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 453 | while (interfaces.hasNext()) { |
| 454 | nextInterface = (OspfInterfaceImpl) interfaces.next(); |
| 455 | Iterator neighbors = nextInterface.listOfNeighbors().values().iterator(); |
| 456 | while (neighbors.hasNext()) { |
| 457 | nextNeighborState = ((OspfNbrImpl) neighbors.next()).getState(); |
| 458 | if (nextNeighborState == OspfNeighborState.EXCHANGE || |
| 459 | nextNeighborState == OspfNeighborState.LOADING) { |
| 460 | return false; |
| 461 | } |
| 462 | } |
| 463 | } |
| 464 | return true; |
| 465 | } |
| 466 | |
| 467 | /** |
| 468 | * Gets header of all types of LSAs. |
| 469 | * |
| 470 | * @param excludeMaxAgeLsa need to include(true) or exclude(false) maxage lsa's |
| 471 | * @param isOpaquecapable need to include(true) or exclude(false) Type 10 Opaque lsa's |
| 472 | * @return list of lsa header in the lsdb |
| 473 | */ |
| 474 | public List getLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaquecapable) { |
| 475 | return database.getAllLsaHeaders(excludeMaxAgeLsa, isOpaquecapable); |
| 476 | } |
| 477 | |
| 478 | /** |
| 479 | * Gets the LSA from LSDB based on the input. |
| 480 | * |
| 481 | * @param lsType type of lsa to form the key |
| 482 | * @param linkStateID link state id to form the key |
| 483 | * @param advertisingRouter advertising router to form the key |
| 484 | * @return lsa wrapper instance which contains the Lsa |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 485 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 486 | public LsaWrapper getLsa(int lsType, String linkStateID, String advertisingRouter) { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 487 | String lsaKey = lsType + "-" + linkStateID + "-" + advertisingRouter; |
| 488 | if (lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA || lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA || |
| 489 | lsType == OspfParameters.AS_OPAQUE_LSA) { |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 490 | try { |
| 491 | byte[] linkStateAsBytes = InetAddress.getByName(linkStateID).getAddress(); |
| 492 | |
| 493 | int opaqueType = linkStateAsBytes[0]; |
| 494 | int opaqueId = OspfUtil.byteToInteger(Arrays.copyOfRange(linkStateAsBytes, 1, |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 495 | linkStateAsBytes.length)); |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 496 | lsaKey = lsType + "-" + opaqueType + opaqueId + "-" + advertisingRouter; |
| 497 | } catch (UnknownHostException uhe) { |
| 498 | log.warn("Can't resolve host in Lsa wrapper", uhe); |
| 499 | return null; |
| 500 | } |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 501 | } |
| 502 | return database.findLsa(lsType, lsaKey); |
| 503 | } |
| 504 | |
| 505 | |
| 506 | /** |
| 507 | * Checks whether an instance of the given LSA exists in the database belonging to this area. |
| 508 | * If so return true else false. |
| 509 | * |
| 510 | * @param lookupLsa ospf LSA instance to lookup |
| 511 | * @return LSA wrapper instance which contains the Lsa |
| 512 | */ |
| 513 | public LsaWrapper lsaLookup(OspfLsa lookupLsa) { |
| 514 | return database.lsaLookup((LsaHeader) lookupLsa); |
| 515 | } |
| 516 | |
| 517 | /** |
| 518 | * Checks whether an instance of the given LSA exists in the database belonging to this area. |
| 519 | * If so return true else false. |
| 520 | * |
| 521 | * @param lsa1 OSPF LSA instance to compare |
| 522 | * @param lsa2 OSPF LSA instance to compare |
| 523 | * @return "same" if both instances are same, "latest" if lsa1 is latest, or "old" if lsa1 is old |
| 524 | */ |
| 525 | public String isNewerOrSameLsa(OspfLsa lsa1, OspfLsa lsa2) { |
| 526 | return database.isNewerOrSameLsa((LsaHeader) lsa1, (LsaHeader) lsa2); |
| 527 | } |
| 528 | |
| 529 | /** |
| 530 | * Methods gets called from ChannelHandler to add the received LSA to LSDB. |
| 531 | * |
| 532 | * @param ospfLsa OSPF LSA instance |
| 533 | * @param ospfInterface OSPF interface instance |
| 534 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 535 | public void addLsa(OspfLsa ospfLsa, OspfInterface ospfInterface) { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 536 | //second param is false as lsa from network |
| 537 | database.addLsa((LsaHeader) ospfLsa, false, ospfInterface); |
| 538 | } |
| 539 | |
| 540 | /** |
| 541 | * Methods gets called from ChannelHandler to add the received LSA to LSDB. |
| 542 | * |
| 543 | * @param ospfLsa OSPF LSA instance |
| 544 | * @param isSelfOriginated true if the LSA is self originated. Else false |
| 545 | * @param ospfInterface OSPF interface instance |
| 546 | */ |
Ray Milkey | 019fba4 | 2018-01-31 14:07:47 -0800 | [diff] [blame] | 547 | public void addLsa(OspfLsa ospfLsa, boolean isSelfOriginated, OspfInterface ospfInterface) { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 548 | database.addLsa((LsaHeader) ospfLsa, isSelfOriginated, ospfInterface); |
| 549 | } |
| 550 | |
| 551 | /** |
| 552 | * Adds the LSA to maxAge bin. |
| 553 | * |
| 554 | * @param key key to add it to LSDB |
| 555 | * @param wrapper LSA wrapper instance |
| 556 | */ |
| 557 | public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) { |
| 558 | database.addLsaToMaxAgeBin(key, wrapper); |
| 559 | } |
| 560 | |
| 561 | /** |
| 562 | * Sets router sequence number for router LSA. |
| 563 | * |
| 564 | * @param newSequenceNumber sequence number |
| 565 | */ |
| 566 | public void setDbRouterSequenceNumber(long newSequenceNumber) { |
| 567 | database.setRouterLsaSeqNo(newSequenceNumber); |
| 568 | } |
| 569 | |
| 570 | /** |
| 571 | * Methods gets called from ChannelHandler to delete the LSA. |
| 572 | * |
| 573 | * @param ospfLsa the LSA instance to delete |
| 574 | */ |
| 575 | public void deleteLsa(LsaHeader ospfLsa) { |
| 576 | database.deleteLsa(ospfLsa); |
| 577 | } |
| 578 | |
| 579 | /** |
| 580 | * Removes LSA from bin. |
| 581 | * |
| 582 | * @param lsaWrapper the LSA wrapper instance to delete |
| 583 | */ |
| 584 | public void removeLsaFromBin(LsaWrapper lsaWrapper) { |
| 585 | database.removeLsaFromBin(lsaWrapper); |
| 586 | } |
| 587 | |
| 588 | @Override |
| 589 | public String toString() { |
| 590 | return MoreObjects.toStringHelper(getClass()) |
| 591 | .omitNullValues() |
| 592 | .add("areaID", areaId) |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 593 | .add("ospfInterfaceList", ospfInterfaceList) |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 594 | .add("externalRoutingCapability", externalRoutingCapability) |
| 595 | .toString(); |
| 596 | } |
| 597 | |
| 598 | /** |
| 599 | * Checks all Neighbors belonging to this Area whether they are in state lesser than the EXCHANGE. |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 600 | * Creates list of such neighbors |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 601 | * Returns list of neighbors who satisfy the conditions |
| 602 | * |
| 603 | * @param ospfInterface OSPF interface instance |
| 604 | * @return List of interfaces having state lesser than exchange |
| 605 | */ |
| 606 | public List<OspfNbr> getNeighborsInFullState(OspfInterface ospfInterface) { |
| 607 | |
| 608 | List<OspfNbr> listEligibleNeighbors = null; |
| 609 | OspfNbrImpl ospfNeighbor = null; |
| 610 | OspfNeighborState nextNeighborState; |
| 611 | Iterator nbrInterface = ospfInterface.listOfNeighbors().values().iterator(); |
| 612 | while (nbrInterface.hasNext()) { |
| 613 | ospfNeighbor = (OspfNbrImpl) nbrInterface.next(); |
| 614 | nextNeighborState = ospfNeighbor.getState(); |
| 615 | if (nextNeighborState.getValue() == OspfNeighborState.FULL.getValue()) { |
| 616 | if (listEligibleNeighbors == null) { |
| 617 | listEligibleNeighbors = new ArrayList<OspfNbr>(); |
| 618 | listEligibleNeighbors.add(ospfNeighbor); |
| 619 | } else { |
| 620 | listEligibleNeighbors.add(ospfNeighbor); |
| 621 | } |
| 622 | } |
| 623 | } |
| 624 | return listEligibleNeighbors; |
| 625 | } |
| 626 | |
| 627 | /** |
| 628 | * Gets the LSDB LSA key from LSA header. |
| 629 | * |
| 630 | * @param lsaHeader LSA header instance |
| 631 | * @return key LSA key |
| 632 | */ |
| 633 | public String getLsaKey(LsaHeader lsaHeader) { |
| 634 | return database.getLsaKey(lsaHeader); |
| 635 | } |
| 636 | |
| 637 | /** |
| 638 | * Adds the received LSA in other neighbors tx list. |
| 639 | * |
| 640 | * @param recLsa LSA Header instance |
| 641 | */ |
| 642 | public void addToOtherNeighborLsaTxList(LsaHeader recLsa) { |
| 643 | //Add the received LSA in other neighbors retransmission list. |
| 644 | log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList"); |
sunishvk | f7c5655 | 2016-07-18 16:02:39 +0530 | [diff] [blame] | 645 | List<OspfInterface> ospfInterfaces = ospfInterfaceList(); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 646 | for (OspfInterface ospfInterfaceFromArea : ospfInterfaces) { |
| 647 | Map neighbors = ospfInterfaceFromArea.listOfNeighbors(); |
| 648 | for (Object neighborIP : neighbors.keySet()) { |
| 649 | OspfNbrImpl nbr = (OspfNbrImpl) neighbors.get(neighborIP); |
| 650 | if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) { |
| 651 | continue; |
| 652 | } |
| 653 | String key = database.getLsaKey(recLsa); |
| 654 | if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING) { |
| 655 | if (nbr.getLsReqList().containsKey(key)) { |
| 656 | LsaWrapper lsWrapper = lsaLookup(recLsa); |
| 657 | if (lsWrapper != null) { |
sunish vk | aa48da8 | 2016-03-02 23:17:06 +0530 | [diff] [blame] | 658 | LsaHeader ownLsa = (LsaHeader) lsWrapper.ospfLsa(); |
| 659 | String status = isNewerOrSameLsa(recLsa, ownLsa); |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 660 | if (status.equals("old")) { |
| 661 | continue; |
| 662 | } else if (status.equals("same")) { |
| 663 | log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " + |
| 664 | "Removing lsa from reTxtList {}", key); |
| 665 | nbr.getLsReqList().remove(key); |
| 666 | continue; |
| 667 | } else { |
| 668 | log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " + |
| 669 | "Removing lsa from reTxtList {}", key); |
| 670 | nbr.getLsReqList().remove(key); |
| 671 | } |
| 672 | } |
| 673 | } |
| 674 | } |
Saritha | 6935951 | 2017-05-09 15:01:48 +0530 | [diff] [blame] | 675 | if (recLsa.advertisingRouter().toString().equals((String) neighborIP)) { |
Kiran Ramachandra | 3d94a6c | 2016-02-17 16:57:03 +0530 | [diff] [blame] | 676 | continue; |
| 677 | } |
| 678 | if ((recLsa.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA || |
| 679 | recLsa.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA)) { |
| 680 | if (nbr.isOpaqueCapable()) { |
| 681 | log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}", |
| 682 | recLsa); |
| 683 | nbr.getReTxList().put(key, recLsa); |
| 684 | } |
| 685 | } else { |
| 686 | log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}", |
| 687 | recLsa); |
| 688 | nbr.getReTxList().put(key, recLsa); |
| 689 | } |
| 690 | } |
| 691 | } |
| 692 | } |
| 693 | |
| 694 | /** |
| 695 | * Gets the options value. |
| 696 | * |
| 697 | * @return options value |
| 698 | */ |
| 699 | public int options() { |
| 700 | return options; |
| 701 | } |
| 702 | |
| 703 | /** |
| 704 | * Sets the options value. |
| 705 | * |
| 706 | * @param options options value |
| 707 | */ |
| 708 | public void setOptions(int options) { |
| 709 | this.options = options; |
| 710 | } |
| 711 | |
| 712 | /** |
| 713 | * Gets the opaque enabled options value. |
| 714 | * |
| 715 | * @return opaque enabled options value |
| 716 | */ |
| 717 | public int opaqueEnabledOptions() { |
| 718 | return Integer.parseInt(OspfParameters.OPAQUE_ENABLED_OPTION_VALUE, 2); |
| 719 | } |
| 720 | |
| 721 | /** |
| 722 | * Gets the lsdb instance for this area. |
| 723 | * |
| 724 | * @return lsdb instance |
| 725 | */ |
| 726 | public OspfLsdb database() { |
| 727 | return database; |
| 728 | } |
Ray Milkey | 0bb1e10 | 2016-11-10 14:51:27 -0800 | [diff] [blame] | 729 | } |