blob: bbeb4ddd9cbc6da3bb673786b100f81beedf9f73 [file] [log] [blame]
/*
* 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);
}
}