Java tutorial
/** Copyright (C) 2015 Cristian Alfonso Prieto Snchez This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have getTransmitErrorCountd a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ugr.cristian.serverVideoApp; /** *@author Cristian Alfonso Prieto Snchez */ import java.lang.System; import java.util.concurrent.Semaphore; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.Map; import java.util.HashMap; import java.util.Set; import java.util.HashSet; import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.Controller; import org.opendaylight.controller.sal.action.Output; import org.opendaylight.controller.sal.action.SetDlDst; import org.opendaylight.controller.sal.action.SetDlSrc; import org.opendaylight.controller.sal.action.SetNwDst; import org.opendaylight.controller.sal.action.SetNwSrc; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Bandwidth; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.Edge; import org.opendaylight.controller.sal.core.Host; import org.opendaylight.controller.sal.core.Latency; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.Path; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.packet.BitBufferHelper; import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.IDataPacketService; import org.opendaylight.controller.sal.packet.IListenDataPacket; import org.opendaylight.controller.sal.packet.IPv4; import org.opendaylight.controller.sal.packet.ICMP; import org.opendaylight.controller.sal.packet.TCP; import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.controller.sal.packet.PacketResult; import org.opendaylight.controller.sal.packet.RawPacket; import org.opendaylight.controller.sal.reader.FlowOnNode; import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.topologymanager.ITopologyManager; import org.opendaylight.controller.statisticsmanager.IStatisticsManager; import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.SparseMultigraph; import edu.uci.ics.jung.graph.util.EdgeType; import org.apache.commons.collections15.Transformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PacketHandler implements IListenDataPacket { private static final Logger log = LoggerFactory.getLogger(PacketHandler.class); private IDataPacketService dataPacketService; private ISwitchManager switchManager; private IFlowProgrammerService flowProgrammerService; private IStatisticsManager statisticsManager; private ITopologyManager topologyManager; private ConcurrentMap<Map<Node, InetAddress>, NodeConnector> tableIP = new ConcurrentHashMap<Map<Node, InetAddress>, NodeConnector>(); private Map<Node, Set<Edge>> nodeEdges = new HashMap<Node, Set<Edge>>(); private Edge edgeMatrix[][]; private Long latencyMatrix[][]; private Long minLatency; private Long mediumLatencyMatrix[][]; private Long minMediumLatency; private Map<Edge, Set<Packet>> edgePackets = new HashMap<Edge, Set<Packet>>(); private ConcurrentMap<Map<Edge, Packet>, Long> packetTime = new ConcurrentHashMap<Map<Edge, Packet>, Long>(); private ConcurrentMap<Edge, Map<String, ArrayList>> edgeStatistics = new ConcurrentHashMap<Edge, Map<String, ArrayList>>(); private Map<String, Long> maxStatistics = new HashMap<String, Long>(); private Map<Edge, Long> previousSentBytes = new HashMap<Edge, Long>(); private Map<Edge, Long> edgeBandWith = new HashMap<Edge, Long>(); private Long minBandWith = 0L; private Map<Edge, Long> edgeMapTime = new HashMap<Edge, Long>(); private Graph<Node, Edge> g = new SparseMultigraph(); private DijkstraShortestPath<Node, Edge> rtpShortestPath; private Map<Edge, ArrayList> edgeMediumMapTime = new HashMap<Edge, ArrayList>(); private short idleTimeOut = 10; private short hardTimeOut = 180; private short hardRTPTimeOut = 1200; private Map<Node, Set<Packet>> receivedPackets = new HashMap<Node, Set<Packet>>(); private ICMPRouting icmpRouting = null; private RTPRouting rtpRouting = null; private AudioRouting audioRouting = null; private TCPRouting tcpRouting = null; /*********Statistics Constants**********/ private final String transmitBytes = "Transmits Bytes"; private final String receiveBytes = "Receive Bytes"; private final String transmitDropBytes = "Transmit Drop Bytes"; private final String receiveDropBytes = "Receive Drop Bytes"; private final String transmitErrorBytes = "Transmit Error Bytes"; private final String receiveErrorBytes = "Receive Error Bytes"; private final String transmitPackets = "Transmits Packets"; private final String receivePackets = "Receive Packets"; private final String[] statisticsName = { transmitBytes, receiveBytes, transmitDropBytes, receiveDropBytes, transmitErrorBytes, receiveErrorBytes, transmitPackets, receivePackets }; /***************************************/ /*************************************/ private int flood = 0; private int MAXFLOODPACKET = 30; /*************************************/ private final Long UPDATETIME = 100L; //The time Interval to check the topology in milliseconds. private final Long LEARNTIME = 10000L; private Long t1 = System.currentTimeMillis(); private Long t2 = 0L; private Long t3 = System.currentTimeMillis(); private Long t4 = 0L; private Long statisticsT1 = 0L; private Long statisticsT2 = 0L; /*************************************/ private boolean force = true; /*************************************/ //Semaphores to prevent conflicts between differents instancies of receiveDataPacket static final Semaphore semaphore = new Semaphore(1); static final Semaphore delFlowSemaphore = new Semaphore(1); static final Semaphore timeSemaphore = new Semaphore(1); static final Semaphore icmpSemaphore = new Semaphore(1); static final Semaphore rtpSemaphore = new Semaphore(1); static final Semaphore statisticSemaphore = new Semaphore(1); static final Semaphore audioSemaphore = new Semaphore(1); static final Semaphore tcpSemaphore = new Semaphore(1); /************************************/ /***********************************/ static final Integer CLEANMETHOD = 2; //The options are COMPLETE(1) (remove all the flows), MINIMUN(2) (remove only the affected flows) private boolean first = true; /*********************************/ static private InetAddress intToInetAddress(int i) { byte b[] = new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff), (byte) (i & 0xff) }; InetAddress addr; try { addr = InetAddress.getByAddress(b); } catch (UnknownHostException e) { return null; } return addr; } /** * Sets a reference to the requested DataPacketService */ void setDataPacketService(IDataPacketService s) { log.trace("Set DataPacketService."); dataPacketService = s; } /** * Unsets DataPacketService */ void unsetDataPacketService(IDataPacketService s) { log.trace("Removed DataPacketService."); if (dataPacketService == s) { dataPacketService = null; } } /** * Sets a reference to the requested SwitchManagerService */ void setSwitchManagerService(ISwitchManager s) { log.trace("Set SwitchManagerService."); switchManager = s; } /** * Unsets SwitchManagerService */ void unsetSwitchManagerService(ISwitchManager s) { log.trace("Removed SwitchManagerService."); if (switchManager == s) { switchManager = null; } } /** * Sets a reference to the requested FlowProgrammerService */ void setFlowProgrammerService(IFlowProgrammerService s) { log.trace("Set FlowProgrammerService."); flowProgrammerService = s; } /** * Unsets FlowProgrammerService */ void unsetFlowProgrammerService(IFlowProgrammerService s) { log.trace("Removed FlowProgrammerService."); if (flowProgrammerService == s) { flowProgrammerService = null; } } /** * Sets a reference to the requested StatisticsService */ void setStatisticsManagerService(IStatisticsManager s) { log.trace("Set StatisticsManagerService."); statisticsManager = s; } /** * Unset StatisticsManager */ void unsetStatisticsManagerService(IStatisticsManager s) { log.trace("Unset StatisticsManagerService."); if (statisticsManager == s) { statisticsManager = null; } } /** * Sets a reference to the requested TopologyManager */ void setTopologyManagerService(ITopologyManager s) { log.trace("Set TopologyManagerService."); topologyManager = s; } /** * Unset TopologyManager */ void unsetTopologyManagerService(ITopologyManager s) { log.trace("Unset TopologyManagerService."); if (topologyManager == s) { topologyManager = null; } } @Override public PacketResult receiveDataPacket(RawPacket inPkt) { //Once a packet come the Topology has to be updated timeSemaphore.tryAcquire(); t2 = System.currentTimeMillis(); if ((t2 - t1) > UPDATETIME) { updateTopology(); t1 = System.currentTimeMillis(); } timeSemaphore.release(); //First I get the incoming Connector where the packet came. NodeConnector ingressConnector = inPkt.getIncomingNodeConnector(); Packet pkt = dataPacketService.decodeDataPacket(inPkt); log.trace("The packet came from " + ingressConnector + " NodeConnector"); //Now we obtain the node where we received the packet Node node = ingressConnector.getNode(); log.trace("The packet came from " + node + " Node"); if (!hasHostConnected(ingressConnector)) { Edge upEdge = getUpEdge(node, ingressConnector); if (upEdge != null) { calculateLatency(upEdge, pkt); } } if (pkt instanceof Ethernet) { //Pass the Ethernet Packet Ethernet ethFrame = (Ethernet) pkt; byte[] srcMAC_B = (ethFrame).getSourceMACAddress(); long srcMAC = BitBufferHelper.toNumber(srcMAC_B); byte[] dstMAC_B = (ethFrame).getDestinationMACAddress(); long dstMAC = BitBufferHelper.toNumber(dstMAC_B); Object l3Pkt = ethFrame.getPayload(); if (l3Pkt instanceof IPv4) { IPv4 ipv4Pkt = (IPv4) l3Pkt; InetAddress srcAddr = intToInetAddress(ipv4Pkt.getSourceAddress()); InetAddress dstAddr = intToInetAddress(ipv4Pkt.getDestinationAddress()); Object l4Datagram = ipv4Pkt.getPayload(); if (l4Datagram instanceof UDP) { UDP udpDatagram = (UDP) l4Datagram; int clientPort = udpDatagram.getSourcePort(); int dstPort = udpDatagram.getDestinationPort(); byte[] udpRawPayload = udpDatagram.getRawPayload(); if (this.rtpRouting.detectRTPPacket(udpRawPayload, dstPort)) { return handleRTPPacket(inPkt, srcAddr, srcMAC_B, ingressConnector, node, dstAddr, dstMAC_B, dstPort); } else if (this.audioRouting.detectAudioPacket(udpRawPayload, dstPort)) { return handleAudioPacket(inPkt, srcAddr, srcMAC_B, ingressConnector, node, dstAddr, dstMAC_B, dstPort); } } else if (l4Datagram instanceof TCP) { TCP tcpDatagram = (TCP) l4Datagram; int clientPort = tcpDatagram.getSourcePort(); int dstPort = tcpDatagram.getDestinationPort(); return handleTCPPacket(inPkt, srcAddr, srcMAC_B, ingressConnector, node, dstAddr, dstMAC_B, dstPort); } else if (l4Datagram instanceof ICMP) { return handleICMPPacket(inPkt, srcAddr, srcMAC_B, ingressConnector, node, dstAddr, dstMAC_B); } } } return PacketResult.IGNORED; } /** * Function called by the dependency manager when all the required * dependencies are satisfied * */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void init() { log.debug("Routing init() is called"); this.nodeEdges = new HashMap<Node, Set<Edge>>(); this.latencyMatrix = null; first = true; updateTopology(); } /** * Function called by the dependency manager when at least one dependency * become unsatisfied or when the component is shutting down because for * example bundle is being stopped. * */ void destroy() { log.debug("Routing destroy() is called"); } /** *Function which build the edgeMatrix *@param edges the topologyMap */ private void buildEdgeMatrix(Map<Node, Set<Edge>> edges) { this.edgeMatrix = null; this.edgeMatrix = new Edge[edges.size()][edges.size()]; Set<Node> nodes = edges.keySet(); for (Iterator<Node> it = nodes.iterator(); it.hasNext();) { Node nodeTemp = it.next(); Set<Edge> nodeEdges = edges.get(nodeTemp); for (Iterator<Edge> it2 = nodeEdges.iterator(); it2.hasNext();) { Edge edgeTemp = it2.next(); putEdge(edgeTemp); } } } /** *This function is called when a Packet come and is necessary to calculate the latency *@param edge The associate edge *@param packet The packet which came just now */ private void calculateLatency(Edge edge, Packet packet) { Set<Packet> temp = this.edgePackets.get(edge); if (checkSetPacket(packet, temp)) { temp.remove(packet); this.edgePackets.remove(edge); this.edgePackets.put(edge, temp); Long t2 = System.nanoTime(); Long t1 = returnPacketTime(edge, packet); if (t1 != null) { Long t = t2 - t1; updateLatencyMatrix(edge, t); if (minLatency == null) { minLatency = t; } else if (minLatency > t) { minLatency = t; } } } } /** *Function that is called when is necessary check if a IPAddress are in memory or not *@param node The node where we have to check *@param addr The IPAddress which is necessary to check *@return The boolean which shows if the Address are or not. */ private boolean checkAddress(Node node, InetAddress addr) { Map<Node, InetAddress> temp = new HashMap<Node, InetAddress>(); temp.put(node, addr); return this.tableIP.containsKey(temp); } /** *This function is called when is necessary to check if the latencyMatrix is complete or not *@return result The boolean which indics if the matrix are complete or not */ private boolean checkLatencyMatrix() { boolean result = true; if (this.edgeMatrix == null || this.latencyMatrix == null) { return false; } for (int i = 0; i < this.edgeMatrix.length; i++) { for (int j = 0; j < this.edgeMatrix[i].length; j++) { if (edgeMatrix[i][j] != null) { if (latencyMatrix[i][j] == null) { return false; } } } } return true; } /** *This function check is a Packet is contained in a Set<Packet> *@param packet The packet *@param packets The set of packets *@return true if is contained or farse is not */ private boolean checkSetPacket(Packet packet, Set<Packet> packets) { for (Iterator<Packet> it = packets.iterator(); it.hasNext();) { Packet temp = it.next(); if (temp.equals(packet)) { return true; } } return false; } /** *This function compare the actual bandWith with the max *@param bandWith The actual BW */ private void compareminBandWith(Long bandWith) { if (bandWith < minBandWith) { minBandWith = bandWith; } } /**Function that is called when is necessary to compare the statistics *@param m1 The HeadNodeConnector Statistic *@param m2 The tailNodeConnector Statistic *@param compare The string which identify the statistic */ private void compareStatistic(Long m1, Long m2, String compare) { Long temp = this.maxStatistics.get(compare); if (m1 > m2) { if (temp == null) { temp = m1; this.maxStatistics.put(compare, temp); } else if (m1 > temp) { temp = m1; this.maxStatistics.remove(compare); this.maxStatistics.put(compare, temp); } } else { if (temp == null) { temp = m2; this.maxStatistics.put(compare, temp); } else if (m2 > temp) { temp = m2; this.maxStatistics.remove(compare); this.maxStatistics.put(compare, temp); } } } /** *This function is called when is required to build a topology Graph */ private void createTopologyGraph() { g = new SparseMultigraph(); for (int i = 0; i < edgeMatrix.length; i++) { for (int j = 0; j < edgeMatrix[i].length; j++) { if (edgeMatrix[i][j] != null) { g.addEdge(edgeMatrix[i][j], edgeMatrix[i][j].getTailNodeConnector().getNode(), edgeMatrix[i][j].getHeadNodeConnector().getNode()); } } } } /** *Function that is called when a edge is down *@param edge The edge which is down. *@param node The node where the edge is detected */ private boolean delFlow(Edge edge, Node node) { NodeConnector tempConnector = edge.getTailNodeConnector(); Node tempNode = tempConnector.getNode(); boolean result = false; List<FlowOnNode> flowsOnNode = new ArrayList(); if (tempNode.equals(node)) { try { flowsOnNode = statisticsManager.getFlows(tempNode); } catch (RuntimeException bad) { log.trace("No flows get, time to try in noCache flows"); try { flowsOnNode = statisticsManager.getFlowsNoCache(tempNode); } catch (RuntimeException veryBad) { log.trace("Impossible to obtain the flows"); } } for (int i = 0; i < flowsOnNode.size(); i++) { FlowOnNode tempFlowOnNode = flowsOnNode.get(i); Flow tempFlow = tempFlowOnNode.getFlow(); if (tempFlow != null) { List<Action> oldActions = tempFlow.getActions(); if (oldActions != null) { List<Action> tempActions = new ArrayList<Action>(); tempActions.add(new Output(tempConnector)); if (tempActions.equals(oldActions)) { log.trace("Deleting flow with outputAction " + tempConnector + " in the node " + node); semaphore.tryAcquire(); try { flowProgrammerService.removeFlow(tempNode, tempFlow); } catch (RuntimeException e8) { log.trace("Error removing flow"); } log.trace("success removing flow"); semaphore.release(); } } } } } return result; } /** *This function return the NodeConnector where a Host is attached *@param srcIP The inetAddress *@return NodeConnector The NodeConnector where the InetAddress is attached */ private NodeConnector findHost(InetAddress srcIP) { Set<NodeConnector> connectors = this.topologyManager.getNodeConnectorWithHost(); for (Iterator<NodeConnector> it = connectors.iterator(); it.hasNext();) { NodeConnector temp = it.next(); List<Host> hosts = this.topologyManager.getHostsAttachedToNodeConnector(temp); for (Iterator<Host> ith = hosts.iterator(); ith.hasNext();) { Host temp2 = ith.next(); if (temp2.getNetworkAddress().equals(srcIP)) { return temp; } } } return null; } /** *The function is a modification of an another function. The original *is property of SDNHUB.org and it's used under a GPLv3 License. All the credits for SDNHUB.org *The original code can be find in *https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial/blob/master/adsal_L2_forwarding/src/main/java/org/opendaylight/tutorial/tutorial_L2_forwarding/internal/TutorialL2Forwarding.java *Function that is called when is necessary flood a determinate packet for all the nodeConnector in a node *@param inPkt pakect that we have to flood *@param node the node which solicite the listenDataPacketService *@param ingressConnector the "port" where the Packet came */ private void floodPacket(RawPacket inPkt, Node node, NodeConnector ingressConnector) { Set<NodeConnector> nodeConnectors = this.switchManager.getUpNodeConnectors(node); Packet pkt = dataPacketService.decodeDataPacket(inPkt); for (NodeConnector p : nodeConnectors) { if (!p.equals(ingressConnector)) { try { RawPacket destPkt = new RawPacket(inPkt); if (!hasHostConnected(p)) { Edge downEdge = getDownEdge(node, p); if (downEdge != null) { putPacket(downEdge, pkt); } } destPkt.setOutgoingNodeConnector(p); this.dataPacketService.transmitDataPacket(destPkt); } catch (ConstructionException e2) { continue; } } } } /** *Function that is called when is necessary to obtain a Edge through a NodeConnector *We suppose that each NodeConnector has only one Edge and the nodeConnector is the head *@param node The actual node *@param node The required node *@param InetAddres The IP required *@return NodeConnector The Connector for this association. */ private NodeConnector getIPNodeConnector(Node node, InetAddress addr) { Map<Node, InetAddress> temp = new HashMap<Node, InetAddress>(); temp.put(node, addr); return this.tableIP.get(temp); } /** *Function that is called when is necessary to obtain a Edge through a NodeConnector *We suppose that each NodeConnector has only one Edge and the NodeConnector is the Head *@param node The actual node *@param connector The NodeConnector which identify the Edge *@return The Edge corresponding the nodeConnector */ private Edge getDownEdge(Node node, NodeConnector connector) { Set<Edge> edges = this.nodeEdges.get(node); for (Iterator<Edge> it = edges.iterator(); it.hasNext();) { Edge temp = it.next(); if (temp.getHeadNodeConnector().equals(connector)) { log.trace("Found the DOWN edge corresponding the connector " + connector + " " + temp); return temp; } } return null; } /** *This method provide the possibility to get a index for a nodeConnector *@param nodeConnector The nodeConnector. */ private int getNodeConnectorIndex(NodeConnector nodeConnector) { int index; Node node = nodeConnector.getNode(); index = Integer.parseInt(node.getID().toString()); return index - 1; } /** *Function that is called when is necessary to obtain a Edge through a NodeConnector *We suppose that each NodeConnector has only one Edge and the NodeConnector is the Tail *@param node The actual node *@param connector The NodeConnector which identify the Edge *@return The Edge corresponding the nodeConnector */ private Edge getUpEdge(Node node, NodeConnector connector) { Set<Edge> edges = this.nodeEdges.get(node); for (Iterator<Edge> it = edges.iterator(); it.hasNext();) { Edge temp = it.next(); if (temp.getTailNodeConnector().equals(connector)) { log.trace("Found the UP edge corresponding the connector " + connector + " " + temp); return temp; } } return null; } /** *This function return true if the NodeConnector has some Host attached *@param connector The NodeConnector *@return true if yes or false if not */ private boolean hasHostConnected(NodeConnector connector) { if (topologyManager.getHostsAttachedToNodeConnector(connector) != null) { return true; } else { return false; } } /** *Function that is called when a Audio Packet needs to be Handled *@param inPKt The received Packet *@param srcAddr The src IP Address *@param srcMAC_B The src MAC Address in bytes *@param ingressConnector The connector where the packet came *@param node The node where the packet have been received *@param dstAddr The dst IP Address *@param dstMAC_B The dst MAC Address in bytes *@param dstPort The audio dstPort that identify the protocol *@return result The result of handle the audio Packet */ private PacketResult handleAudioPacket(RawPacket inPkt, InetAddress srcAddr, byte[] srcMAC_B, NodeConnector ingressConnector, Node node, InetAddress dstAddr, byte[] dstMAC_B, int dstPort) { Packet pkt = dataPacketService.decodeDataPacket(inPkt); NodeConnector egressConnector = null; PacketResult result = null; if (flood < MAXFLOODPACKET) { this.flood++; floodPacket(inPkt, node, ingressConnector); } else { NodeConnector tempSrcConnector = findHost(srcAddr); Node tempSrcNode = tempSrcConnector.getNode(); NodeConnector tempDstConnector = findHost(dstAddr); Node tempDstNode = tempDstConnector.getNode(); Map<Node, Node> tempMap = new HashMap<Node, Node>(); tempMap.put(tempSrcNode, tempDstNode); List<Edge> definitivePath = new ArrayList<Edge>(); try { this.audioSemaphore.tryAcquire(); definitivePath = this.audioRouting.getAudioShortestPath(tempSrcNode, tempDstNode); this.rtpSemaphore.release(); } catch (RuntimeException badDijkstraAudio) { log.info("Impossible to obtain the best Path."); log.info("If the problem persist please update your topology (link s1 s2 down and up for example)"); this.audioSemaphore.tryAcquire(); this.audioRouting = new AudioRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith); this.audioSemaphore.release(); return PacketResult.IGNORED; } if (definitivePath != null) { egressConnector = installAudioListFlows(definitivePath, srcAddr, srcMAC_B, dstAddr, dstMAC_B, node, tempSrcConnector, tempDstConnector, dstPort); if (!hasHostConnected(egressConnector)) { Edge downEdge = getDownEdge(node, egressConnector); if (downEdge != null) { putPacket(downEdge, pkt); } } if (egressConnector != null) { //Send the packet for the selected Port. inPkt.setOutgoingNodeConnector(egressConnector); this.dataPacketService.transmitDataPacket(inPkt); } else { floodPacket(inPkt, node, ingressConnector); } result = PacketResult.CONSUME; } else { log.trace("Destination host is unrecheable!"); result = PacketResult.IGNORED; } } return result; } /** *Function that is called when a ICMP Packet needs to be Handled *@param inPKt The received Packet *@param srcAddr The src IP Address *@param srcMAC_B The src MAC Address in bytes *@param ingressConnector The connector where the packet came *@param node The node where the packet have been received *@param dstAddr The dst IP Address *@param dstMAC_B The dst MAC Address in bytes *@return result The result of handle the ICMP Packet */ private PacketResult handleICMPPacket(RawPacket inPkt, InetAddress srcAddr, byte[] srcMAC_B, NodeConnector ingressConnector, Node node, InetAddress dstAddr, byte[] dstMAC_B) { Packet pkt = dataPacketService.decodeDataPacket(inPkt); NodeConnector egressConnector = null; PacketResult result = null; if (flood < MAXFLOODPACKET) { this.flood++; floodPacket(inPkt, node, ingressConnector); } else { NodeConnector tempSrcConnector = findHost(srcAddr); Node tempSrcNode = tempSrcConnector.getNode(); NodeConnector tempDstConnector = findHost(dstAddr); Node tempDstNode = tempDstConnector.getNode(); List<Edge> definitivePath = new ArrayList<Edge>(); try { this.icmpSemaphore.tryAcquire(); definitivePath = this.icmpRouting.getICMPShortestPath(tempSrcNode, tempDstNode); this.icmpSemaphore.release(); } catch (RuntimeException badDijkstraICMP) { log.info("Impossible to obtain the best Path."); log.info("If the problem persist please update your topology (link s1 s2 down and up for example)"); this.icmpSemaphore.tryAcquire(); this.icmpRouting = new ICMPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g); this.icmpSemaphore.release(); first = true; floodPacket(inPkt, node, ingressConnector); } if (definitivePath != null || definitivePath.isEmpty()) { egressConnector = installListFlows(definitivePath, srcAddr, srcMAC_B, dstAddr, dstMAC_B, node, tempSrcConnector, tempDstConnector); if (!hasHostConnected(egressConnector)) { Edge downEdge = getDownEdge(node, egressConnector); if (downEdge != null) { putPacket(downEdge, pkt); } } if (egressConnector != null) { //Send the packet for the selected Port. inPkt.setOutgoingNodeConnector(egressConnector); this.dataPacketService.transmitDataPacket(inPkt); } else { floodPacket(inPkt, node, ingressConnector); } /********************************************Debug********************************** */ /* log.debug("" + this.latencyMatrix[0][1]); log.debug("" + this.mediumLatencyMatrix[0][1]); log.debug("" + this.standardCostMatrix[0][1]); /*************************************** ***Debug***************************************/ result = PacketResult.CONSUME; } else { log.trace("Destination host is unrecheable!"); result = PacketResult.IGNORED; } } return result; } /** *Function that is called when a TCP Packet needs to be Handled *@param inPKt The received Packet *@param srcAddr The src IP Address *@param srcMAC_B The src MAC Address in bytes *@param ingressConnector The connector where the packet came *@param node The node where the packet have been received *@param dstAddr The dst IP Address *@param dstMAC_B The dst MAC Address in bytes *@param dstPort The dstPort *@return result The result of handle the RTP Packet */ private PacketResult handleTCPPacket(RawPacket inPkt, InetAddress srcAddr, byte[] srcMAC_B, NodeConnector ingressConnector, Node node, InetAddress dstAddr, byte[] dstMAC_B, int dstPort) { Packet pkt = dataPacketService.decodeDataPacket(inPkt); NodeConnector egressConnector = null; PacketResult result = null; if (flood < MAXFLOODPACKET) { this.flood++; floodPacket(inPkt, node, ingressConnector); } else { NodeConnector tempSrcConnector = findHost(srcAddr); Node tempSrcNode = tempSrcConnector.getNode(); NodeConnector tempDstConnector = findHost(dstAddr); Node tempDstNode = tempDstConnector.getNode(); Map<Node, Node> tempMap = new HashMap<Node, Node>(); tempMap.put(tempSrcNode, tempDstNode); List<Edge> definitivePath = new ArrayList<Edge>(); try { this.tcpSemaphore.tryAcquire(); definitivePath = this.tcpRouting.getTCPShortestPath(tempSrcNode, tempDstNode); this.tcpSemaphore.release(); } catch (RuntimeException badDijkstraTCP) { log.info("Impossible to obtain the best Path."); log.info("If the problem persist please update your topology (link s1 s2 down and up for example)"); this.tcpSemaphore.tryAcquire(); this.tcpRouting = new TCPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith); this.tcpSemaphore.release(); return PacketResult.IGNORED; } if (definitivePath != null) { egressConnector = installTCPListFlows(definitivePath, srcAddr, srcMAC_B, dstAddr, dstMAC_B, node, tempSrcConnector, tempDstConnector, dstPort); if (!hasHostConnected(egressConnector)) { Edge downEdge = getDownEdge(node, egressConnector); if (downEdge != null) { putPacket(downEdge, pkt); } } if (egressConnector != null) { //Send the packet for the selected Port. inPkt.setOutgoingNodeConnector(egressConnector); this.dataPacketService.transmitDataPacket(inPkt); } else { floodPacket(inPkt, node, ingressConnector); } result = PacketResult.CONSUME; } else { log.trace("Destination host is unrecheable!"); result = PacketResult.IGNORED; } } return result; } /** *Function that is called when a RTP Packet needs to be Handled *@param inPKt The received Packet *@param srcAddr The src IP Address *@param srcMAC_B The src MAC Address in bytes *@param ingressConnector The connector where the packet came *@param node The node where the packet have been received *@param dstAddr The dst IP Address *@param dstMAC_B The dst MAC Address in bytes *@param dstPort The RTP dstPort that identify the protocol *@return result The result of handle the RTP Packet */ private PacketResult handleRTPPacket(RawPacket inPkt, InetAddress srcAddr, byte[] srcMAC_B, NodeConnector ingressConnector, Node node, InetAddress dstAddr, byte[] dstMAC_B, int dstPort) { Packet pkt = dataPacketService.decodeDataPacket(inPkt); NodeConnector egressConnector = null; PacketResult result = null; if (flood < MAXFLOODPACKET) { this.flood++; floodPacket(inPkt, node, ingressConnector); } else { NodeConnector tempSrcConnector = findHost(srcAddr); Node tempSrcNode = tempSrcConnector.getNode(); NodeConnector tempDstConnector = findHost(dstAddr); Node tempDstNode = tempDstConnector.getNode(); Map<Node, Node> tempMap = new HashMap<Node, Node>(); tempMap.put(tempSrcNode, tempDstNode); List<Edge> definitivePath = new ArrayList<Edge>(); try { this.rtpSemaphore.tryAcquire(); definitivePath = this.rtpRouting.getRTPShortestPath(tempSrcNode, tempDstNode); this.rtpSemaphore.release(); } catch (RuntimeException badDijkstraRTP) { log.info("Impossible to obtain the best Path."); log.info("If the problem persist please update your topology (link s1 s2 down and up for example)"); this.rtpSemaphore.tryAcquire(); this.rtpRouting = new RTPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith, this.statisticsManager); this.rtpSemaphore.release(); return PacketResult.IGNORED; } if (definitivePath != null) { egressConnector = installRTPListFlows(definitivePath, srcAddr, srcMAC_B, dstAddr, dstMAC_B, node, tempSrcConnector, tempDstConnector, dstPort); if (!hasHostConnected(egressConnector)) { Edge downEdge = getDownEdge(node, egressConnector); if (downEdge != null) { putPacket(downEdge, pkt); } } if (egressConnector != null) { //Send the packet for the selected Port. inPkt.setOutgoingNodeConnector(egressConnector); this.dataPacketService.transmitDataPacket(inPkt); } else { floodPacket(inPkt, node, ingressConnector); } result = PacketResult.CONSUME; } else { log.trace("Destination host is unrecheable!"); result = PacketResult.IGNORED; } } return result; } /** *This function initialize the map edgeMediumTime */ private void initializeEdgeMediumTime() { Set<Edge> edges = this.topologyManager.getEdges().keySet(); edgeMediumMapTime.clear(); ArrayList<Long> temp; for (Iterator<Edge> it = edges.iterator(); it.hasNext();) { temp = new ArrayList(); Edge tempEdge = it.next(); edgeMediumMapTime.put(tempEdge, temp); } } /** *This function initialize the map edgeMediumTime */ private void completeEdgeMediumMapTime() { Set<Edge> edges = this.topologyManager.getEdges().keySet(); ArrayList<Long> temp; for (Iterator<Edge> it = edges.iterator(); it.hasNext();) { temp = new ArrayList(); Edge tempEdge = it.next(); if (!edgeMediumMapTime.containsKey(tempEdge)) { edgeMediumMapTime.put(tempEdge, temp); } } } /** *Function that is called when is necesarry to install a List of flows *All the flows will have two timeOut, idle and Hard. *@param path The Edge List *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param node The node where we have to return the egressConnector *@param srcConnector The Connector src *@param dstConnector The Connector dst *@param dstPort The rtp destination Port *@return The NodeConnector for the node */ private NodeConnector installAudioListFlows(List<Edge> path, InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, Node node, NodeConnector srcConnector, NodeConnector dstConnector, int dstPort) { NodeConnector result = null; for (int i = 0; i < path.size(); i++) { Edge tempEdge = path.get(i); NodeConnector tempConnector = tempEdge.getTailNodeConnector(); Node tempNode = tempConnector.getNode(); if (tempNode.equals(node)) { result = tempConnector; } if (programAudioFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, tempConnector, tempNode, dstPort)) { log.trace("Flow installed on " + node + " in the port " + tempConnector); } else { log.trace("Error trying to install the flow"); } if (i == path.size() - 1) { NodeConnector lastConnector = findHost(dstAddr); Node lastNode = lastConnector.getNode(); if (programRTPFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, lastConnector, lastNode, dstPort)) { log.trace("Flow installed on " + lastNode + " in the port " + lastConnector); } else { log.trace("Error trying to install the flow"); } } } ///////////////////////The dst node will have a flow for the IP return result; } /** *Function that is called when is necesarry to install a List of flows *All the flows will have two timeOut, idle and Hard. *@param path The Edge List *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param node The node where we have to return the egressConnector *@param srcConnector The Connector src *@param dstConnector The Connector dst *@return The NodeConnector for the node */ private NodeConnector installListFlows(List<Edge> path, InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, Node node, NodeConnector srcConnector, NodeConnector dstConnector) { NodeConnector result = null; for (int i = 0; i < path.size(); i++) { Edge tempEdge = path.get(i); NodeConnector tempConnector = tempEdge.getTailNodeConnector(); Node tempNode = tempConnector.getNode(); if (tempNode.equals(node)) { result = tempConnector; } if (programFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, tempConnector, tempNode)) { log.trace("Flow installed on " + node + " in the port " + tempConnector); } else { log.trace("Error trying to install the flow"); } } if (programFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, dstConnector, dstConnector.getNode())) { log.trace("Flow installed on " + dstConnector.getNode() + " in the port " + dstConnector); } else { log.trace("Error trying to install the flow"); } return result; } /** *Function that is called when is necesarry to install a List of flows *All the flows will have two timeOut, idle and Hard. *@param path The Edge List *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param node The node where we have to return the egressConnector *@param srcConnector The Connector src *@param dstConnector The Connector dst *@param dstPort The rtp destination Port *@return The NodeConnector for the node */ private NodeConnector installTCPListFlows(List<Edge> path, InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, Node node, NodeConnector srcConnector, NodeConnector dstConnector, int dstPort) { NodeConnector result = null; for (int i = 0; i < path.size(); i++) { Edge tempEdge = path.get(i); NodeConnector tempConnector = tempEdge.getTailNodeConnector(); Node tempNode = tempConnector.getNode(); if (tempNode.equals(node)) { result = tempConnector; } if (programTCPFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, tempConnector, tempNode, dstPort)) { log.trace("Flow installed on " + node + " in the port " + tempConnector); } else { log.trace("Error trying to install the flow"); } if (i == path.size() - 1) { NodeConnector lastConnector = findHost(dstAddr); Node lastNode = lastConnector.getNode(); if (programTCPFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, lastConnector, lastNode, dstPort)) { log.trace("Flow installed on " + lastNode + " in the port " + lastConnector); } else { log.trace("Error trying to install the flow"); } } } ///////////////////////The dst node will have a flow for the IP return result; } /** *Function that is called when is necesarry to install a List of flows *All the flows will have two timeOut, idle and Hard. *@param path The Edge List *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param node The node where we have to return the egressConnector *@param srcConnector The Connector src *@param dstConnector The Connector dst *@param dstPort The rtp destination Port *@return The NodeConnector for the node */ private NodeConnector installRTPListFlows(List<Edge> path, InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, Node node, NodeConnector srcConnector, NodeConnector dstConnector, int dstPort) { NodeConnector result = null; for (int i = 0; i < path.size(); i++) { Edge tempEdge = path.get(i); NodeConnector tempConnector = tempEdge.getTailNodeConnector(); Node tempNode = tempConnector.getNode(); if (tempNode.equals(node)) { result = tempConnector; } if (programRTPFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, tempConnector, tempNode, dstPort)) { log.trace("Flow installed on " + node + " in the port " + tempConnector); } else { log.trace("Error trying to install the flow"); } if (i == path.size() - 1) { NodeConnector lastConnector = findHost(dstAddr); Node lastNode = lastConnector.getNode(); if (programRTPFlow(srcAddr, srcMAC_B, dstAddr, dstMAC_B, lastConnector, lastNode, dstPort)) { log.trace("Flow installed on " + lastNode + " in the port " + lastConnector); } else { log.trace("Error trying to install the flow"); } } } ///////////////////////The dst node will have a flow for the IP return result; } /** *Function that is called when is necessary to put a Association Node,IP and NodeConnector *in ourt IPTable. *@param node The node where we have to create the association. *@param InetAddres The IP Address *@param NodeConnector The NodeConnector where the Packet came. */ private void learnIPAddress(Node node, InetAddress addr, NodeConnector connector) { Map<Node, InetAddress> temp = new HashMap<Node, InetAddress>(); temp.put(node, addr); this.tableIP.remove(temp); this.tableIP.put(temp, connector); } /** *The function is a modification of an another function. The original *is property of SDNHUB.org and it's used under a GPLv3 License. All the credits for SDNHUB.org *The original code can be find in *https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial/blob/master/adsal_L2_forwarding/src/main/java/org/opendaylight/tutorial/tutorial_L2_forwarding/internal/TutorialL2Forwarding.java *Function that is called when is necesarry to install a flow *All the flows will have two timeOut, idle and Hard. *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param outConnector The dstConnector that will install on the node *@param node The node where the flow will be installed */ synchronized private boolean programFlow(InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, NodeConnector outConnector, Node node) { Match match = new Match(); match.setField(MatchType.DL_TYPE, (short) 0x0800); // IPv4 ethertype match.setField(MatchType.NW_PROTO, IPProtocols.ICMP.byteValue()); match.setField(MatchType.NW_SRC, srcAddr); match.setField(MatchType.NW_DST, dstAddr); match.setField(MatchType.DL_SRC, srcMAC_B); match.setField(MatchType.DL_DST, dstMAC_B); List<Action> actions = new ArrayList<Action>(); actions.add(new Output(outConnector)); Flow f = new Flow(match, actions); // Create the flow Flow flow = new Flow(match, actions); flow.setIdleTimeout(idleTimeOut); flow.setHardTimeout(hardTimeOut); // Use FlowProgrammerService to program flow. try { semaphore.tryAcquire(); Status status = flowProgrammerService.addFlowAsync(node, flow); semaphore.release(); if (!status.isSuccess()) { log.trace("Could not program flow: " + status.getDescription()); return false; } else { return true; } } catch (RuntimeException unexpectError) { log.trace("Error trying to install the flow"); return false; } } /** *The function is a modification of an another function. The original *is property of SDNHUB.org and it's used under a GPLv3 License. All the credits for SDNHUB.org *The original code can be find in *https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial/blob/master/adsal_L2_forwarding/src/main/java/org/opendaylight/tutorial/tutorial_L2_forwarding/internal/TutorialL2Forwarding.java *Function that is called when is necesarry to install a flow *All the flows will have two timeOut, idle and Hard. *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param outConnector The dstConnector that will install on the node *@param node The node where the flow will be installed *@param dstPort The destination Port for Audio Packet */ synchronized private boolean programAudioFlow(InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, NodeConnector outConnector, Node node, int dstPort) { Match match = new Match(); match.setField(MatchType.DL_TYPE, (short) 0x0800); // IPv4 ethertype match.setField(MatchType.NW_SRC, srcAddr); match.setField(MatchType.NW_DST, dstAddr); match.setField(MatchType.DL_SRC, srcMAC_B); match.setField(MatchType.DL_DST, dstMAC_B); match.setField(MatchType.TP_DST, (short) dstPort); match.setField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()); List<Action> actions = new ArrayList<Action>(); actions.add(new Output(outConnector)); Flow f = new Flow(match, actions); // Create the flow Flow flow = new Flow(match, actions); flow.setIdleTimeout(idleTimeOut); flow.setHardTimeout(hardTimeOut); // Use FlowProgrammerService to program flow. try { semaphore.tryAcquire(); Status status = flowProgrammerService.addFlowAsync(node, flow); semaphore.release(); if (!status.isSuccess()) { log.trace("Could not program flow: " + status.getDescription()); return false; } else { return true; } } catch (RuntimeException unexpectError) { log.trace("Error trying to install the flow"); return false; } } /** *The function is a modification of an another function. The original *is property of SDNHUB.org and it's used under a GPLv3 License. All the credits for SDNHUB.org *The original code can be find in *https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial/blob/master/adsal_L2_forwarding/src/main/java/org/opendaylight/tutorial/tutorial_L2_forwarding/internal/TutorialL2Forwarding.java *Function that is called when is necesarry to install a flow *All the flows will have two timeOut, idle and Hard. *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param outConnector The dstConnector that will install on the node *@param node The node where the flow will be installed */ synchronized private boolean programTCPFlow(InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, NodeConnector outConnector, Node node, int dstPort) { Match match = new Match(); match.setField(MatchType.DL_TYPE, (short) 0x0800); // IPv4 ethertype match.setField(MatchType.NW_SRC, srcAddr); match.setField(MatchType.NW_DST, dstAddr); match.setField(MatchType.DL_SRC, srcMAC_B); match.setField(MatchType.DL_DST, dstMAC_B); match.setField(MatchType.TP_DST, (short) dstPort); match.setField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue()); List<Action> actions = new ArrayList<Action>(); actions.add(new Output(outConnector)); Flow f = new Flow(match, actions); // Create the flow Flow flow = new Flow(match, actions); flow.setIdleTimeout(idleTimeOut); flow.setHardTimeout(hardTimeOut); // Use FlowProgrammerService to program flow. try { semaphore.tryAcquire(); Status status = flowProgrammerService.addFlowAsync(node, flow); semaphore.release(); if (!status.isSuccess()) { log.trace("Could not program flow: " + status.getDescription()); return false; } else { return true; } } catch (RuntimeException unexpectError) { log.trace("Error trying to install the flow"); return false; } } /** *The function is a modification of an another function. The original *is property of SDNHUB.org and it's used under a GPLv3 License. All the credits for SDNHUB.org *The original code can be find in *https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial/blob/master/adsal_L2_forwarding/src/main/java/org/opendaylight/tutorial/tutorial_L2_forwarding/internal/TutorialL2Forwarding.java *Function that is called when is necesarry to install a flow *All the flows will have two timeOut, idle and Hard. *@param srcAddr The source IPv4 Address *@param srcMAC_B The srcMACAddress in byte format *@param dstAddr The destination IPV4 Address *@param dstMAC_B The dstMACAddress in byte format *@param outConnector The dstConnector that will install on the node *@param node The node where the flow will be installed *@param dstPort The destination Port for RTP Packet */ synchronized private boolean programRTPFlow(InetAddress srcAddr, byte[] srcMAC_B, InetAddress dstAddr, byte[] dstMAC_B, NodeConnector outConnector, Node node, int dstPort) { Match match = new Match(); match.setField(MatchType.DL_TYPE, (short) 0x0800); // IPv4 ethertype match.setField(MatchType.NW_SRC, srcAddr); match.setField(MatchType.NW_DST, dstAddr); match.setField(MatchType.DL_SRC, srcMAC_B); match.setField(MatchType.DL_DST, dstMAC_B); match.setField(MatchType.TP_DST, (short) dstPort); match.setField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()); List<Action> actions = new ArrayList<Action>(); actions.add(new Output(outConnector)); Flow f = new Flow(match, actions); // Create the flow Flow flow = new Flow(match, actions); flow.setIdleTimeout(idleTimeOut); flow.setHardTimeout(hardRTPTimeOut); // Use FlowProgrammerService to program flow. try { semaphore.tryAcquire(); Status status = flowProgrammerService.addFlowAsync(node, flow); semaphore.release(); if (!status.isSuccess()) { log.trace("Could not program flow: " + status.getDescription()); return false; } else { return true; } } catch (RuntimeException unexpectError) { log.trace("Error trying to install the flow"); return false; } } /** *Function that is called when is necessary to put a edge in the edgeMatrix *@param edge The edge that it will be put in the matrix. */ private void putEdge(Edge edge) { int node1 = getNodeConnectorIndex(edge.getTailNodeConnector()); int node2 = getNodeConnectorIndex(edge.getHeadNodeConnector()); this.edgeMatrix[node1][node2] = edge; log.trace("Put the edge in the position: " + node1 + " " + node2); } /** *Function that is called when is necessary to add a Edge to statistics *@param edge The edge */ private void putEdgeStatistics(Edge edge) { NodeConnector head = edge.getHeadNodeConnector(); NodeConnector tail = edge.getTailNodeConnector(); NodeConnectorStatistics headStatistics = this.statisticsManager.getNodeConnectorStatistics(head); NodeConnectorStatistics tailStatistics = this.statisticsManager.getNodeConnectorStatistics(tail); Long m1, m2; ////////////////////////////////// ArrayList<Long> tempArray = new ArrayList<Long>(); m1 = headStatistics.getTransmitByteCount(); m2 = tailStatistics.getTransmitByteCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, transmitBytes); Map<String, ArrayList> tempMap = new HashMap<String, ArrayList>(); tempMap.put(transmitBytes, tempArray); ///////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getReceiveByteCount(); m2 = tailStatistics.getReceiveByteCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, receiveBytes); tempMap.put(receiveBytes, tempArray); ////////////////////////////////// statisticSemaphore.tryAcquire(); statisticsT2 = System.currentTimeMillis(); statisticSemaphore.release(); statisticSemaphore.tryAcquire(); statisticsT1 = edgeMapTime.get(edge); statisticSemaphore.release(); Long previousB = previousSentBytes.get(edge); previousSentBytes.remove(edge); Long tempBW = minBandWith; if (statisticsT1 != null && statisticsT2 != null) { if (previousB == null) { if (statisticsT2 > statisticsT1) { tempBW = ((m1 + m2) / 2) / (statisticsT2 - statisticsT1); } } else { if (statisticsT2 > statisticsT1) { tempBW = ((m1 + m2) / 2 - previousB) / (statisticsT2 - statisticsT1); } } } statisticSemaphore.tryAcquire(); statisticsT1 = System.currentTimeMillis(); statisticSemaphore.release(); previousSentBytes.put(edge, (m1 + m2) / 2); compareminBandWith(tempBW); this.edgeBandWith.remove(edge); this.edgeMapTime.remove(edge); this.edgeBandWith.put(edge, tempBW); this.edgeMapTime.put(edge, statisticsT2); ////////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getTransmitDropCount(); m2 = tailStatistics.getTransmitDropCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, transmitDropBytes); tempMap.put(transmitDropBytes, tempArray); ///////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getReceiveDropCount(); m2 = tailStatistics.getReceiveDropCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, receiveDropBytes); tempMap.put(receiveDropBytes, tempArray); /////////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getTransmitErrorCount(); m2 = tailStatistics.getTransmitErrorCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, transmitErrorBytes); tempMap.put(transmitErrorBytes, tempArray); /////////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getReceiveErrorCount(); m2 = tailStatistics.getReceiveErrorCount(); tempArray.add(m1); tempArray.add(m2); compareStatistic(m1, m2, receiveErrorBytes); tempMap.put(receiveErrorBytes, tempArray); /////////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getTransmitPacketCount(); m2 = tailStatistics.getTransmitPacketCount(); tempArray.add(m1); tempArray.add(m2); tempMap.put(transmitPackets, tempArray); /////////////////////////////////////// tempArray = new ArrayList<Long>(); m1 = headStatistics.getReceivePacketCount(); m2 = tailStatistics.getReceivePacketCount(); tempArray.add(m1); tempArray.add(m2); tempMap.put(receivePackets, tempArray); /////////////////////////////////////// this.edgeStatistics.put(edge, tempMap); } /** *This function put a new association Edge Packet en the Map and put the thime in the PacketTime map *@parameter edge The edge *@parameter packet The packet */ private void putPacket(Edge edge, Packet packet) { Set<Packet> temp = this.edgePackets.get(edge); if (temp != null) { if (temp.contains(packet)) { temp.remove(packet); this.edgePackets.remove(edge); this.edgePackets.put(edge, temp); removePacketTime(edge, packet); } else { temp.add(packet); this.edgePackets.remove(edge); this.edgePackets.put(edge, temp); Long t = System.nanoTime(); Map<Edge, Packet> temp2 = new HashMap<Edge, Packet>(); temp2.put(edge, packet); this.packetTime.put(temp2, t); } } else { temp = new HashSet<Packet>(); temp.add(packet); this.edgePackets.remove(edge); this.edgePackets.put(edge, temp); Long t = System.nanoTime(); Map<Edge, Packet> temp2 = new HashMap<Edge, Packet>(); temp2.put(edge, packet); this.packetTime.put(temp2, t); } } /** *Function that is called when is necessary to check the flows on the nodes *@param edges The new node association Set<Edge> that have to be compared with the old topology */ synchronized private void removeOldFlow(Map<Node, Set<Edge>> edges) { Set<Node> nodes = edges.keySet(); for (Iterator<Node> it = nodes.iterator(); it.hasNext();) { Node tempNode = it.next(); switch (CLEANMETHOD) { case 1: delFlowSemaphore.tryAcquire(); Status status = flowProgrammerService.removeAllFlows(tempNode); delFlowSemaphore.release(); if (!status.isSuccess()) { log.info("Impossible to remove the flows on the node " + tempNode); } break; case 2: Set<Edge> tempEdgesOld = this.nodeEdges.get(tempNode); Set<Edge> tempEdgesNew = edges.get(tempNode); if (tempEdgesOld != null && tempEdgesNew != null) { if (tempEdgesNew.size() < tempEdgesOld.size()) { for (Iterator<Edge> it2 = tempEdgesOld.iterator(); it2.hasNext();) { Edge tempEdge = it2.next(); if (!tempEdgesNew.contains(tempEdge)) { log.trace("The edge " + tempEdge + " in the node " + tempNode + " is down now"); this.icmpSemaphore.tryAcquire(); first = icmpRouting.removeFlows(tempEdge, flowProgrammerService, statisticsManager); this.icmpSemaphore.release(); this.tcpSemaphore.tryAcquire(); first = tcpRouting.removeFlows(tempEdge, flowProgrammerService, statisticsManager); this.tcpSemaphore.release(); this.rtpSemaphore.tryAcquire(); first = rtpRouting.removeFlows(tempEdge, flowProgrammerService, statisticsManager); this.rtpSemaphore.release(); this.audioSemaphore.tryAcquire(); first = audioRouting.removeFlows(tempEdge, flowProgrammerService, statisticsManager); this.audioSemaphore.release(); } } first = true; } } break; } } } /** *This function is called when a association Edge, Packet, Time are wrong. *@param edge The edge identificator *@param packet The packet */ private void removePacketTime(Edge edge, Packet packet) { Map<Edge, Packet> temp = new HashMap<Edge, Packet>(); temp.put(edge, packet); this.packetTime.remove(temp); } private void resetLatencyMatrix() { if (this.latencyMatrix == null || this.latencyMatrix.length == 0 || this.mediumLatencyMatrix == null || this.mediumLatencyMatrix.length == 0) { this.latencyMatrix = new Long[this.nodeEdges.size()][this.nodeEdges.size()]; this.mediumLatencyMatrix = new Long[this.nodeEdges.size()][this.nodeEdges.size()]; if (edgeMediumMapTime == null) { initializeEdgeMediumTime(); } else { completeEdgeMediumMapTime(); } } } /** *This function restart the latency and mediumLatencyMatrix */ private void resetLatencyMatrix(Map<Node, Set<Edge>> edges) { if (this.latencyMatrix == null || this.latencyMatrix.length == 0 || this.mediumLatencyMatrix == null || this.mediumLatencyMatrix.length == 0 || force == true) { this.latencyMatrix = new Long[this.nodeEdges.size()][this.nodeEdges.size()]; this.mediumLatencyMatrix = new Long[this.nodeEdges.size()][this.nodeEdges.size()]; initializeEdgeMediumTime(); force = false; } else if (edgeMediumMapTime != null) { Set<Node> nodes = edges.keySet(); for (Iterator<Node> it = nodes.iterator(); it.hasNext();) { Node tempNode = it.next(); Set<Edge> tempEdgesOld = this.nodeEdges.get(tempNode); Set<Edge> tempEdgesNew = edges.get(tempNode); if (tempEdgesOld != null && tempEdgesNew != null) { if (tempEdgesNew.size() < tempEdgesOld.size()) { for (Iterator<Edge> it2 = tempEdgesOld.iterator(); it2.hasNext();) { Edge tempEdge = it2.next(); if (!tempEdgesNew.contains(tempEdge)) { this.edgeMediumMapTime.remove(tempEdge); //int aux1 = getNodeConnectorIndex(tempEdge.getTailNodeConnector()); //int aux2 = getNodeConnectorIndex(tempEdge.getHeadNodeConnector()); //this.edgeMatrix[aux1][aux2] = null; } } } } } } } private void resetStatistics() { this.edgeStatistics.clear(); Set<Node> tempNodes = this.nodeEdges.keySet(); for (Iterator<Node> it = tempNodes.iterator(); it.hasNext();) { Node tempNode = it.next(); Set<Edge> tempEdges = this.nodeEdges.get(tempNode); for (Iterator<Edge> it2 = tempEdges.iterator(); it2.hasNext();) { Edge tempEdge = it2.next(); resetNodeConnectorStatistics(tempEdge); } } } private void resetNodeConnectorStatistics(Edge edge) { NodeConnector head = edge.getHeadNodeConnector(); NodeConnector tail = edge.getTailNodeConnector(); NodeConnectorStatistics headStatistics = this.statisticsManager.getNodeConnectorStatistics(head); NodeConnectorStatistics tailStatistics = this.statisticsManager.getNodeConnectorStatistics(tail); headStatistics.setReceiveByteCount(0L); tailStatistics.setTransmitByteCount(0L); headStatistics.setReceivePacketCount(0L); tailStatistics.setTransmitPacketCount(0L); } /** *This function reset the routing protocols */ private void resetRoutingProtocols() { this.icmpSemaphore.tryAcquire(); this.icmpRouting = new ICMPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g); this.icmpSemaphore.release(); this.tcpSemaphore.tryAcquire(); this.tcpRouting = new TCPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith); this.tcpSemaphore.release(); this.rtpSemaphore.tryAcquire(); this.rtpRouting = new RTPRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith, this.statisticsManager); this.rtpSemaphore.release(); this.audioSemaphore.tryAcquire(); this.audioRouting = new AudioRouting(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.g, this.edgeBandWith, this.minBandWith); this.audioSemaphore.release(); } /** *This function return the time for a Edge Packet association *@param edge The edge *@param packet The packet *@return time The stored time */ private Long returnPacketTime(Edge edge, Packet packet) { Set<Map<Edge, Packet>> temp = this.packetTime.keySet(); Map<Edge, Packet> temp2 = new HashMap<Edge, Packet>(); temp2.clear(); temp2.put(edge, packet); for (Iterator<Map<Edge, Packet>> it = temp.iterator(); it.hasNext();) { Map<Edge, Packet> temp3 = it.next(); if (temp3.equals(temp2)) { Long time = this.packetTime.get(temp3); this.packetTime.remove(temp3); log.trace("Returning time for the solicitated packet" + time); return time; } } return null; } /** *This function is called when is necessary to sum all the elements of a Array *@param array The array which will be sum *@return result The complete sum of the array */ private Long sumLongArray(ArrayList<Long> array) { Long result = 0L; for (int i = 0; i < array.size(); i++) { result += array.get(i); } return result; } /** *Function that is called when we pretend to show in log all the elements of a Matrix *@matrix[][] The matrix */ private void traceEdgeMatrix(Edge matrix[][]) { for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { log.debug("Element " + i + " " + j + " is: " + matrix[i][j]); } } } /** *Function that is called when we pretend to show in log all the elements of a Matrix *@matrix[][] The matrix */ private void traceLongMatrix(Long matrix[][]) { if (matrix != null) { for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { log.debug("Element " + i + " " + j + " is: " + matrix[i][j]); } } } } /** *Function that is called when is necessary update the statistics. */ private void updateEdgeStatistics() { this.edgeStatistics.clear(); Set<Node> tempNodes = this.nodeEdges.keySet(); for (Iterator<Node> it = tempNodes.iterator(); it.hasNext();) { Node tempNode = it.next(); Set<Edge> tempEdges = this.nodeEdges.get(tempNode); for (Iterator<Edge> it2 = tempEdges.iterator(); it2.hasNext();) { Edge tempEdge = it2.next(); putEdgeStatistics(tempEdge); } } } /** *This function update the graph for ICMPRouting. */ private void updateICMPGraph() { createTopologyGraph(); this.icmpRouting.updateGraph(this.g); } /** *The follow function update the latencyMatrix for the position of the edge *@param edge The edge *@param t The latency time. */ private void updateLatencyMatrix(Edge edge, Long t) { int node1 = getNodeConnectorIndex(edge.getTailNodeConnector()); int node2 = getNodeConnectorIndex(edge.getHeadNodeConnector()); ArrayList<Long> temp = this.edgeMediumMapTime.get(edge); if (temp.size() == 20) { temp.remove(0); temp.add(t); } else { temp.add(t); } this.edgeMediumMapTime.remove(edge); this.edgeMediumMapTime.put(edge, temp); Long sum = sumLongArray(temp); this.mediumLatencyMatrix[node1][node2] = sum / temp.size(); if (minMediumLatency == null) { this.minMediumLatency = sum / temp.size(); } else { if (this.minMediumLatency > (sum / temp.size())) { this.minMediumLatency = sum / temp.size(); } } this.latencyMatrix[node1][node2] = t; log.trace("Put the Latency: " + t + " in the position: " + node1 + " " + node2); } /** *This function update the graph for RTPRouting. */ private void updateRTPGraph() { createTopologyGraph(); this.rtpRouting.updateGraph(this.g); } /** *Function that is called when is necessary update the current Topology store */ synchronized private void updateTopology() { Map<Node, Set<Edge>> edges = this.topologyManager.getNodeEdges(); if (this.nodeEdges.isEmpty() || !this.nodeEdges.equals(edges) || this.nodeEdges == null) { this.packetTime.clear(); this.edgePackets.clear(); this.edgeBandWith.clear(); this.minBandWith = 0L; this.edgeMapTime.clear(); flood = 0; MAXFLOODPACKET = 20 * this.nodeEdges.size(); if (this.nodeEdges != null && edges != null) { removeOldFlow(edges); resetLatencyMatrix(edges); } this.nodeEdges = edges; buildEdgeMatrix(edges); log.trace("The new map is " + this.nodeEdges); createTopologyGraph(); updateEdgeStatistics(); if (checkLatencyMatrix()) { if (first == true) { resetRoutingProtocols(); first = false; } } else { first = true; force = true; resetLatencyMatrix(); flood = 0; } log.debug("The topology has been updated"); } updateEdgeStatistics(); this.icmpSemaphore.tryAcquire(); this.icmpRouting.updateStandardCostMatrix(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics); this.icmpSemaphore.release(); this.tcpSemaphore.tryAcquire(); this.tcpRouting.updateTCPCostMatrix(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.edgeBandWith, this.minBandWith); this.tcpSemaphore.release(); this.rtpSemaphore.tryAcquire(); this.rtpRouting.updateRTPCostMatrix(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.edgeBandWith, this.minBandWith); this.rtpSemaphore.release(); this.audioSemaphore.tryAcquire(); this.audioRouting.updateAudioCostMatrix(this.nodeEdges, this.edgeMatrix, this.latencyMatrix, this.minLatency, this.mediumLatencyMatrix, this.minMediumLatency, this.edgeStatistics, this.maxStatistics, this.edgeBandWith, this.minBandWith); this.audioSemaphore.release(); //log.debug("Estadisticas: "+this.edgeStatistics); log.debug("Latencia instantnea: "); traceLongMatrix(latencyMatrix); log.debug("Latencia media: "); traceLongMatrix(mediumLatencyMatrix); //log.debug("Mapa de tiempos de enlaces: "+edgeMediumMapTime); } }