ONOS-4086 to ONOS-4091, ONOS-4098 to ONOS-4100:ISIS controller implementation
Change-Id: I7be52805652fe762baf808515401d6b5042b2aa5
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/Controller.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/Controller.java
new file mode 100755
index 0000000..c12c520
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/Controller.java
@@ -0,0 +1,241 @@
+/*
+ * 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 com.fasterxml.jackson.databind.JsonNode;
+import org.jboss.netty.bootstrap.ClientBootstrap;
+import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictor;
+import org.jboss.netty.channel.ChannelFuture;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
+import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisNetworkType;
+import org.onosproject.isis.controller.IsisProcess;
+import org.onosproject.isis.controller.IsisRouterType;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+
+import static org.onlab.util.Tools.groupedThreads;
+
+/**
+ * Representation of an ISIS controller.
+ */
+public class Controller {
+ protected static final int BUFFER_SIZE = 4 * 1024 * 1024;
+ private static final Logger log = LoggerFactory.getLogger(Controller.class);
+ private final int peerWorkerThreads = 16;
+ private List<IsisProcess> processes = null;
+ private IsisChannelHandler isisChannelHandler;
+ private NioClientSocketChannelFactory peerExecFactory;
+ private ClientBootstrap peerBootstrap = null;
+ private TpPort isisPort = TpPort.tpPort(IsisConstants.SPORT);
+
+ /**
+ * Deactivates ISIS controller.
+ */
+ public void isisDeactivate() {
+ peerExecFactory.shutdown();
+ }
+
+ /**
+ * Updates the processes configuration.
+ *
+ * @param jsonNode json node instance
+ * @throws Exception might throws parse exception
+ */
+ public void updateConfig(JsonNode jsonNode) throws Exception {
+ log.debug("Controller::UpdateConfig called");
+ byte[] configPacket = new byte[IsisConstants.CONFIG_LENGTH];
+ byte numberOfInterface = 0; // number of interfaces to configure
+
+ configPacket[0] = (byte) 0xFF; // its a conf packet - identifier
+ List<IsisProcess> isisProcesses = getConfig(jsonNode);
+
+ for (IsisProcess isisProcess : isisProcesses) {
+ log.debug("IsisProcessDetails : " + isisProcess);
+ for (IsisInterface isisInterface : isisProcess.isisInterfaceList()) {
+ DefaultIsisInterface isisInterfaceImpl = (DefaultIsisInterface) isisInterface;
+ log.debug("IsisInterfaceDetails : " + isisInterface);
+ numberOfInterface++;
+ configPacket[2 * numberOfInterface] = (byte) isisInterfaceImpl.interfaceIndex();
+ if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
+ isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L1.value()) {
+ configPacket[(2 * numberOfInterface) + 1] = (byte) 0;
+ } else if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
+ isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L2.value()) {
+ configPacket[(2 * numberOfInterface) + 1] = (byte) 1;
+ } else if (isisInterface.networkType() == IsisNetworkType.P2P) {
+ configPacket[(2 * numberOfInterface) + 1] = (byte) 2;
+ } else if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
+ isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L1L2.value()) {
+ configPacket[(2 * numberOfInterface) + 1] = (byte) 3;
+ }
+ }
+ }
+ configPacket[1] = numberOfInterface;
+ //First time configuration
+ if (processes == null) {
+ processes = isisProcesses;
+ //Initialize connection by creating a channel handler instance and sent the config packet);
+ initConnection();
+ //Initializing the interface map in channel handler
+ isisChannelHandler.initializeInterfaceMap();
+ } else {
+ isisChannelHandler.updateInterfaceMap(isisProcesses);
+ }
+ //Send the config packet
+ isisChannelHandler.sentConfigPacket(configPacket);
+ }
+
+ /**
+ * Initializes the netty client channel connection.
+ */
+ private void initConnection() {
+ if (peerBootstrap != null) {
+ return;
+ }
+ peerBootstrap = createPeerBootStrap();
+
+ peerBootstrap.setOption("reuseAddress", true);
+ peerBootstrap.setOption("tcpNoDelay", true);
+ peerBootstrap.setOption("keepAlive", true);
+ peerBootstrap.setOption("receiveBufferSize", Controller.BUFFER_SIZE);
+ peerBootstrap.setOption("receiveBufferSizePredictorFactory",
+ new FixedReceiveBufferSizePredictorFactory(
+ Controller.BUFFER_SIZE));
+ peerBootstrap.setOption("receiveBufferSizePredictor",
+ new AdaptiveReceiveBufferSizePredictor(64, 1024, 65536));
+ peerBootstrap.setOption("child.keepAlive", true);
+ peerBootstrap.setOption("child.tcpNoDelay", true);
+ peerBootstrap.setOption("child.sendBufferSize", Controller.BUFFER_SIZE);
+ peerBootstrap.setOption("child.receiveBufferSize", Controller.BUFFER_SIZE);
+ peerBootstrap.setOption("child.receiveBufferSizePredictorFactory",
+ new FixedReceiveBufferSizePredictorFactory(
+ Controller.BUFFER_SIZE));
+ peerBootstrap.setOption("child.reuseAddress", true);
+
+ isisChannelHandler = new IsisChannelHandler(this, processes);
+ ChannelPipelineFactory pfact = new IsisPipelineFactory(isisChannelHandler);
+ peerBootstrap.setPipelineFactory(pfact);
+ ChannelFuture connection = peerBootstrap.connect(new InetSocketAddress(IsisConstants.SHOST, isisPort.toInt()));
+ }
+
+ /**
+ * Creates peer boot strap.
+ *
+ * @return client bootstrap instance
+ */
+ private ClientBootstrap createPeerBootStrap() {
+
+ if (peerWorkerThreads == 0) {
+ peerExecFactory = new NioClientSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/isis", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/isis", "worker-%d")));
+ return new ClientBootstrap(peerExecFactory);
+ } else {
+ peerExecFactory = new NioClientSocketChannelFactory(
+ Executors.newCachedThreadPool(groupedThreads("onos/isis", "boss-%d")),
+ Executors.newCachedThreadPool(groupedThreads("onos/isis", "worker-%d")),
+ peerWorkerThreads);
+ return new ClientBootstrap(peerExecFactory);
+ }
+ }
+
+ /**
+ * Gets all configured processes.
+ *
+ * @return all configured processes
+ */
+ public List<IsisProcess> getAllConfiguredProcesses() {
+ return processes;
+ }
+
+ /**
+ * Gets the list of processes configured.
+ *
+ * @param json posted json
+ * @return list of processes configured
+ */
+ private List<IsisProcess> getConfig(JsonNode json) throws Exception {
+
+ List<IsisProcess> isisProcessesList = new ArrayList<>();
+ JsonNode jsonNodes = json;
+
+ if (jsonNodes == null) {
+ return isisProcessesList;
+ }
+ jsonNodes.forEach(jsonNode -> {
+ List<IsisInterface> interfaceList = new ArrayList<>();
+ for (JsonNode jsonNode1 : jsonNode.path(IsisConstants.INTERFACE)) {
+ IsisInterface isisInterface = new DefaultIsisInterface();
+ isisInterface.setInterfaceIndex(jsonNode1.path(IsisConstants.INTERFACEINDEX).asInt());
+ isisInterface.setInterfaceIpAddress(Ip4Address.valueOf(jsonNode1
+ .path(IsisConstants.INTERFACEIP)
+ .asText()));
+ try {
+ isisInterface.setNetworkMask(InetAddress.getByName((jsonNode1
+ .path(IsisConstants.NETWORKMASK).asText())).getAddress());
+ } catch (UnknownHostException e) {
+ log.debug("Error:: Parsing network mask");
+ }
+ isisInterface.setInterfaceMacAddress(MacAddress.valueOf(jsonNode1
+ .path(IsisConstants.MACADDRESS)
+ .asText()));
+ isisInterface.setIntermediateSystemName(jsonNode1
+ .path(IsisConstants.INTERMEDIATESYSTEMNAME)
+ .asText());
+ isisInterface.setSystemId(jsonNode1.path(IsisConstants.SYSTEMID).asText());
+ isisInterface.setReservedPacketCircuitType(jsonNode1
+ .path(IsisConstants.RESERVEDPACKETCIRCUITTYPE)
+ .asInt());
+ if (isisInterface.reservedPacketCircuitType() == IsisRouterType.L1.value()) {
+ isisInterface.setL1LanId(jsonNode1.path(IsisConstants.LANID).asText());
+ }
+ isisInterface.setIdLength(jsonNode1.path(IsisConstants.IDLENGTH).asInt());
+ isisInterface.setMaxAreaAddresses(jsonNode1.path(IsisConstants.MAXAREAADDRESSES).asInt());
+ isisInterface.setNetworkType(IsisNetworkType.get(jsonNode1
+ .path(IsisConstants.NETWORKTYPE)
+ .asInt()));
+ isisInterface.setAreaAddress(jsonNode1.path(IsisConstants.AREAADDRESS).asText());
+ isisInterface.setAreaLength(jsonNode1.path(IsisConstants.AREALENGTH).asInt());
+ isisInterface.setLspId(jsonNode1.path(IsisConstants.LSPID).asText());
+ isisInterface.setCircuitId(jsonNode1.path(IsisConstants.CIRCUITID).asText());
+ isisInterface.setHoldingTime(jsonNode1.path(IsisConstants.HOLDINGTIME).asInt());
+ isisInterface.setPriority(jsonNode1.path(IsisConstants.PRIORITY).asInt());
+ isisInterface.setHelloInterval(jsonNode1.path(IsisConstants.HELLOINTERVAL).asInt());
+ interfaceList.add(isisInterface);
+ }
+ IsisProcess process = new DefaultIsisProcess();
+ process.setProcessId(jsonNode.path(IsisConstants.PROCESSESID).asText());
+ process.setIsisInterfaceList(interfaceList);
+ isisProcessesList.add(process);
+ });
+
+ return isisProcessesList;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisController.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisController.java
new file mode 100755
index 0000000..0929db4
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisController.java
@@ -0,0 +1,82 @@
+/*
+ * 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 com.fasterxml.jackson.databind.JsonNode;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.isis.controller.IsisController;
+import org.onosproject.isis.controller.IsisProcess;
+import org.onosproject.isis.controller.topology.IsisRouterListener;
+import org.onosproject.net.driver.DriverService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Represents ISIS controller implementation.
+ */
+@Component(immediate = true)
+@Service
+public class DefaultIsisController implements IsisController {
+
+ protected static final Logger log = LoggerFactory.getLogger(DefaultIsisController.class);
+ private final Controller controller = new Controller();
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Activate
+ public void activate() {
+ log.debug("ISISControllerImpl activate");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ controller.isisDeactivate();
+ log.debug("ISISControllerImpl deActivate");
+ }
+
+ @Override
+ public List<IsisProcess> allConfiguredProcesses() {
+ List<IsisProcess> processes = controller.getAllConfiguredProcesses();
+ return processes;
+ }
+
+ @Override
+ public void updateConfig(JsonNode jsonNode) {
+ log.debug("updateConfig::IsisList::processes::{}", jsonNode);
+ try {
+ controller.updateConfig(jsonNode);
+ } catch (Exception e) {
+ log.debug("Error::updateConfig::{}", e.getMessage());
+ }
+ }
+
+ @Override
+ public void addRouterListener(IsisRouterListener isisRouterListener) {
+ log.debug("IsisControllerImpl::addRouterListener...");
+ }
+
+ @Override
+ public void removeRouterListener(IsisRouterListener isisRouterListener) {
+ log.debug("IsisControllerImpl::removeRouterListener...");
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisInterface.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisInterface.java
new file mode 100755
index 0000000..bbeb4dd
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisInterface.java
@@ -0,0 +1,1086 @@
+/*
+ * 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);
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisNeighbor.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisNeighbor.java
new file mode 100755
index 0000000..3180c5d
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisNeighbor.java
@@ -0,0 +1,350 @@
+/*
+ * 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.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.IsisNeighbor;
+import org.onosproject.isis.controller.IsisPduType;
+import org.onosproject.isis.controller.IsisRouterType;
+import org.onosproject.isis.io.isispacket.pdu.HelloPdu;
+import org.onosproject.isis.io.isispacket.pdu.L1L2HelloPdu;
+import org.onosproject.isis.io.isispacket.pdu.P2PHelloPdu;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Representation of an ISIS neighbor.
+ * The first thing an ISIS router must do is find its neighbors and form adjacency.
+ * Each neighbor that the router finds will be represented by this class.
+ */
+public class DefaultIsisNeighbor implements IsisNeighbor {
+ private static final Logger log = LoggerFactory.getLogger(DefaultIsisNeighbor.class);
+ private String neighborAreaId;
+ private String neighborSystemId;
+ private Ip4Address interfaceIp;
+ private MacAddress neighborMacAddress;
+ private int holdingTime;
+ private IsisRouterType routerType;
+ private String l1LanId;
+ private String l2LanId;
+ private byte localCircuitId;
+ private int localExtendedCircuitId;
+ private IsisInterfaceState neighborState = IsisInterfaceState.INITIAL;
+ private InternalInactivityTimeCheck inActivityTimeCheckTask;
+ private ScheduledExecutorService exServiceInActivity;
+ private boolean inActivityTimerScheduled = false;
+ private IsisInterface isisInterface;
+
+ /**
+ * Creates an instance of ISIS neighbor.
+ *
+ * @param helloMessage hello message instance
+ * @param isisInterface ISIS interface instance
+ */
+ public DefaultIsisNeighbor(HelloPdu helloMessage, IsisInterface isisInterface) {
+ this.neighborMacAddress = helloMessage.sourceMac();
+ List<String> areaAddresses = helloMessage.areaAddress();
+ this.neighborAreaId = (areaAddresses != null) ? areaAddresses.get(0) : "";
+ this.neighborSystemId = helloMessage.sourceId();
+ List<Ip4Address> interfaceIpAddresses = helloMessage.interfaceIpAddresses();
+ this.interfaceIp = (helloMessage.interfaceIpAddresses() != null) ?
+ interfaceIpAddresses.get(0) : IsisConstants.DEFAULTIP;
+ this.holdingTime = helloMessage.holdingTime();
+ this.routerType = IsisRouterType.get(helloMessage.circuitType());
+ if (helloMessage instanceof L1L2HelloPdu) {
+ if (IsisPduType.L1HELLOPDU == helloMessage.isisPduType()) {
+ l1LanId = ((L1L2HelloPdu) helloMessage).lanId();
+ } else if (IsisPduType.L2HELLOPDU == helloMessage.isisPduType()) {
+ l2LanId = ((L1L2HelloPdu) helloMessage).lanId();
+ }
+ } else if (helloMessage instanceof P2PHelloPdu) {
+ this.localCircuitId = ((P2PHelloPdu) helloMessage).localCircuitId();
+ }
+ this.isisInterface = isisInterface;
+ }
+
+ /**
+ * Returns local extended circuit ID.
+ *
+ * @return local extended circuit ID
+ */
+ public int localExtendedCircuitId() {
+ return localExtendedCircuitId;
+ }
+
+ /**
+ * Sets local extended circuit ID.
+ *
+ * @param localExtendedCircuitId neighbor extended circuit ID
+ */
+ public void setLocalExtendedCircuitId(int localExtendedCircuitId) {
+ this.localExtendedCircuitId = localExtendedCircuitId;
+ }
+
+ /**
+ * Returns neighbor area ID.
+ *
+ * @return neighbor area ID
+ */
+ public String neighborAreaId() {
+ return neighborAreaId;
+ }
+
+ /**
+ * Sets neighbor area ID.
+ *
+ * @param neighborAreaId neighbor area ID
+ */
+ public void setNeighborAreaId(String neighborAreaId) {
+ this.neighborAreaId = neighborAreaId;
+ }
+
+ /**
+ * Returns neighbor system ID.
+ *
+ * @return neighbor system ID
+ */
+ public String neighborSystemId() {
+ return neighborSystemId;
+ }
+
+ /**
+ * Sets neighbor system ID.
+ *
+ * @param neighborSystemId neighbor system ID
+ */
+ public void setNeighborSystemId(String neighborSystemId) {
+ this.neighborSystemId = neighborSystemId;
+ }
+
+ /**
+ * Returns interface IP.
+ *
+ * @return interface IP
+ */
+ public Ip4Address interfaceIp() {
+ return interfaceIp;
+ }
+
+ /**
+ * Sets interface IP.
+ *
+ * @param interfaceIp IP
+ */
+ public void setInterfaceIp(Ip4Address interfaceIp) {
+ this.interfaceIp = interfaceIp;
+ }
+
+ /**
+ * Returns neighbor mac address.
+ *
+ * @return neighborMacAddress neighbor mac address
+ */
+ public MacAddress neighborMacAddress() {
+ return neighborMacAddress;
+ }
+
+ /**
+ * Sets neighbor mac address.
+ *
+ * @param neighborMacAddress mac address
+ */
+ public void setNeighborMacAddress(MacAddress neighborMacAddress) {
+ this.neighborMacAddress = neighborMacAddress;
+ }
+
+ /**
+ * 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 router type.
+ *
+ * @return router type
+ */
+ public IsisRouterType routerType() {
+ return routerType;
+ }
+
+ /**
+ * Sets router type.
+ *
+ * @param routerType router type
+ */
+ public void setRouterType(IsisRouterType routerType) {
+ this.routerType = routerType;
+ }
+
+ /**
+ * Returns L1 lan ID.
+ *
+ * @return L1 lan ID
+ */
+ public String l1LanId() {
+ return l1LanId;
+ }
+
+ /**
+ * Sets L1 lan ID.
+ *
+ * @param l1LanId L1 lan ID
+ */
+ public void setL1LanId(String l1LanId) {
+ this.l1LanId = l1LanId;
+ }
+
+ /**
+ * Returns L2 lan ID.
+ *
+ * @return L2 lan ID
+ */
+ public String l2LanId() {
+ return l2LanId;
+ }
+
+ /**
+ * Sets L2 lan ID.
+ *
+ * @param l2LanId L2 lan ID
+ */
+ public void setL2LanId(String l2LanId) {
+ this.l1LanId = l1LanId;
+ }
+
+ /**
+ * Gets the neighbor interface state.
+ *
+ * @return neighbor interface state
+ */
+ public IsisInterfaceState interfaceState() {
+ return neighborState;
+ }
+
+ /**
+ * Sets the neighbor interface state.
+ *
+ * @param neighborState the neighbor interface state
+ */
+ public void setNeighborState(IsisInterfaceState neighborState) {
+ this.neighborState = neighborState;
+ }
+
+ /**
+ * Returns local circuit ID.
+ *
+ * @return local circuit ID
+ */
+ public byte localCircuitId() {
+ return localCircuitId;
+ }
+
+ /**
+ * Sets local circuit ID.
+ *
+ * @param localCircuitId local circuit ID
+ */
+ public void setLocalCircuitId(byte localCircuitId) {
+ this.localCircuitId = localCircuitId;
+ }
+
+ /**
+ * Returns neighbor state.
+ *
+ * @return neighbor state
+ */
+ public IsisInterfaceState neighborState() {
+ return neighborState;
+ }
+
+ /**
+ * Starts the inactivity timer.
+ */
+ public void startInactivityTimeCheck() {
+ if (!inActivityTimerScheduled) {
+ log.debug("IsisNeighbor::startInactivityTimeCheck");
+ inActivityTimeCheckTask = new InternalInactivityTimeCheck();
+ exServiceInActivity = Executors.newSingleThreadScheduledExecutor();
+ exServiceInActivity.scheduleAtFixedRate(inActivityTimeCheckTask, holdingTime,
+ holdingTime, TimeUnit.SECONDS);
+ inActivityTimerScheduled = true;
+ }
+ }
+
+ /**
+ * Stops the inactivity timer.
+ */
+ public void stopInactivityTimeCheck() {
+ if (inActivityTimerScheduled) {
+ log.debug("IsisNeighbor::stopInactivityTimeCheck ");
+ exServiceInActivity.shutdown();
+ inActivityTimerScheduled = false;
+ }
+ }
+
+ /**
+ * Called when neighbor is down.
+ */
+ public void neighborDown() {
+ log.debug("Neighbor Down {} and NeighborSystemId {}", neighborMacAddress,
+ neighborSystemId);
+ stopInactivityTimeCheck();
+ isisInterface.setL1LanId(IsisConstants.DEFAULTLANID);
+ isisInterface.setL2LanId(IsisConstants.DEFAULTLANID);
+
+ neighborState = IsisInterfaceState.DOWN;
+ isisInterface.removeNeighbor(this);
+ }
+
+ /**
+ * Represents a Task which will do an inactivity time check.
+ */
+ private class InternalInactivityTimeCheck implements Runnable {
+ /**
+ * Creates an instance.
+ */
+ InternalInactivityTimeCheck() {
+ }
+
+ @Override
+ public void run() {
+ log.debug("Neighbor Not Heard till the past router dead interval .");
+ neighborDown();
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisProcess.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisProcess.java
new file mode 100755
index 0000000..cc8bfd4
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/DefaultIsisProcess.java
@@ -0,0 +1,65 @@
+/*
+ * 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.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisProcess;
+
+import java.util.List;
+
+/**
+ * Represents of an ISIS process.
+ */
+public class DefaultIsisProcess implements IsisProcess {
+ private String processId;
+ private List<IsisInterface> isisInterfaceList;
+
+ /**
+ * Gets process ID.
+ *
+ * @return process ID
+ */
+ public String processId() {
+ return processId;
+ }
+
+ /**
+ * Sets process ID.
+ *
+ * @param processId process ID
+ */
+ public void setProcessId(String processId) {
+ this.processId = processId;
+ }
+
+ /**
+ * Gets list of ISIS interface details.
+ *
+ * @return list of ISIS interface details
+ */
+ public List<IsisInterface> isisInterfaceList() {
+ return isisInterfaceList;
+ }
+
+ /**
+ * Sets list of ISIS interface details.
+ *
+ * @param isisInterfaceList list of ISIS interface details
+ */
+ public void setIsisInterfaceList(List<IsisInterface> isisInterfaceList) {
+ this.isisInterfaceList = isisInterfaceList;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java
new file mode 100755
index 0000000..064176d
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java
@@ -0,0 +1,251 @@
+/*
+ * 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.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
+import org.jboss.netty.handler.timeout.ReadTimeoutException;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisLsdb;
+import org.onosproject.isis.controller.IsisMessage;
+import org.onosproject.isis.controller.IsisProcess;
+import org.onosproject.isis.controller.impl.lsdb.DefaultIsisLsdb;
+import org.onosproject.isis.exceptions.IsisParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * Channel handler deals with the ISIS channel connection.
+ * Also it dispatches messages to the appropriate handlers for processing.
+ */
+public class IsisChannelHandler extends IdleStateAwareChannelHandler {
+
+ private static final Logger log = LoggerFactory.getLogger(IsisChannelHandler.class);
+ private static Map<Integer, Object> isisDb = null;
+ private Channel channel;
+ private Controller controller;
+ private List<IsisProcess> processes = null;
+ private List<ScheduledExecutorService> executorList = new ArrayList<>();
+ private byte[] configPacket = null;
+ private Map<Integer, IsisInterface> isisInterfaceMap = new ConcurrentHashMap<>();
+ private IsisLsdb isisLsdb = new DefaultIsisLsdb();
+ private List<Ip4Address> interfaceIps = new ArrayList<>();
+
+ /**
+ * Creates an instance of ISIS channel handler.
+ *
+ * @param controller controller instance
+ * @param processes list of configured processes
+ */
+ public IsisChannelHandler(Controller controller, List<IsisProcess> processes) {
+ this.controller = controller;
+ this.processes = processes;
+ }
+
+ /**
+ * Initializes the interface map with interface details.
+ */
+ public void initializeInterfaceMap() {
+ for (IsisProcess process : processes) {
+ for (IsisInterface isisInterface : process.isisInterfaceList()) {
+ isisInterfaceMap.put(isisInterface.interfaceIndex(), isisInterface);
+ interfaceIps.add(isisInterface.interfaceIpAddress());
+ }
+ }
+ //Initializes the interface with all interface ip details - for ls pdu generation
+ initializeInterfaceIpList();
+ }
+
+ /**
+ * Updates the interface map with interface details.
+ *
+ * @param isisProcesses updated process instances
+ */
+ public void updateInterfaceMap(List<IsisProcess> isisProcesses) {
+ for (IsisProcess isisUpdatedProcess : isisProcesses) {
+ for (IsisInterface isisUpdatedInterface : isisUpdatedProcess.isisInterfaceList()) {
+ IsisInterface isisInterface = isisInterfaceMap.get(isisUpdatedInterface.interfaceIndex());
+ if (isisInterface == null) {
+ isisInterfaceMap.put(isisInterface.interfaceIndex(), isisInterface);
+ interfaceIps.add(isisInterface.interfaceIpAddress());
+ } else {
+ isisInterface.setReservedPacketCircuitType(isisUpdatedInterface.reservedPacketCircuitType());
+ isisInterface.setNetworkType(isisUpdatedInterface.networkType());
+ isisInterface.setHoldingTime(isisUpdatedInterface.holdingTime());
+ isisInterface.setHelloInterval(isisUpdatedInterface.helloInterval());
+ isisInterfaceMap.put(isisInterface.interfaceIndex(), isisInterface);
+ }
+ }
+ }
+ }
+
+ /**
+ * Initializes the interface with all interface ip details.
+ */
+ public void initializeInterfaceIpList() {
+ for (IsisProcess process : processes) {
+ for (IsisInterface isisInterface : process.isisInterfaceList()) {
+ ((DefaultIsisInterface) isisInterface).setAllConfiguredInterfaceIps(interfaceIps);
+ }
+ }
+ }
+
+ /**
+ * Initialize channel, start hello sender and initialize LSDB.
+ */
+ private void initialize() {
+ log.debug("IsisChannelHandler initialize..!!!");
+ if (configPacket != null) {
+ log.debug("IsisChannelHandler initialize -> sentConfig packet of length ::"
+ + configPacket.length);
+ sentConfigPacket(configPacket);
+ }
+ //start the hello timer
+ startHelloSender();
+ //Initialize Database
+ isisLsdb.initializeDb();
+ }
+
+ @Override
+ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) throws Exception {
+ log.info("ISIS channelConnected from {}", evt.getChannel().getRemoteAddress());
+ this.channel = evt.getChannel();
+ initialize();
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
+ log.debug("IsisChannelHandler::channelDisconnected...!!!");
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+ log.info("[exceptionCaught]: " + e.toString());
+ if (e.getCause() instanceof ReadTimeoutException) {
+ log.error("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress());
+ return;
+ } else if (e.getCause() instanceof ClosedChannelException) {
+ log.debug("Channel for ISIS {} already closed", e.getChannel().getRemoteAddress());
+ } else if (e.getCause() instanceof IOException) {
+ log.error("Disconnecting ISIS {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
+ e.getCause().getMessage());
+ if (log.isDebugEnabled()) {
+ log.debug("StackTrace for previous Exception: {}", e.getCause());
+ }
+ } else if (e.getCause() instanceof IsisParseException) {
+ IsisParseException errMsg = (IsisParseException) e.getCause();
+ byte errorCode = errMsg.errorCode();
+ byte errorSubCode = errMsg.errorSubCode();
+ log.error("Error while parsing message from ISIS {}, ErrorCode {}",
+ e.getChannel().getRemoteAddress(), errorCode);
+ } else if (e.getCause() instanceof RejectedExecutionException) {
+ log.warn("Could not process message: queue full");
+ } else {
+ log.error("Error while processing message from ISIS {}",
+ e.getChannel().getRemoteAddress());
+ }
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ log.debug("IsisChannelHandler::messageReceived...!!!");
+ Object message = e.getMessage();
+ if (message instanceof List) {
+ List<IsisMessage> isisMessageList = (List<IsisMessage>) message;
+ log.debug("IsisChannelHandler::List of IsisMessages Size {}", isisMessageList.size());
+ if (isisMessageList != null) {
+ for (IsisMessage isisMessage : isisMessageList) {
+ processIsisMessage(isisMessage, ctx);
+ }
+ } else {
+ log.debug("IsisChannelHandler::IsisMessages Null List...!!");
+ }
+ }
+ if (message instanceof IsisMessage) {
+ IsisMessage isisMessage = (IsisMessage) message;
+ log.debug("IsisChannelHandler::IsisMessages received...!!");
+ processIsisMessage(isisMessage, ctx);
+ }
+ }
+
+ /**
+ * 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 ctx channel handler context instance.
+ * @throws Exception might throws exception
+ */
+ public void processIsisMessage(IsisMessage isisMessage, ChannelHandlerContext ctx) throws Exception {
+ log.debug("IsisChannelHandler::processIsisMessage...!!!");
+ int interfaceIndex = isisMessage.interfaceIndex();
+ IsisInterface isisInterface = isisInterfaceMap.get(interfaceIndex);
+ isisInterface.processIsisMessage(isisMessage, isisLsdb, channel);
+ }
+
+ /**
+ * Starts the hello timer which sends hello packet every configured seconds.
+ */
+ public void startHelloSender() {
+ log.debug("IsisController::startHelloSender");
+ Set<Integer> interfaceIndexes = isisInterfaceMap.keySet();
+ for (Integer interfaceIndex : interfaceIndexes) {
+ IsisInterface isisInterface = isisInterfaceMap.get(interfaceIndex);
+ isisInterface.startHelloSender(channel);
+ }
+ }
+
+ /**
+ * Stops the hello timer.
+ */
+ public void stopHelloSender() {
+ log.debug("ISISChannelHandler::stopHelloTimer ");
+ for (ScheduledExecutorService exServiceHello : executorList) {
+ exServiceHello.shutdown();
+ }
+ }
+
+ /**
+ * Sends the interface configuration packet to server.
+ *
+ * @param configPacket interface configuration
+ */
+ public void sentConfigPacket(byte[] configPacket) {
+ if (channel != null) {
+ channel.write(configPacket);
+ log.debug("IsisChannelHandler sentConfigPacket packet sent..!!!");
+ } else {
+ log.debug("IsisChannelHandler sentConfigPacket channel not connected - re try..!!!");
+ this.configPacket = configPacket;
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisHelloPduSender.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisHelloPduSender.java
new file mode 100755
index 0000000..87338f5
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisHelloPduSender.java
@@ -0,0 +1,88 @@
+/*
+ * 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 com.google.common.primitives.Bytes;
+import org.jboss.netty.channel.Channel;
+import org.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisNetworkType;
+import org.onosproject.isis.controller.IsisRouterType;
+import org.onosproject.isis.io.util.IsisUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Representation of an ISIS hello pdu sender task.
+ */
+public class IsisHelloPduSender implements Runnable {
+ private static final Logger log = LoggerFactory.getLogger(IsisHelloPduSender.class);
+ private Channel channel = null;
+ private IsisInterface isisInterface = null;
+
+ /**
+ * Creates an instance of Hello PDU Sender task.
+ *
+ * @param channel netty channel instance
+ * @param isisInterface ISIS interface instance
+ */
+ public IsisHelloPduSender(Channel channel, IsisInterface isisInterface) {
+ this.channel = channel;
+ this.isisInterface = isisInterface;
+ }
+
+ @Override
+ public void run() {
+ if (channel != null) {
+ try {
+ byte[] helloPdu = null;
+ byte[] interfaceIndex = {(byte) isisInterface.interfaceIndex()};
+
+ if (isisInterface.networkType() == IsisNetworkType.P2P) {
+ helloPdu = IsisUtil.getP2pHelloPdu(isisInterface, true);
+ helloPdu = Bytes.concat(helloPdu, interfaceIndex);
+ channel.write(helloPdu);
+ } else if (isisInterface.networkType() == IsisNetworkType.BROADCAST) {
+ switch (IsisRouterType.get(isisInterface.reservedPacketCircuitType())) {
+ case L1:
+ helloPdu = IsisUtil.getL1HelloPdu(isisInterface, true);
+ helloPdu = Bytes.concat(helloPdu, interfaceIndex);
+ channel.write(helloPdu);
+ break;
+ case L2:
+ helloPdu = IsisUtil.getL2HelloPdu(isisInterface, true);
+ helloPdu = Bytes.concat(helloPdu, interfaceIndex);
+ channel.write(helloPdu);
+ break;
+ case L1L2:
+ helloPdu = IsisUtil.getL1HelloPdu(isisInterface, true);
+ helloPdu = Bytes.concat(helloPdu, interfaceIndex);
+ channel.write(helloPdu);
+
+ helloPdu = IsisUtil.getL2HelloPdu(isisInterface, true);
+ helloPdu = Bytes.concat(helloPdu, interfaceIndex);
+ channel.write(helloPdu);
+ break;
+ default:
+ log.debug("IsisHelloPduSender::Unknown circuit type...!!!");
+ break;
+ }
+ }
+ } catch (Exception e) {
+ log.debug("Exception @IsisHelloPduSender:: {}", e.getMessage());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageDecoder.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageDecoder.java
new file mode 100755
index 0000000..f2cbf19
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageDecoder.java
@@ -0,0 +1,94 @@
+/*
+ * 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.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+import org.onlab.packet.MacAddress;
+import org.onosproject.isis.controller.IsisMessage;
+import org.onosproject.isis.io.isispacket.IsisMessageReader;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.onosproject.isis.io.util.IsisUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Decodes an ISIS message from a Channel, for use in a netty pipeline.
+ */
+public class IsisMessageDecoder extends FrameDecoder {
+
+ private static final Logger log = LoggerFactory.getLogger(IsisMessageDecoder.class);
+
+ @Override
+ protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
+ log.debug("IsisMessageDecoder::Message received <:> length {}", buffer.readableBytes());
+ if (!channel.isConnected()) {
+ log.info("Channel is not connected.");
+ return null;
+ }
+
+ IsisMessageReader messageReader = new IsisMessageReader();
+ List<IsisMessage> isisMessageList = new LinkedList<>();
+ int dataLength = buffer.readableBytes();
+ while (buffer.readableBytes() >= IsisConstants.MINIMUM_FRAME_LEN) {
+ ChannelBuffer payload = buffer.readBytes(IsisConstants.MINIMUM_FRAME_LEN);
+ ChannelBuffer ethernetHeader = payload.readBytes(IsisUtil.ETHER_HEADER_LEN);
+ //Read the Source MAC address from ethernet header at the 6th position
+ MacAddress sourceMac = getSourceMac(ethernetHeader);
+ //Strip 17 byte ethernet header and get the ISIS data buffer
+ ChannelBuffer isisDataBuffer = payload.readBytes(payload.readableBytes());
+ int readableBytes = isisDataBuffer.readableBytes();
+ IsisMessage message = messageReader.readFromBuffer(isisDataBuffer);
+ //Last 7 bytes is metadata. ie. interface MAC address and interface index.
+ if (message != null) {
+ if (isisDataBuffer.readableBytes() >= IsisConstants.METADATA_LEN) {
+ //Sets the source MAC
+ message.setSourceMac(sourceMac);
+ isisDataBuffer.readerIndex(readableBytes - IsisConstants.METADATA_LEN);
+ log.debug("IsisMessageDecoder::Reading metadata <:> length {}", isisDataBuffer.readableBytes());
+ byte[] macBytes = new byte[IsisUtil.SIX_BYTES];
+ isisDataBuffer.readBytes(macBytes, 0, IsisUtil.SIX_BYTES);
+ MacAddress macAddress = MacAddress.valueOf(macBytes);
+ int interfaceIndex = isisDataBuffer.readByte();
+ message.setInterfaceMac(macAddress);
+ message.setInterfaceIndex(interfaceIndex);
+ }
+ isisMessageList.add(message);
+ }
+ }
+
+ return isisMessageList;
+ }
+
+ /**
+ * Gets the source MAC address from the ethernet header.
+ *
+ * @param ethHeader ethernet header bytes
+ * @return MAC address of the source router
+ */
+ private MacAddress getSourceMac(ChannelBuffer ethHeader) {
+ //Source MAC is at position 6 to 11 (6 bytes)
+ ethHeader.skipBytes(IsisUtil.SIX_BYTES);
+ MacAddress sourceMac = MacAddress.valueOf(ethHeader.readBytes(IsisUtil.SIX_BYTES).array());
+
+ return sourceMac;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageEncoder.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageEncoder.java
new file mode 100755
index 0000000..af46712
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisMessageEncoder.java
@@ -0,0 +1,42 @@
+/*
+ * 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.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Encodes an ISIS message for output into a ChannelBuffer, for use in a netty pipeline.
+ */
+public class IsisMessageEncoder extends OneToOneEncoder {
+ private static final Logger log = LoggerFactory.getLogger(IsisMessageEncoder.class);
+
+ @Override
+ protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
+
+ byte[] byteMsg = (byte[]) msg;
+ log.debug("Encoding isisMessage of length {}", byteMsg.length);
+ ChannelBuffer channelBuffer = ChannelBuffers.buffer(byteMsg.length);
+ channelBuffer.writeBytes(byteMsg);
+
+ return channelBuffer;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisPipelineFactory.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisPipelineFactory.java
new file mode 100755
index 0000000..227bb2f
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisPipelineFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+
+/**
+ * Creates a ChannelPipeline for a client-side ISIS channel.
+ */
+public class IsisPipelineFactory implements ChannelPipelineFactory {
+ private IsisChannelHandler isisChannelHandler;
+
+ /**
+ * Creates an instance of ISIS channel pipeline factory.
+ *
+ * @param isisChannelHandler ISIS channel handler instance
+ */
+ public IsisPipelineFactory(IsisChannelHandler isisChannelHandler) {
+ this.isisChannelHandler = isisChannelHandler;
+ }
+
+ @Override
+ public ChannelPipeline getPipeline() throws Exception {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("encoder", new IsisMessageDecoder());
+ pipeline.addLast("decoder", new IsisMessageEncoder());
+ pipeline.addLast("handler", isisChannelHandler);
+
+ return pipeline;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdb.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdb.java
new file mode 100755
index 0000000..33a0a17
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdb.java
@@ -0,0 +1,315 @@
+/*
+ * 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.lsdb;
+
+import org.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisLsdb;
+import org.onosproject.isis.controller.IsisLsdbAge;
+import org.onosproject.isis.controller.IsisLspBin;
+import org.onosproject.isis.controller.IsisMessage;
+import org.onosproject.isis.controller.IsisPduType;
+import org.onosproject.isis.controller.LspWrapper;
+import org.onosproject.isis.io.isispacket.pdu.LsPdu;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Representation of ISIS link state database.
+ */
+public class DefaultIsisLsdb implements IsisLsdb {
+ private static final Logger log = LoggerFactory.getLogger(DefaultIsisLsdb.class);
+ private Map<String, LspWrapper> isisL1Db = new ConcurrentHashMap<>();
+ private Map<String, LspWrapper> isisL2Db = new ConcurrentHashMap<>();
+ private IsisLsdbAge lsdbAge = null;
+ private int l1LspSeqNo = IsisConstants.STARTLSSEQUENCENUM;
+ private int l2LspSeqNo = IsisConstants.STARTLSSEQUENCENUM;
+
+ /**
+ * Creates an instance of ISIS LSDB.
+ */
+ public DefaultIsisLsdb() {
+ lsdbAge = new DefaultIsisLsdbAge();
+ }
+
+ /**
+ * Initializes the link state database.
+ */
+ public void initializeDb() {
+ lsdbAge.startDbAging();
+ }
+
+ /**
+ * Returns the LSDB LSP key.
+ *
+ * @param systemId system ID
+ * @return key
+ */
+ public String lspKey(String systemId) {
+ StringBuilder lspKey = new StringBuilder();
+ lspKey.append(systemId);
+ lspKey.append(".00");
+ lspKey.append("-");
+ lspKey.append("00");
+
+ return lspKey.toString();
+ }
+
+ /**
+ * Returns the neighbor L1 database information.
+ *
+ * @return neighbor L1 database information
+ */
+ public Map<String, LspWrapper> getL1Db() {
+ return isisL1Db;
+ }
+
+ /**
+ * Returns the neighbor L2 database information.
+ *
+ * @return neighbor L2 database information
+ */
+ public Map<String, LspWrapper> getL2Db() {
+ return isisL2Db;
+ }
+
+ /**
+ * Returns the LSDB instance.
+ *
+ * @return LSDB instance
+ */
+ public IsisLsdb isisLsdb() {
+ return this;
+ }
+
+ /**
+ * Returns all LSPs (L1 and L2).
+ *
+ * @param excludeMaxAgeLsp exclude the max age LSPs
+ * @return List of LSPs
+ */
+ public List<LspWrapper> allLspHeaders(boolean excludeMaxAgeLsp) {
+ List<LspWrapper> summaryList = new CopyOnWriteArrayList();
+ addLspToHeaderList(summaryList, excludeMaxAgeLsp, isisL1Db);
+ addLspToHeaderList(summaryList, excludeMaxAgeLsp, isisL2Db);
+
+ return summaryList;
+ }
+
+ /**
+ * Adds the LSPs to summary list.
+ *
+ * @param summaryList summary list
+ * @param excludeMaxAgeLsp exclude max age LSP
+ * @param lspMap map of LSP
+ */
+ private void addLspToHeaderList(List summaryList, boolean excludeMaxAgeLsp, Map lspMap) {
+ Iterator slotVals = lspMap.values().iterator();
+ while (slotVals.hasNext()) {
+ LspWrapper wrapper = (LspWrapper) slotVals.next();
+ if (excludeMaxAgeLsp) {
+ //if current age of lsa is max age or lsa present in Max Age bin
+ if (wrapper.remainingLifetime() != 0) {
+ addToList(wrapper, summaryList);
+ }
+ } else {
+ addToList(wrapper, summaryList);
+ }
+ }
+ }
+
+ /**
+ * Adds the LSPWrapper to summary list.
+ *
+ * @param wrapper LSP wrapper instance
+ * @param summList LSP summary list
+ */
+ private void addToList(LspWrapper wrapper, List summList) {
+ //set the current age
+ ((LsPdu) wrapper.lsPdu()).setRemainingLifeTime(wrapper.remainingLifetime());
+ summList.add(wrapper);
+ }
+
+ /**
+ * Finds the LSP from appropriate maps L1 or L2 based on type.
+ *
+ * @param pduType L1 or L2 LSP
+ * @param lspId LSP ID
+ * @return LSP wrapper object
+ */
+ public LspWrapper findLsp(IsisPduType pduType, String lspId) {
+ LspWrapper lspWrapper = null;
+
+ switch (pduType) {
+ case L1LSPDU:
+ lspWrapper = isisL1Db.get(lspId);
+ break;
+ case L2LSPDU:
+ lspWrapper = isisL2Db.get(lspId);
+ break;
+ default:
+ log.debug("Unknown LSP type..!!!");
+ break;
+ }
+
+ //set the current age
+ if (lspWrapper != null) {
+ //set the current age
+ ((DefaultLspWrapper) lspWrapper).lsPdu().setRemainingLifeTime(lspWrapper.remainingLifetime());
+ }
+
+ return lspWrapper;
+ }
+
+ /**
+ * Installs a new self-originated LSP.
+ *
+ * @return true if successfully added
+ */
+ public boolean addLsp(IsisMessage isisMessage, boolean isSelfOriginated, IsisInterface isisInterface) {
+ LsPdu lspdu = (LsPdu) isisMessage;
+ DefaultLspWrapper lspWrapper = new DefaultLspWrapper();
+ lspWrapper.setLspAgeReceived(IsisConstants.LSPMAXAGE - lspdu.remainingLifeTime());
+ lspWrapper.setRemainingLifetime(IsisConstants.LSPMAXAGE - lsdbAge.ageCounter());
+ lspWrapper.setLspType(IsisPduType.get(lspdu.pduType()));
+ lspWrapper.setLsPdu(lspdu);
+ lspWrapper.setAgeCounterWhenReceived(lsdbAge.ageCounter());
+ lspWrapper.setAgeCounterRollOverWhenAdded(lsdbAge.ageCounterRollOver());
+ lspWrapper.setSelfOriginated(isSelfOriginated);
+ lspWrapper.setIsisInterface(isisInterface);
+ lspWrapper.setLsdbAge(lsdbAge);
+ addLsp(lspWrapper, lspdu.lspId());
+
+ log.debug("Added LSp In LSDB: {}", lspWrapper);
+
+ return true;
+ }
+
+ /**
+ * Adds the LSP to L1 or L2 database.
+ *
+ * @param lspWrapper LSA wrapper instance
+ * @param key key
+ * @return True if added else false
+ */
+ private boolean addLsp(LspWrapper lspWrapper, String key) {
+ //Remove the lsa from bin if exist.
+ removeLspFromBin(lspWrapper);
+
+ switch (lspWrapper.lsPdu().isisPduType()) {
+ case L1LSPDU:
+ isisL1Db.put(key, lspWrapper);
+ break;
+ case L2LSPDU:
+ isisL2Db.put(key, lspWrapper);
+ break;
+ default:
+ log.debug("Unknown LSP type to add..!!!");
+ break;
+ }
+
+ //add it to bin
+ Integer binNumber = lsdbAge.age2Bin(IsisConstants.LSPMAXAGE - lspWrapper.remainingLifetime());
+ IsisLspBin lspBin = lsdbAge.getLspBin(binNumber);
+ if (lspBin != null) {
+ //remove from existing
+ lspWrapper.setBinNumber(binNumber);
+ lspBin.addIsisLsp(key, lspWrapper);
+ lsdbAge.addLspBin(binNumber, lspBin);
+ log.debug("Added Type {} LSP to LSDB and LSABin[{}], Remaining life time of LSA {}",
+ lspWrapper.lsPdu().isisPduType(),
+ binNumber, lspWrapper.remainingLifetime());
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes LSP from Bin.
+ *
+ * @param lsaWrapper LSP wrapper instance
+ */
+ public void removeLspFromBin(LspWrapper lsaWrapper) {
+ if (lsaWrapper != null) {
+ lsdbAge.removeLspFromBin(lsaWrapper);
+ }
+ }
+
+ /**
+ * Returns new ,latest or old according to the type of ISIS message received.
+ *
+ * @param lsp1 LSP instance
+ * @param lsp2 LSP instance
+ * @return string status
+ */
+ public String isNewerOrSameLsp(IsisMessage lsp1, IsisMessage lsp2) {
+ LsPdu receivedLsp = (LsPdu) lsp1;
+ LsPdu lspFromDb = (LsPdu) lsp2;
+ if (receivedLsp.sequenceNumber() > lspFromDb.sequenceNumber()) {
+ return "latest";
+ } else if (receivedLsp.sequenceNumber() < lspFromDb.sequenceNumber()) {
+ return "old";
+ } else if (receivedLsp.sequenceNumber() == lspFromDb.sequenceNumber()) {
+ return "same";
+ }
+
+ return "";
+ }
+
+ /**
+ * Returns the sequence number.
+ *
+ * @param lspType type of LSP
+ * @return sequence number
+ */
+ public int lsSequenceNumber(IsisPduType lspType) {
+ switch (lspType) {
+ case L1LSPDU:
+ return l1LspSeqNo++;
+ case L2LSPDU:
+ return l2LspSeqNo++;
+ default:
+ return IsisConstants.STARTLSSEQUENCENUM;
+ }
+ }
+
+ /**
+ * Deletes the given LSP.
+ *
+ * @param lspMessage LSP instance
+ */
+ public void deleteLsp(IsisMessage lspMessage) {
+ LsPdu lsp = (LsPdu) lspMessage;
+ String lspKey = lsp.lspId();
+ switch (lsp.isisPduType()) {
+ case L1LSPDU:
+ isisL1Db.remove(lspKey);
+ break;
+ case L2LSPDU:
+ isisL2Db.remove(lspKey);
+ break;
+ default:
+ log.debug("Unknown LSP type to remove..!!!");
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdbAge.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdbAge.java
new file mode 100755
index 0000000..2cf07ba
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLsdbAge.java
@@ -0,0 +1,248 @@
+/*
+ * 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.lsdb;
+
+import org.onosproject.isis.controller.IsisLsdbAge;
+import org.onosproject.isis.controller.IsisLspBin;
+import org.onosproject.isis.controller.LspWrapper;
+import org.onosproject.isis.io.isispacket.pdu.LsPdu;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Representation of ISIS link state database ageing process.
+ */
+public class DefaultIsisLsdbAge implements IsisLsdbAge {
+ private static final Logger log = LoggerFactory.getLogger(DefaultIsisLsdbAge.class);
+ protected static int ageCounter = 0;
+ private InternalAgeTimer dbAgeTimer;
+ private ScheduledExecutorService exServiceage;
+ private Integer maxBins = 1200;
+ private Map<Integer, IsisLspBin> ageBins = new ConcurrentHashMap<>(maxBins);
+ private int ageCounterRollOver = 0;
+ private IsisLspQueueConsumer queueConsumer = null;
+ private BlockingQueue<LspWrapper> lsaQueue = new ArrayBlockingQueue<>(1024);
+
+ /**
+ * Creates an instance of LSDB age.
+ */
+ public DefaultIsisLsdbAge() {
+ // create LSBin's in the HashMap.
+ for (int i = 0; i < maxBins; i++) {
+ IsisLspBin lspBin = new DefaultIsisLspBin(i);
+ ageBins.put(i, lspBin);
+ }
+ }
+
+ /**
+ * Returns age counter.
+ *
+ * @return age counter
+ */
+ public int ageCounter() {
+ return ageCounter;
+ }
+
+ /**
+ * Returns age counter roll over.
+ *
+ * @return age counter roll over
+ */
+ public int ageCounterRollOver() {
+
+ return ageCounterRollOver;
+ }
+
+ /**
+ * Adds LSP to LS bin for ageing.
+ *
+ * @param binNumber key to store in bin
+ * @param lspBin LSP bin instance
+ */
+ public void addLspBin(int binNumber, IsisLspBin lspBin) {
+ if (!ageBins.containsKey(binNumber)) {
+ ageBins.put(binNumber, lspBin);
+ }
+ }
+
+ /**
+ * Returns LSP from Bin.
+ *
+ * @param binKey key
+ * @return bin instance
+ */
+ public IsisLspBin getLspBin(int binKey) {
+
+ return ageBins.get(binKey);
+ }
+
+ /**
+ * Removes LSP from Bin.
+ *
+ * @param lspWrapper wrapper instance
+ */
+ public void removeLspFromBin(LspWrapper lspWrapper) {
+ if (ageBins.containsKey(lspWrapper.binNumber())) {
+ IsisLspBin lsaBin = ageBins.get(lspWrapper.binNumber());
+ lsaBin.removeIsisLsp(((LsPdu) lspWrapper.lsPdu()).lspId(), lspWrapper);
+ }
+ }
+
+ /**
+ * Returns the bin number.
+ *
+ * @param age Can be either age or ageCounter
+ * @return bin number.
+ */
+ public int age2Bin(int age) {
+ if (age <= ageCounter) {
+ return (ageCounter - age);
+ } else {
+ return ((IsisConstants.LSPMAXAGE - 1) + (ageCounter - age));
+ }
+ }
+
+ /**
+ * Starts the aging timer and queue consumer.
+ */
+ public void startDbAging() {
+ startDbAgeTimer();
+ queueConsumer = new IsisLspQueueConsumer(lsaQueue);
+ new Thread(queueConsumer).start();
+ }
+
+ /**
+ * Starts DB aging task.
+ */
+ private void startDbAgeTimer() {
+ dbAgeTimer = new InternalAgeTimer();
+ //from 1 sec
+ exServiceage = Executors.newSingleThreadScheduledExecutor();
+ exServiceage.scheduleAtFixedRate(dbAgeTimer, 1, 1, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Gets called every second as part of the aging process.
+ */
+ public void ageLsp() {
+ refreshLsa();
+ maxAgeLsa();
+
+ if (ageCounter == IsisConstants.LSPMAXAGE) {
+ ageCounter = 0;
+ ageCounterRollOver++;
+ } else {
+ ageCounter++;
+ }
+ }
+
+ /**
+ * If the LSP have completed the MaxAge - they are moved called stop aging.
+ */
+ public void maxAgeLsa() {
+ if (ageCounter == 0) {
+ return;
+ }
+ //Get from Age Bins
+ IsisLspBin lspBin = ageBins.get(ageCounter - 1);
+ if (lspBin == null) {
+ return;
+ }
+ Map lspBinMap = lspBin.listOfLsp();
+ for (Object key : lspBinMap.keySet()) {
+ LspWrapper lspWrapper = (LspWrapper) lspBinMap.get((String) key);
+ if (lspWrapper.currentAge() == IsisConstants.LSPMAXAGE) {
+ lspWrapper.setLspProcessing(IsisConstants.MAXAGELSP);
+ log.debug("Lsp picked for maxage removal. Age Counter: {}, AgeCounterRollover: {}, " +
+ "AgeCounterRollover WhenAddedToDb: {}, LSA Type: {}, LSA Key: {}",
+ ageCounter, ageCounterRollOver, lspWrapper.currentAge(),
+ lspWrapper.lsPdu().isisPduType(), key);
+ //add it to lspQueue for processing
+ try {
+ lsaQueue.put(lspWrapper);
+ //remove from bin
+ lspBin.removeIsisLsp((String) key, lspWrapper);
+ } catch (InterruptedException e) {
+ log.debug("Error::LSDBAge::maxAgeLsp::{}", e.getMessage());
+ }
+ }
+ }
+
+ }
+
+ /*
+ * If the LSP is in age bin of 900s- it's pushed into refresh list.
+ */
+ public void refreshLsa() {
+ int binNumber;
+ if (ageCounter < IsisConstants.LSPREFRESH) {
+ binNumber = ageCounter + IsisConstants.LSPREFRESH;
+ } else {
+ binNumber = ageCounter - IsisConstants.LSPREFRESH;
+ }
+ if (binNumber > IsisConstants.LSPMAXAGE) {
+ binNumber = binNumber - IsisConstants.LSPMAXAGE;
+ }
+ IsisLspBin lspBin = ageBins.get(binNumber);
+ if (lspBin == null) {
+ return;
+ }
+ Map lspBinMap = lspBin.listOfLsp();
+ for (Object key : lspBinMap.keySet()) {
+ LspWrapper lsp = (LspWrapper) lspBinMap.get((String) key);
+ try {
+ if (lsp.isSelfOriginated()) {
+ log.debug("Lsp picked for refreshLsp. binNumber: {}, LSA Type: {}, LSA Key: {}",
+ binNumber, lsp.lspType(), key);
+ lsp.setLspProcessing(IsisConstants.REFRESHLSP);
+ lsaQueue.put(lsp);
+ //remove from bin
+ lspBin.removeIsisLsp((String) key, lsp);
+ }
+ } catch (InterruptedException e) {
+ log.debug("Error::LSDBAge::refreshLsp::{}", e.getMessage());
+ }
+ }
+ }
+
+
+ /**
+ * Runnable task which runs every second and calls aging process.
+ */
+ private class InternalAgeTimer implements Runnable {
+
+ /**
+ * Creates an instance of age timer task.
+ */
+ InternalAgeTimer() {
+ log.debug("Starts::IsisLsdbAge::AgeTimer...!!! ");
+ }
+
+ @Override
+ public void run() {
+ ageLsp();
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLspBin.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLspBin.java
new file mode 100755
index 0000000..2505c90
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultIsisLspBin.java
@@ -0,0 +1,104 @@
+/*
+ * 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.lsdb;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.isis.controller.IsisLspBin;
+import org.onosproject.isis.controller.LspWrapper;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Representation of LSP bin, where an LSP is stored for Aging.
+ * A bin is identified by a bin number and can have one or more LSPs
+ * store in a particular bin location
+ */
+public class DefaultIsisLspBin implements IsisLspBin {
+ private int binNumber;
+ private Map<String, LspWrapper> listOfLsp = new ConcurrentHashMap<>();
+
+ /**
+ * Creates ISIS LSP bin instance.
+ *
+ * @param binNumber bin number
+ */
+ public DefaultIsisLspBin(int binNumber) {
+ this.binNumber = binNumber;
+ }
+
+ /**
+ * Adds the LSP to wrapper.
+ *
+ * @param lspKey key to add the LSP
+ * @param lspWrapper LSP wrapper instance
+ */
+ public void addIsisLsp(String lspKey, LspWrapper lspWrapper) {
+ if (!listOfLsp.containsKey(lspKey)) {
+ listOfLsp.put(lspKey, lspWrapper);
+ lspWrapper.setBinNumber(this.binNumber);
+ }
+ }
+
+ /**
+ * Returns the LSP wrapper.
+ *
+ * @param lspKey LSP key
+ * @return LSP wrapper
+ */
+ public LspWrapper isisLsp(String lspKey) {
+ return listOfLsp.get(lspKey);
+ }
+
+ /**
+ * Removes ISIS LSP from database.
+ *
+ * @param lspKey LSP key
+ * @param lspWrapper LSP wrapper instance
+ */
+ public void removeIsisLsp(String lspKey, LspWrapper lspWrapper) {
+ if (listOfLsp.containsKey(lspKey)) {
+ listOfLsp.remove(lspKey);
+ }
+ }
+
+ /**
+ * Returns all LSP wrappers.
+ *
+ * @return all LSP wrappers
+ */
+ public Map<String, LspWrapper> listOfLsp() {
+ return listOfLsp;
+ }
+
+ /**
+ * Returns the bin number.
+ *
+ * @return the bin number
+ */
+ public int binNumber() {
+ return binNumber;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .omitNullValues()
+ .add("binNumber", binNumber)
+ .add("listOfLsp", listOfLsp)
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultLspWrapper.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultLspWrapper.java
new file mode 100755
index 0000000..b89e88f
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/DefaultLspWrapper.java
@@ -0,0 +1,267 @@
+/*
+ * 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.lsdb;
+
+import org.onosproject.isis.controller.IsisInterface;
+import org.onosproject.isis.controller.IsisLsdbAge;
+import org.onosproject.isis.controller.IsisPduType;
+import org.onosproject.isis.controller.LspWrapper;
+import org.onosproject.isis.io.isispacket.pdu.LsPdu;
+import org.onosproject.isis.io.util.IsisConstants;
+
+/**
+ * Representation of LSP wrapper where the LSPs are stored with metadata.
+ */
+public class DefaultLspWrapper implements LspWrapper {
+ private int binNumber = -1;
+ private boolean selfOriginated = false;
+ private IsisPduType lspType;
+ private int lspAgeReceived;
+ private int ageCounterWhenReceived;
+ private LsPdu lsPdu;
+ private IsisLsdbAge lsdbAge;
+ private int ageCounterRollOverWhenAdded;
+ private int remainingLifetime;
+ private IsisInterface isisInterface;
+ private String lspProcessing;
+
+ /**
+ * Returns "refreshLsp" or "maxageLsp" based on LSP to process.
+ *
+ * @return LSP processing string
+ */
+ public String lspProcessing() {
+ return lspProcessing;
+ }
+
+ /**
+ * Sets LSP processing "refreshLsp" or "maxageLsp" based on LSP to process.
+ *
+ * @param lspProcessing "refreshLsp" or "maxageLsp" based on LSP to process
+ */
+ public void setLspProcessing(String lspProcessing) {
+ this.lspProcessing = lspProcessing;
+ }
+
+ /**
+ * Returns LSP age received.
+ *
+ * @return LSP age received
+ */
+ public int lspAgeReceived() {
+ return lspAgeReceived;
+ }
+
+ /**
+ * Sets LSP age received.
+ *
+ * @param lspAgeReceived LSP age received.
+ */
+ public void setLspAgeReceived(int lspAgeReceived) {
+ this.lspAgeReceived = lspAgeReceived;
+ }
+
+ /**
+ * Returns ISIS interface instance.
+ *
+ * @return ISIS interface instance
+ */
+ public IsisInterface isisInterface() {
+ return isisInterface;
+ }
+
+ /**
+ * Sets ISIS interface.
+ *
+ * @param isisInterface ISIS interface instance
+ */
+ public void setIsisInterface(IsisInterface isisInterface) {
+ this.isisInterface = isisInterface;
+ }
+
+ /**
+ * Returns age counter when received.
+ *
+ * @return age counter when received
+ */
+ public int ageCounterWhenReceived() {
+
+ return ageCounterWhenReceived;
+ }
+
+ /**
+ * Sets age counter when received.
+ *
+ * @param ageCounterWhenReceived age counter when received
+ */
+ public void setAgeCounterWhenReceived(int ageCounterWhenReceived) {
+ this.ageCounterWhenReceived = ageCounterWhenReceived;
+ }
+
+ /**
+ * Returns age counter roll over.
+ *
+ * @return age counter roll over
+ */
+ public int ageCounterRollOverWhenAdded() {
+ return ageCounterRollOverWhenAdded;
+ }
+
+ /**
+ * Sets age counter roll over when added.
+ *
+ * @param ageCounterRollOverWhenAdded age counter roll over when added
+ */
+ public void setAgeCounterRollOverWhenAdded(int ageCounterRollOverWhenAdded) {
+ this.ageCounterRollOverWhenAdded = ageCounterRollOverWhenAdded;
+ }
+
+ /**
+ * Returns bin number.
+ *
+ * @return bin number
+ */
+ public int binNumber() {
+ return binNumber;
+ }
+
+ /**
+ * Sets bin number.
+ *
+ * @param binNumber bin number
+ */
+ public void setBinNumber(int binNumber) {
+ this.binNumber = binNumber;
+ }
+
+ /**
+ * Returns true if self originated.
+ *
+ * @return true if self originated.
+ */
+ public boolean isSelfOriginated() {
+ return selfOriginated;
+ }
+
+ /**
+ * Sets true if self originated.
+ *
+ * @param selfOriginated true if self originated else false
+ */
+ public void setSelfOriginated(boolean selfOriginated) {
+ this.selfOriginated = selfOriginated;
+ }
+
+ /**
+ * Returns ISIS PDU type.
+ *
+ * @return ISIS PDU type
+ */
+ public IsisPduType lspType() {
+ return lspType;
+ }
+
+ /**
+ * Sets ISIS PDU type.
+ *
+ * @param lspType ISIS PDU type
+ */
+ public void setLspType(IsisPduType lspType) {
+ this.lspType = lspType;
+ }
+
+ /**
+ * Returns LSPDU which the wrapper contains.
+ *
+ * @return LSPDU which the wrapper contains
+ */
+ public LsPdu lsPdu() {
+ return lsPdu;
+ }
+
+ /**
+ * Sets LSPDU which the wrapper contains.
+ *
+ * @param lsPdu LSPDU which the wrapper contains
+ */
+ public void setLsPdu(LsPdu lsPdu) {
+ this.lsPdu = lsPdu;
+ }
+
+ /**
+ * Returns ISIS LSDB age.
+ *
+ * @return ISIS LSDB age
+ */
+ public IsisLsdbAge lsdbAge() {
+ return lsdbAge;
+ }
+
+ /**
+ * Sets LSDB age.
+ *
+ * @param lsdbAge LSDB age
+ */
+ public void setLsdbAge(IsisLsdbAge lsdbAge) {
+ this.lsdbAge = lsdbAge;
+ }
+
+ /**
+ * Returns the current LSP Age.
+ *
+ * @return LSP age
+ */
+ public int currentAge() {
+
+ int currentAge = 0;
+ //ls age received
+ if (lsdbAge.ageCounter() >= ageCounterWhenReceived) {
+ currentAge = lspAgeReceived + (lsdbAge.ageCounter() - ageCounterWhenReceived);
+ } else {
+ currentAge = lspAgeReceived + ((IsisConstants.LSPMAXAGE + lsdbAge.ageCounter())
+ - ageCounterWhenReceived);
+ }
+
+ if (currentAge >= IsisConstants.LSPMAXAGE) {
+ return IsisConstants.LSPMAXAGE;
+ } else if ((currentAge == lspAgeReceived) && ageCounterRollOverWhenAdded
+ != lsdbAge.ageCounterRollOver()) {
+ return IsisConstants.LSPMAXAGE;
+ }
+
+ return currentAge;
+ }
+
+ /**
+ * Returns remaining time.
+ *
+ * @return remaining time
+ */
+ public int remainingLifetime() {
+ //Calculate the remaining lifetime
+ remainingLifetime = IsisConstants.LSPMAXAGE - lsdbAge.ageCounter();
+ return remainingLifetime;
+ }
+
+ /**
+ * Sets remaining life time.
+ *
+ * @param remainingLifetime LSPs remaining life time
+ */
+ public void setRemainingLifetime(int remainingLifetime) {
+ this.remainingLifetime = remainingLifetime;
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/IsisLspQueueConsumer.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/IsisLspQueueConsumer.java
new file mode 100755
index 0000000..9007093
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/IsisLspQueueConsumer.java
@@ -0,0 +1,128 @@
+/*
+ * 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.lsdb;
+
+import org.jboss.netty.channel.Channel;
+import org.onosproject.isis.controller.IsisLsdb;
+import org.onosproject.isis.controller.IsisPduType;
+import org.onosproject.isis.controller.LspWrapper;
+import org.onosproject.isis.controller.impl.DefaultIsisInterface;
+import org.onosproject.isis.io.isispacket.pdu.LsPdu;
+import org.onosproject.isis.io.util.IsisConstants;
+import org.onosproject.isis.io.util.IsisUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * Representation of LSP queue consumer.
+ */
+public class IsisLspQueueConsumer implements Runnable {
+ private static final Logger log = LoggerFactory.getLogger(IsisLspQueueConsumer.class);
+ private BlockingQueue queue = null;
+
+ /**
+ * Creates an instance of LSP queue consumer.
+ *
+ * @param queue queue instance
+ */
+ public IsisLspQueueConsumer(BlockingQueue queue) {
+ this.queue = queue;
+ }
+
+ /**
+ * Gets the LSP wrapper instance from queue and process it.
+ */
+ @Override
+ public void run() {
+ log.debug("LSPQueueConsumer:run...!!!");
+ try {
+ while (true) {
+ if (!queue.isEmpty()) {
+ LspWrapper wrapper = (LspWrapper) queue.take();
+ String lspProcessing = wrapper.lspProcessing();
+ switch (lspProcessing) {
+ case IsisConstants.REFRESHLSP:
+ log.debug("LSPQueueConsumer: Message - " + IsisConstants.REFRESHLSP +
+ " consumed.");
+ processRefreshLsp(wrapper);
+ break;
+ case IsisConstants.MAXAGELSP:
+ log.debug("LSPQueueConsumer: Message - " + IsisConstants.MAXAGELSP +
+ " consumed.");
+ processMaxAgeLsa(wrapper);
+ break;
+ default:
+ log.debug("Unknown command to process the LSP in queue ...!!!");
+ break;
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ log.debug("Error::LSPQueueConsumer::{}", e.getMessage());
+ }
+ }
+
+ /**
+ * Process refresh LSP.
+ *
+ * @param wrapper LSP wrapper instance
+ */
+ private void processRefreshLsp(LspWrapper wrapper) throws Exception {
+ if (wrapper.isSelfOriginated()) { //self originated
+ DefaultIsisInterface isisInterface = (DefaultIsisInterface) wrapper.isisInterface();
+ Channel channel = isisInterface.channel();
+ if (channel != null && channel.isConnected()) {
+ LsPdu lsPdu = (LsPdu) wrapper.lsPdu();
+ lsPdu.setSequenceNumber(isisInterface.isisLsdb().lsSequenceNumber(
+ IsisPduType.get(lsPdu.pduType())));
+ lsPdu.setRemainingLifeTime(IsisConstants.LSPMAXAGE);
+ byte[] lspBytes = lsPdu.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, isisInterface.interfaceIndex()));
+
+ log.debug("LSPQueueConsumer: processRefreshLsp - Flooded SelfOriginated LSP {}",
+ wrapper.lsPdu());
+ }
+
+ }
+ }
+
+ /**
+ * Process max age LSP.
+ *
+ * @param wrapper LSP wrapper instance
+ */
+ private void processMaxAgeLsa(LspWrapper wrapper) {
+ //set the destination
+ DefaultIsisInterface isisInterface = (DefaultIsisInterface) wrapper.isisInterface();
+ if (isisInterface != null) {
+ //delete from db
+ LsPdu lsPdu = (LsPdu) wrapper.lsPdu();
+ IsisLsdb isisDb = isisInterface.isisLsdb();
+ isisDb.deleteLsp(lsPdu);
+ log.debug("LSPQueueConsumer: processMaxAgeLsp - Removed-Max Age LSP {}",
+ wrapper.lsPdu());
+ }
+ }
+}
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/package-info.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/package-info.java
new file mode 100755
index 0000000..cbab4b4
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/lsdb/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of the ISIS controller LSDB and related functionality.
+ */
+package org.onosproject.isis.controller.impl.lsdb;
\ No newline at end of file
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/package-info.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/package-info.java
new file mode 100755
index 0000000..99f39be
--- /dev/null
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of the ISIS controller.
+ */
+package org.onosproject.isis.controller.impl;
\ No newline at end of file