| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.isis.controller.impl; |
| |
| import org.jboss.netty.channel.Channel; |
| import org.onlab.packet.Ip4Address; |
| import org.onlab.packet.MacAddress; |
| import org.onosproject.isis.controller.IsisInterface; |
| import org.onosproject.isis.controller.IsisInterfaceState; |
| import org.onosproject.isis.controller.IsisLsdb; |
| import org.onosproject.isis.controller.IsisMessage; |
| import org.onosproject.isis.controller.IsisNeighbor; |
| import org.onosproject.isis.controller.IsisNetworkType; |
| import org.onosproject.isis.controller.IsisPduType; |
| import org.onosproject.isis.controller.IsisRouterType; |
| import org.onosproject.isis.controller.LspWrapper; |
| import org.onosproject.isis.io.isispacket.IsisHeader; |
| import org.onosproject.isis.io.isispacket.pdu.Csnp; |
| import org.onosproject.isis.io.isispacket.pdu.HelloPdu; |
| import org.onosproject.isis.io.isispacket.pdu.L1L2HelloPdu; |
| import org.onosproject.isis.io.isispacket.pdu.LsPdu; |
| import org.onosproject.isis.io.isispacket.pdu.P2PHelloPdu; |
| import org.onosproject.isis.io.isispacket.pdu.Psnp; |
| import org.onosproject.isis.io.isispacket.tlv.AdjacencyStateTlv; |
| import org.onosproject.isis.io.isispacket.tlv.IsisTlv; |
| import org.onosproject.isis.io.isispacket.tlv.LspEntriesTlv; |
| import org.onosproject.isis.io.isispacket.tlv.LspEntry; |
| import org.onosproject.isis.io.isispacket.tlv.TlvHeader; |
| import org.onosproject.isis.io.isispacket.tlv.TlvType; |
| import org.onosproject.isis.io.util.IsisConstants; |
| import org.onosproject.isis.io.util.IsisUtil; |
| import org.onosproject.isis.io.util.LspGenerator; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.ScheduledExecutorService; |
| import java.util.concurrent.ScheduledFuture; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Representation of an ISIS interface. |
| */ |
| public class DefaultIsisInterface implements IsisInterface { |
| private static final Logger log = LoggerFactory.getLogger(DefaultIsisInterface.class); |
| boolean flagValue = false; |
| private int interfaceIndex; |
| private Ip4Address interfaceIpAddress; |
| private byte[] networkMask; |
| private MacAddress interfaceMacAddress; |
| private String intermediateSystemName; |
| private String systemId; |
| private String l1LanId; |
| private String l2LanId; |
| private int idLength; |
| private int maxAreaAddresses; |
| private int reservedPacketCircuitType; |
| private IsisNetworkType networkType; |
| private String areaAddress; |
| private int areaLength; |
| private String lspId; |
| private int holdingTime; |
| private int priority; |
| private String circuitId; |
| private int helloInterval; |
| private Map<MacAddress, IsisNeighbor> neighborList = new ConcurrentHashMap<>(); |
| private IsisHelloPduSender isisHelloPduSender = null; |
| private ScheduledExecutorService exServiceHello = null; |
| private IsisInterfaceState interfaceState = IsisInterfaceState.DOWN; |
| private IsisLsdb isisLsdb = null; |
| private List<Ip4Address> allConfiguredInterfaceIps = null; |
| private Channel channel; |
| |
| /** |
| * Returns ISIS LSDB instance. |
| * |
| * @return ISIS LSDB instance |
| */ |
| public IsisLsdb isisLsdb() { |
| return isisLsdb; |
| } |
| |
| /** |
| * Sets all configured interface IPs. |
| * |
| * @param allConfiguredInterfaces all configured interface IPs |
| */ |
| public void setAllConfiguredInterfaceIps(List<Ip4Address> allConfiguredInterfaces) { |
| allConfiguredInterfaceIps = allConfiguredInterfaces; |
| } |
| |
| /** |
| * Removes neighbor from the interface neighbor map. |
| * |
| * @param isisNeighbor ISIS neighbor instance |
| */ |
| public void removeNeighbor(IsisNeighbor isisNeighbor) { |
| neighborList.remove(isisNeighbor.neighborMacAddress()); |
| } |
| |
| /** |
| * Returns the ISIS neighbor instance if exists. |
| * |
| * @param isisNeighborMac mac address of the neighbor router |
| * @return ISIS neighbor instance if exists else null |
| */ |
| public IsisNeighbor lookup(MacAddress isisNeighborMac) { |
| return neighborList.get(isisNeighborMac); |
| } |
| |
| /** |
| * Returns the neighbors list. |
| * |
| * @return neighbors list |
| */ |
| public Set<MacAddress> neighbors() { |
| return neighborList.keySet(); |
| } |
| |
| /** |
| * Returns channel instance. |
| * |
| * @return channel instance |
| */ |
| public Channel channel() { |
| return channel; |
| } |
| |
| /** |
| * Returns interface index. |
| * |
| * @return interface index |
| */ |
| public int interfaceIndex() { |
| return interfaceIndex; |
| } |
| |
| /** |
| * Set interface index. |
| * |
| * @param interfaceIndex interface index |
| */ |
| public void setInterfaceIndex(int interfaceIndex) { |
| this.interfaceIndex = interfaceIndex; |
| } |
| |
| /** |
| * Returns the interface IP address. |
| * |
| * @return interface IP address |
| */ |
| public Ip4Address interfaceIpAddress() { |
| return interfaceIpAddress; |
| } |
| |
| /** |
| * Sets the interface IP address. |
| * |
| * @param interfaceIpAddress interfaceIpAddress interface IP address |
| */ |
| public void setInterfaceIpAddress(Ip4Address interfaceIpAddress) { |
| this.interfaceIpAddress = interfaceIpAddress; |
| } |
| |
| /** |
| * Returns the network mask. |
| * |
| * @return network mask |
| */ |
| public byte[] networkMask() { |
| return networkMask; |
| } |
| |
| /** |
| * Sets the network mask. |
| * |
| * @param networkMask network mask |
| */ |
| public void setNetworkMask(byte[] networkMask) { |
| this.networkMask = networkMask; |
| } |
| |
| /** |
| * Returns the interface mac address. |
| * |
| * @return interface mac address |
| */ |
| public MacAddress getInterfaceMacAddress() { |
| return interfaceMacAddress; |
| } |
| |
| /** |
| * Sets the interface mac address. |
| * |
| * @param interfaceMacAddress interface mac address |
| */ |
| public void setInterfaceMacAddress(MacAddress interfaceMacAddress) { |
| this.interfaceMacAddress = interfaceMacAddress; |
| } |
| |
| /** |
| * Returns intermediate system name. |
| * |
| * @return intermediate system name |
| */ |
| public String intermediateSystemName() { |
| return intermediateSystemName; |
| } |
| |
| /** |
| * Sets intermediate system name. |
| * |
| * @param intermediateSystemName intermediate system name |
| */ |
| public void setIntermediateSystemName(String intermediateSystemName) { |
| this.intermediateSystemName = intermediateSystemName; |
| } |
| |
| /** |
| * Returns system ID. |
| * |
| * @return system ID |
| */ |
| public String systemId() { |
| return systemId; |
| } |
| |
| /** |
| * Sets system ID. |
| * |
| * @param systemId system ID |
| */ |
| public void setSystemId(String systemId) { |
| this.systemId = systemId; |
| } |
| |
| /** |
| * Returns LAN ID. |
| * |
| * @return LAN ID |
| */ |
| public String l1LanId() { |
| return l1LanId; |
| } |
| |
| /** |
| * Sets LAN ID. |
| * |
| * @param l1LanId LAN ID |
| */ |
| public void setL1LanId(String l1LanId) { |
| this.l1LanId = l1LanId; |
| } |
| |
| /** |
| * Returns LAN ID. |
| * |
| * @return LAN ID |
| */ |
| public String l2LanId() { |
| return l2LanId; |
| } |
| |
| /** |
| * Sets LAN ID. |
| * |
| * @param l2LanId LAN ID |
| */ |
| public void setL2LanId(String l2LanId) { |
| this.l2LanId = l2LanId; |
| } |
| |
| /** |
| * Returns ID length. |
| * |
| * @return ID length |
| */ |
| public int getIdLength() { |
| |
| return ((idLength == 0) ? 6 : idLength); |
| } |
| |
| /** |
| * Sets ID length. |
| * |
| * @param idLength ID length |
| */ |
| public void setIdLength(int idLength) { |
| this.idLength = idLength; |
| } |
| |
| /** |
| * Returns max area addresses. |
| * |
| * @return max area addresses |
| */ |
| public int getMaxAreaAddresses() { |
| |
| return maxAreaAddresses; |
| } |
| |
| /** |
| * Sets area max addresses. |
| * |
| * @param maxAreaAddresses max area addresses |
| */ |
| public void setMaxAreaAddresses(int maxAreaAddresses) { |
| this.maxAreaAddresses = maxAreaAddresses; |
| } |
| |
| /** |
| * Returns reserved packet circuit type. |
| * |
| * @return reserved packet circuit type |
| */ |
| public int reservedPacketCircuitType() { |
| return reservedPacketCircuitType; |
| } |
| |
| /** |
| * Sets reserved packet circuit type. |
| * |
| * @param reservedPacketCircuitType reserved packet circuit type |
| */ |
| public void setReservedPacketCircuitType(int reservedPacketCircuitType) { |
| this.reservedPacketCircuitType = reservedPacketCircuitType; |
| } |
| |
| /** |
| * Returns point to point. |
| * |
| * @return point to point |
| */ |
| public IsisNetworkType networkType() { |
| return networkType; |
| } |
| |
| /** |
| * Sets point to point or broadcast. |
| * |
| * @param networkType point to point or broadcast |
| */ |
| public void setNetworkType(IsisNetworkType networkType) { |
| this.networkType = networkType; |
| } |
| |
| /** |
| * Returns area address. |
| * |
| * @return area address |
| */ |
| public String areaAddress() { |
| return areaAddress; |
| } |
| |
| /** |
| * Sets area address. |
| * |
| * @param areaAddress area address |
| */ |
| public void setAreaAddress(String areaAddress) { |
| this.areaAddress = areaAddress; |
| } |
| |
| /** |
| * Returns area length. |
| * |
| * @return area length |
| */ |
| public int getAreaLength() { |
| return areaLength; |
| } |
| |
| /** |
| * Sets area length. |
| * |
| * @param areaLength area length |
| */ |
| public void setAreaLength(int areaLength) { |
| this.areaLength = areaLength; |
| } |
| |
| /** |
| * Returns LSP ID. |
| * |
| * @return LSP ID |
| */ |
| public String getLspId() { |
| return lspId; |
| } |
| |
| /** |
| * Sets LSP ID. |
| * |
| * @param lspId link state packet ID |
| */ |
| public void setLspId(String lspId) { |
| this.lspId = lspId; |
| } |
| |
| /** |
| * Returns holding time. |
| * |
| * @return holding time |
| */ |
| public int holdingTime() { |
| return holdingTime; |
| } |
| |
| /** |
| * Sets holding time. |
| * |
| * @param holdingTime holding time |
| */ |
| public void setHoldingTime(int holdingTime) { |
| this.holdingTime = holdingTime; |
| } |
| |
| /** |
| * Returns priority. |
| * |
| * @return priority |
| */ |
| public int priority() { |
| return priority; |
| } |
| |
| /** |
| * Sets priority. |
| * |
| * @param priority priority |
| */ |
| public void setPriority(int priority) { |
| this.priority = priority; |
| } |
| |
| /** |
| * Returns hello interval. |
| * |
| * @return hello interval |
| */ |
| public int helloInterval() { |
| return helloInterval; |
| } |
| |
| /** |
| * Sets hello interval. |
| * |
| * @param helloInterval hello interval |
| */ |
| public void setHelloInterval(int helloInterval) { |
| this.helloInterval = helloInterval; |
| } |
| |
| /** |
| * Returns the interface state. |
| * |
| * @return interface state |
| */ |
| public IsisInterfaceState interfaceState() { |
| return interfaceState; |
| } |
| |
| /** |
| * Sets the interface state. |
| * |
| * @param interfaceState the interface state |
| */ |
| public void setInterfaceState(IsisInterfaceState interfaceState) { |
| this.interfaceState = interfaceState; |
| } |
| |
| /** |
| * Returns the circuit ID. |
| * |
| * @return circuit ID |
| */ |
| public String circuitId() { |
| return circuitId; |
| } |
| |
| /** |
| * Sets the circuit ID. |
| * |
| * @param circuitId circuit ID |
| */ |
| public void setCircuitId(String circuitId) { |
| this.circuitId = circuitId; |
| } |
| |
| /** |
| * Processes received ISIS message. |
| * When an ISIS message received it is handed over to this method. |
| * Based on the type of the ISIS message received it will be handed over |
| * to corresponding message handler methods. |
| * |
| * @param isisMessage received ISIS message |
| * @param isisLsdb ISIS LSDB instance |
| */ |
| public void processIsisMessage(IsisMessage isisMessage, IsisLsdb isisLsdb, Channel channel) { |
| log.debug("IsisInterfaceImpl::processIsisMessage...!!!"); |
| if (channel == null) { |
| this.channel = channel; |
| } |
| if (this.isisLsdb == null) { |
| this.isisLsdb = isisLsdb; |
| } |
| |
| switch (isisMessage.isisPduType()) { |
| case L1HELLOPDU: |
| case L2HELLOPDU: |
| processL1L2HelloPduMessage(isisMessage, channel); |
| break; |
| case P2PHELLOPDU: |
| processP2pHelloPduMessage(isisMessage, channel); |
| break; |
| case L1LSPDU: |
| case L2LSPDU: |
| processLsPduMessage(isisMessage, channel); |
| break; |
| case L1CSNP: |
| case L2CSNP: |
| processCsnPduMessage(isisMessage, channel); |
| break; |
| case L1PSNP: |
| case L2PSNP: |
| log.debug("Received a PSNP packet...!!!"); |
| break; |
| default: |
| log.debug("Unknown packet to process...!!!"); |
| break; |
| } |
| } |
| |
| /** |
| * Validates the received message. |
| * |
| * @param helloPdu ISIS message instance |
| * @return true if valid ISIS message else false |
| */ |
| public boolean validateHelloMessage(HelloPdu helloPdu) { |
| boolean isValid = false; |
| |
| //Local InterfaceAddress TLV and compare with the IP Interface address and check if they are in same subnet |
| List<Ip4Address> interfaceIpAddresses = helloPdu.interfaceIpAddresses(); |
| Ip4Address neighborIp = (helloPdu.interfaceIpAddresses() != null) ? |
| interfaceIpAddresses.get(0) : Ip4Address.valueOf("0.0.0.0"); |
| if (!IsisUtil.sameNetwork(interfaceIpAddress, neighborIp, networkMask)) { |
| return false; |
| } |
| |
| //Verify if it's in same area, Areas which the router belongs to |
| List<String> areas = helloPdu.areaAddress(); |
| for (String area : areas) { |
| if (areaAddress.equals(area)) { |
| isValid = true; |
| } |
| } |
| |
| return isValid; |
| } |
| |
| /** |
| * Checks neighbor presents in the list or not. |
| * |
| * @param neighborMac neighbor MAc address |
| * @return true if neighbor exist else false |
| */ |
| private boolean isNeighborInList(MacAddress neighborMac) { |
| return neighborList.containsKey(neighborMac); |
| } |
| |
| /** |
| * Adds neighbor in the list. |
| * |
| * @param neighbor neighbor MAC address |
| * @return true if neighbor exist else false |
| */ |
| private void addNeighbouringRouter(IsisNeighbor neighbor) { |
| neighborList.put(neighbor.neighborMacAddress(), neighbor); |
| } |
| |
| /** |
| * Returns neighbor presents in the list. |
| * |
| * @param neighborMac neighbor MAc address |
| * @return neighbor instance |
| */ |
| private IsisNeighbor neighbouringRouter(MacAddress neighborMac) { |
| return neighborList.get(neighborMac); |
| } |
| |
| /** |
| * Processes the L1 or L2 hello message. |
| * |
| * @param isisMessage hello message instance |
| * @param channel channel instance |
| */ |
| public void processL1L2HelloPduMessage(IsisMessage isisMessage, Channel channel) { |
| log.debug("Enters processL1L2HelloPduMessage ...!!!"); |
| log.debug("IsisInterfaceImpl::processHelloMessage...!!!"); |
| |
| L1L2HelloPdu helloPacket = (L1L2HelloPdu) isisMessage; |
| log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} ISISInterfaceState {} ", |
| networkType, interfaceState); |
| |
| //If L1 Hello, validate the area, network and max address |
| if (IsisPduType.get(helloPacket.pduType()) == IsisPduType.L1HELLOPDU && |
| !validateHelloMessage(helloPacket)) { |
| return; |
| } |
| |
| //Get the neighbor |
| IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac()); |
| //Neighbor is not in list |
| if (!isNeighborInList(isisMessage.sourceMac())) { |
| neighbor = new DefaultIsisNeighbor(helloPacket, this); |
| addNeighbouringRouter(neighbor); |
| } |
| |
| neighbor.stopInactivityTimeCheck(); |
| neighbor.startInactivityTimeCheck(); |
| |
| //Assign the DIS |
| String lanId = helloPacket.lanId(); |
| |
| if (IsisPduType.L1HELLOPDU == helloPacket.isisPduType()) { |
| buildUpdateAndSendSelfGeneratedLspIfDisChange(l1LanId, lanId, channel); |
| l1LanId = lanId; |
| neighbor.setL1LanId(lanId); |
| //if a change in lanid |
| } else if (IsisPduType.L2HELLOPDU == helloPacket.isisPduType()) { |
| buildUpdateAndSendSelfGeneratedLspIfDisChange(l1LanId, lanId, channel); |
| l2LanId = lanId; |
| neighbor.setL2LanId(lanId); |
| } |
| |
| //Check in neighbors list our MAC address present |
| List<MacAddress> neighbors = helloPacket.neighborList(); |
| for (MacAddress macAddress : neighbors) { |
| if (interfaceMacAddress.equals(macAddress)) { |
| neighbor.setNeighborState(IsisInterfaceState.UP); |
| //Build Self LSP add in LSDB and sent it. |
| buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel); |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Builds and store and send self generated LSP. |
| * |
| * @param channel netty channel instance |
| */ |
| private void buildStoreAndSendSelfGeneratedLspIfNotExistInDb(Channel channel) { |
| //Check our LSP is present in DB. else create a self LSP and store it and sent it |
| String lspKey = isisLsdb.lspKey(systemId); |
| LspWrapper wrapper = null; |
| if (reservedPacketCircuitType == IsisRouterType.L1.value()) { |
| wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey); |
| if (wrapper == null) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } |
| } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) { |
| wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey); |
| if (wrapper == null) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } |
| } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) { |
| wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey); |
| if (wrapper == null) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } |
| |
| wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey); |
| if (wrapper == null) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } |
| } |
| } |
| |
| /** |
| * Builds and update in DB and send self generated LSP. |
| * |
| * @param previousLanId previous DIS ID |
| * @param latestLanId latest DIS ID |
| * @param channel netty channel instance |
| */ |
| private void buildUpdateAndSendSelfGeneratedLspIfDisChange(String previousLanId, |
| String latestLanId, Channel channel) { |
| //If DIS change then build and sent LSP |
| if (previousLanId != null && !previousLanId.equals(IsisConstants.DEFAULTLANID) && |
| !previousLanId.equals(latestLanId)) { |
| //Create a self LSP and Update it in DB and sent it |
| String lspKey = isisLsdb.lspKey(systemId); |
| if (reservedPacketCircuitType == IsisRouterType.L1.value()) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) { |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) { |
| //L1 LSPDU |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| //L1 LSPDU |
| lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps); |
| isisLsdb.addLsp(lsp, true, this); |
| sendLsp(lsp, channel); |
| } |
| } |
| |
| } |
| |
| /** |
| * Sends LS PDU message to channel. |
| * |
| * @param lsp LS PDU message instance |
| * @param channel channel instance |
| */ |
| private void sendLsp(LsPdu lsp, Channel channel) { |
| byte[] lspBytes = lsp.asBytes(); |
| lspBytes = IsisUtil.addLengthAndMarkItInReserved(lspBytes, IsisConstants.LENGTHPOSITION, |
| IsisConstants.LENGTHPOSITION + 1, |
| IsisConstants.RESERVEDPOSITION); |
| lspBytes = IsisUtil.addChecksum(lspBytes, IsisConstants.CHECKSUMPOSITION, |
| IsisConstants.CHECKSUMPOSITION + 1); |
| //write to the channel |
| channel.write(IsisUtil.framePacket(lspBytes, interfaceIndex)); |
| } |
| |
| /** |
| * Processes P2P hello message. |
| * |
| * @param isisMessage hello message instance |
| * @param channel channel instance |
| */ |
| public void processP2pHelloPduMessage(IsisMessage isisMessage, Channel channel) { |
| log.debug("Enters processP2pHelloPduMessage ...!!!"); |
| P2PHelloPdu helloPacket = (P2PHelloPdu) isisMessage; |
| |
| log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} OSPFInterfaceState {} ", |
| networkType, interfaceState); |
| |
| //validate the area, network and max address |
| if (!validateHelloMessage(helloPacket)) { |
| return; |
| } |
| |
| IsisNeighbor neighbor = null; |
| List<IsisTlv> tlvs = ((P2PHelloPdu) isisMessage).tlvs(); |
| AdjacencyStateTlv stateTlv = null; |
| for (IsisTlv tlv : tlvs) { |
| if (tlv instanceof AdjacencyStateTlv) { |
| stateTlv = (AdjacencyStateTlv) tlv; |
| break; |
| } |
| } |
| |
| if (stateTlv == null) { |
| neighbor = neighbouringRouter(isisMessage.sourceMac()); |
| if (neighbor == null) { |
| neighbor = new DefaultIsisNeighbor(helloPacket, this); |
| addNeighbouringRouter(neighbor); |
| } |
| neighbor.setNeighborState(IsisInterfaceState.DOWN); |
| buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel); |
| } else if (stateTlv.adjacencyType() == IsisInterfaceState.DOWN.value()) { |
| neighbor = neighbouringRouter(isisMessage.sourceMac()); |
| if (neighbor == null) { |
| neighbor = new DefaultIsisNeighbor(helloPacket, this); |
| addNeighbouringRouter(neighbor); |
| } |
| neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId()); |
| } else if (stateTlv.adjacencyType() == IsisInterfaceState.INITIAL.value()) { |
| //Neighbor already present in the list |
| neighbor = neighbouringRouter(isisMessage.sourceMac()); |
| neighbor.setNeighborState(IsisInterfaceState.INITIAL); |
| neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId()); |
| //interfaceState = IsisInterfaceState.UP; |
| } else if (stateTlv.adjacencyType() == IsisInterfaceState.UP.value()) { |
| //Build Self LSP add in LSDB and sent it. |
| neighbor = neighbouringRouter(isisMessage.sourceMac()); |
| neighbor.setNeighborState(IsisInterfaceState.UP); |
| neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId()); |
| buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel); |
| } |
| |
| neighbor.stopInactivityTimeCheck(); |
| neighbor.startInactivityTimeCheck(); |
| } |
| |
| /** |
| * Processes LS PDU message. |
| * |
| * @param isisMessage LS pdu message instance |
| * @param channel channel instance |
| */ |
| public void processLsPduMessage(IsisMessage isisMessage, Channel channel) { |
| log.debug("Enters processLsPduMessage ...!!!"); |
| LsPdu lsPdu = (LsPdu) isisMessage; |
| LspWrapper wrapper = isisLsdb.findLsp(lsPdu.isisPduType(), lsPdu.lspId()); |
| if (wrapper == null || isisLsdb.isNewerOrSameLsp(lsPdu, wrapper.lsPdu()).equalsIgnoreCase("latest")) { |
| //not exist in the database or latest, then add it in database |
| isisLsdb.addLsp(lsPdu, false, this); |
| } |
| |
| //If network type is P2P, acknowledge with a PSNP |
| if (networkType() == IsisNetworkType.P2P) { |
| IsisPduType psnpType = null; |
| if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L1LSPDU) { |
| psnpType = IsisPduType.L1PSNP; |
| } else if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L2LSPDU) { |
| psnpType = IsisPduType.L2PSNP; |
| } |
| IsisHeader isisHeader = new LspGenerator().getHeader(psnpType); |
| Psnp psnp = new Psnp(isisHeader); |
| psnp.setSourceId(lspKeyP2P(this.systemId)); |
| TlvHeader tlvHeader = new TlvHeader(); |
| tlvHeader.setTlvType(TlvType.LSPENTRY.value()); |
| tlvHeader.setTlvLength(0); |
| LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader); |
| LspEntry lspEntry = new LspEntry(); |
| lspEntry.setLspChecksum(lsPdu.checkSum()); |
| lspEntry.setLspId(lsPdu.lspId()); |
| lspEntry.setLspSequenceNumber(lsPdu.sequenceNumber()); |
| lspEntry.setRemainingTime(lsPdu.remainingLifeTime()); |
| lspEntriesTlv.addLspEntry(lspEntry); |
| psnp.addTlv(lspEntriesTlv); |
| |
| //write it to channel buffer. |
| byte[] psnpBytes = psnp.asBytes(); |
| psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION, |
| IsisConstants.LENGTHPOSITION + 1, |
| IsisConstants.RESERVEDPOSITION); |
| flagValue = false; |
| //write to the channel |
| channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex)); |
| } |
| } |
| |
| /** |
| * Processes CSN PDU message. |
| * |
| * @param isisMessage CSN PDU message instance |
| * @param channel channel instance |
| */ |
| public void processCsnPduMessage(IsisMessage isisMessage, Channel channel) { |
| log.debug("Enters processCsnPduMessage ...!!!"); |
| if (reservedPacketCircuitType == IsisRouterType.L1.value()) { |
| processOnL1CsnPdu(isisMessage, channel); |
| } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) { |
| processOnL2CsnPdu(isisMessage, channel); |
| } |
| } |
| |
| /** |
| * Process the isisMessage which belongs to L1 CSN PDU. |
| * checks the database for this LsPdu if it exists further check for sequence number |
| * sequence number is greater will send PsnPdu. |
| * |
| * @param isisMessage CSN PDU message instance |
| * @param channel netty channel instance |
| */ |
| private void processOnL1CsnPdu(IsisMessage isisMessage, Channel channel) { |
| Csnp csnPacket = (Csnp) isisMessage; |
| List<LspEntry> lspEntryRequestList = new ArrayList<>(); |
| boolean selfOriginatedFound = false; |
| if (IsisPduType.L1CSNP.equals(csnPacket.isisPduType())) { |
| List<IsisTlv> isisTlvs = csnPacket.getAllTlv(); |
| Iterator iterator = isisTlvs.iterator(); |
| while (iterator.hasNext()) { |
| IsisTlv isisTlv = (IsisTlv) iterator.next(); |
| if (isisTlv instanceof LspEntriesTlv) { |
| LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv; |
| List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry(); |
| Iterator lspEntryListIterator = lspEntryList.iterator(); |
| while (lspEntryListIterator.hasNext()) { |
| LspEntry lspEntry = (LspEntry) lspEntryListIterator.next(); |
| String lspKey = lspEntry.lspId(); |
| LspWrapper lspWrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey); |
| if (lspWrapper != null) { |
| LsPdu lsPdu = (LsPdu) lspWrapper.lsPdu(); |
| if (lspWrapper.isSelfOriginated()) { |
| selfOriginatedFound = true; |
| if (lspEntry.lspSequenceNumber() > lsPdu.sequenceNumber()) { |
| sendLsPduMessage(lspEntry.lspSequenceNumber(), csnPacket.isisPduType(), channel); |
| } |
| } else { |
| if (lsPdu.sequenceNumber() < lspEntry.lspSequenceNumber()) { |
| lspEntryRequestList.add(lspEntry); |
| flagValue = true; |
| } |
| } |
| } else { |
| lspEntryRequestList.add(lspEntry); |
| flagValue = true; |
| } |
| } |
| } |
| } |
| if (flagValue) { |
| sendPsnPduMessage(lspEntryRequestList, csnPacket.isisPduType(), channel); |
| } |
| |
| if (!selfOriginatedFound) { |
| String lspKey = isisLsdb.lspKey(systemId); |
| LspWrapper wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey); |
| sendLsp((LsPdu) wrapper.lsPdu(), channel); |
| } |
| } |
| } |
| |
| /** |
| * Process the isisMessage which belongs to L2 CSNP. |
| * checks the database for this LsPdu if it exists further check for sequence number |
| * sequence number is greater will send PsnPdu. |
| * |
| * @param isisMessage received CSNP message |
| * @param channel netty channel instance |
| */ |
| private void processOnL2CsnPdu(IsisMessage isisMessage, Channel channel) { |
| Csnp csnPacket = (Csnp) isisMessage; |
| List<LspEntry> lspEntryRequestList = new ArrayList<>(); |
| boolean selfOriginatedFound = false; |
| if (IsisPduType.L2CSNP.equals(csnPacket.isisPduType())) { |
| List<IsisTlv> isisTlvs = csnPacket.getAllTlv(); |
| Iterator iterator = isisTlvs.iterator(); |
| while (iterator.hasNext()) { |
| IsisTlv isisTlv = (IsisTlv) iterator.next(); |
| if (isisTlv instanceof LspEntriesTlv) { |
| LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv; |
| List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry(); |
| Iterator lspEntryListIterator = lspEntryList.iterator(); |
| while (lspEntryListIterator.hasNext()) { |
| LspEntry lspEntry = (LspEntry) lspEntryListIterator.next(); |
| String lspKey = lspEntry.lspId(); |
| LspWrapper lspWrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey); |
| if (lspWrapper != null) { |
| LsPdu lsPdu = (LsPdu) lspWrapper.lsPdu(); |
| if (lspWrapper.isSelfOriginated()) { |
| selfOriginatedFound = true; |
| if (lspEntry.lspSequenceNumber() > lsPdu.sequenceNumber()) { |
| sendLsPduMessage(lspEntry.lspSequenceNumber(), csnPacket.isisPduType(), channel); |
| } |
| } else { |
| if (lsPdu.sequenceNumber() < lspEntry.lspSequenceNumber()) { |
| lspEntryRequestList.add(lspEntry); |
| flagValue = true; |
| } |
| } |
| } else { |
| lspEntryRequestList.add(lspEntry); |
| flagValue = true; |
| } |
| } |
| } |
| } |
| if (flagValue) { |
| sendPsnPduMessage(lspEntryRequestList, csnPacket.isisPduType(), channel); |
| lspEntryRequestList.clear(); |
| } |
| |
| if (!selfOriginatedFound) { |
| String lspKey = isisLsdb.lspKey(systemId); |
| LspWrapper wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey); |
| sendLsp((LsPdu) wrapper.lsPdu(), channel); |
| } |
| } |
| } |
| |
| /** |
| * Sends the partial sequence number PDU. |
| * |
| * @param lspEntryRequestList list of lsp entry request |
| * @param isisPduType intermediate system PDU type |
| * @param channel netty channel instance |
| */ |
| private void sendPsnPduMessage(List<LspEntry> lspEntryRequestList, IsisPduType isisPduType, Channel channel) { |
| IsisPduType psnpType = null; |
| if (isisPduType == IsisPduType.L1CSNP) { |
| psnpType = IsisPduType.L1PSNP; |
| } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) { |
| psnpType = IsisPduType.L2PSNP; |
| } |
| IsisHeader isisHeader = new LspGenerator().getHeader(psnpType); |
| Psnp psnp = new Psnp(isisHeader); |
| psnp.setSourceId(lspKeyP2P(this.systemId)); |
| TlvHeader tlvHeader = new TlvHeader(); |
| tlvHeader.setTlvType(TlvType.LSPENTRY.value()); |
| tlvHeader.setTlvLength(0); |
| LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader); |
| for (LspEntry lspEntry : lspEntryRequestList) { |
| lspEntriesTlv.addLspEntry(lspEntry); |
| } |
| psnp.addTlv(lspEntriesTlv); |
| //write it to channel buffer. |
| byte[] psnpBytes = psnp.asBytes(); |
| psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION, |
| IsisConstants.LENGTHPOSITION + 1, |
| IsisConstants.RESERVEDPOSITION); |
| flagValue = false; |
| //write to the channel |
| channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex)); |
| } |
| |
| /** |
| * Gets the LSP key. |
| * |
| * @param systemId system ID |
| * @return key |
| */ |
| public String lspKeyP2P(String systemId) { |
| StringBuilder lspKey = new StringBuilder(); |
| lspKey.append(systemId); |
| lspKey.append(".00"); |
| return lspKey.toString(); |
| } |
| |
| /** |
| * Sends the link state PDU with latest self generated lsp entry. |
| * |
| * @param sequenceNumber sequence number of the self generated lsp |
| * @param isisPduType intermediate system type |
| * @param channel netty channel instance |
| */ |
| private void sendLsPduMessage(int sequenceNumber, IsisPduType isisPduType, Channel channel) { |
| String lspKey = isisLsdb.lspKey(systemId); |
| LsPdu lsp = new LspGenerator().getLsp(this, lspKey, isisPduType, allConfiguredInterfaceIps); |
| lsp.setSequenceNumber(sequenceNumber); |
| byte[] lspBytes = lsp.asBytes(); |
| lspBytes = IsisUtil.addLengthAndMarkItInReserved(lspBytes, IsisConstants.LENGTHPOSITION, |
| IsisConstants.LENGTHPOSITION + 1, |
| IsisConstants.RESERVEDPOSITION); |
| lspBytes = IsisUtil.addChecksum(lspBytes, IsisConstants.CHECKSUMPOSITION, |
| IsisConstants.CHECKSUMPOSITION + 1); |
| //write to the channel |
| channel.write(IsisUtil.framePacket(lspBytes, interfaceIndex)); |
| } |
| |
| |
| /** |
| * Starts the hello timer which sends hello packet every configured seconds. |
| * |
| * @param channel netty channel instance |
| */ |
| public void startHelloSender(Channel channel) { |
| log.debug("IsisInterfaceImpl::startHelloSender"); |
| |
| isisHelloPduSender = new IsisHelloPduSender(channel, this); |
| exServiceHello = Executors.newSingleThreadScheduledExecutor(); |
| final ScheduledFuture<?> helloHandle = |
| exServiceHello.scheduleAtFixedRate(isisHelloPduSender, 0, |
| helloInterval, TimeUnit.SECONDS); |
| } |
| } |