net.beaconcontroller.tutorial.LearningSwitchTutorialSolution.java Source code

Java tutorial

Introduction

Here is the source code for net.beaconcontroller.tutorial.LearningSwitchTutorialSolution.java

Source

/**
 * Copyright 2010-2013, Stanford University. This file is licensed under the
 * BSD license as described in the included LICENSE.txt.
 */

/**
 * @author Luiz Arthur Feitosa dos Santos
 * @email luiz.arthur.feitosa.santos@gmail.com
 * 
 * This class starts all processes to OF-IDPS.
 * 
 * This class receive packets from switches to decide if the packets will be
 * forwarded to the network or if this packet represent a threat and must be
 * mitigated.
 * 
 * It is based on tutorial class used to teach how to build a simple layer 2
 * learning switch. (@author David Erickson (daviderickson@cs.stanford.edu) -
 * 10/14/12)
 * 
 */
package net.beaconcontroller.tutorial;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.OfIDPS.memoryAttacks.MemorysAttacks;
import net.beaconcontroller.IPS.AlertMessage;
import net.beaconcontroller.IPS.FlowsSuspiciousOfDoS;
import net.beaconcontroller.core.IBeaconProvider;
import net.beaconcontroller.core.IOFMessageListener;
import net.beaconcontroller.core.IOFSwitch;
import net.beaconcontroller.core.IOFSwitchListener;
import net.beaconcontroller.packet.Ethernet;
import net.beaconcontroller.packet.IPv4;

import org.json.simple.JSONObject;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFType;
import org.openflow.protocol.action.OFAction;
import org.openflow.protocol.action.OFActionEnqueue;
import org.openflow.protocol.action.OFActionOutput;
import org.openflow.util.U16;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LearningSwitchTutorialSolution implements IOFMessageListener, IOFSwitchListener {

    /*
     * To variables disable* below, use 1 to disable or any other value to enable, like 0 (zero).
     */
    /*
     * Use to enable or disable ALL Of-IDPS architecture.
     */
    protected static int disableOfIDPS = 0;
    /*
     * This can disable the ability of Of-IDPF collect Openflows statistics 
     * messages from network elements, like switches.
     * If this is is equal to 1 (enable), this will too affect disable the
     * disableOfIDPS_UseOfAlerts because we won't have OpenFlow data to do
     * the analysis. 
     */
    public static int disableOfIDPS_UseOfgetStatisticsFromNetwork = 0;
    /*
     * Enable or disable the analysis of security threats based on OpenFlow
     * statistics, this depend that the
     * disableOfIDPS_UseOfgetStatisticsFromNetwork variable is enabled
     * (different of 1).
     * 
     * If just this variable is disabled and the
     * disableOfIDPS_UseOfgetStatisticsFromNetwork variable is enable, then, the
     * Of-IDPS will just collect Openflow statistics messages but won't use this
     * for reactions.
     * 
     * This is used, here and in the MemoryAttacks class.
     */
    public static int disableOfIDPS_UseOfAlerts = 0;
    /*
     *  Enable or disable the use of IDS message on the Of-IDPS
     *  
     *  This is used in the MemoryAttacks class.
     *  
     */
    public static int disableOfIDPS_UseIDSAlerts = 0;

    /*
     * Used to send and receive OpenFlow statistics messages, like flows
     * installed in OpenFlow switches.
     */
    SensorOpenFlow sensorOF = new SensorOpenFlow();

    /*
     * Used to analyze OpenFlow message to decide if network have troubles, for
     * example we can use this to identify if network is under attack.
     */
    AnalysisFlow analysisFlow = new AnalysisFlow();

    /*
     * Memory attacks is used to store rules that can be applied in packets analyzed by this
     * OpenFlow controller, this will decide if this packets will has flows
     * normally installed, installed with bandwidth reduction, or blocked.
     *
     * SensoriaMemoryAttacks - Store rules that represent attacks that are occurring now, this rules
     * will correspond directly with the socket network from the security alerts
     * (IDS, OpenFlow, etc). TODO - We have that implement SensorialMemoryAttacks yet.
     * 
     * 
     */
    Map<String, AlertMessage> sensorialMemoryAttacks = new HashMap<String, AlertMessage>();
    /*
     * shortMemoryAttacks used to store security rules that are created by the
     * MemorysAttacks class, using recent security alerts from IDS and OpenFlow
     * statistics messages. This rules are created using the itemsets algorithm
     * that make this autonomically.
     */
    Map<String, AlertMessage> shortMemoryAttacks = new HashMap<String, AlertMessage>();
    /*
     * longMemoryAttacks used to store security rules that are created by the
     * MemorysAttacks class, using recent and old security alerts from IDS and
     * OpenFlow statistics messages. This rules are created using the itemsets
     * algorithm that make this autonomically. TODO - this needed to be
     * implemented yet.
     */
    Map<String, AlertMessage> longMemoryAttacks = new HashMap<String, AlertMessage>();

    /*
     * Starts the MemorysAttacks object that will populate the attacks memory
     * with security rules, that will be used to this class. This rules are
     * returned indirectly, like pointer.
     */
    protected MemorysAttacks memoryAttacks = new MemorysAttacks(shortMemoryAttacks, longMemoryAttacks,
            sensorialMemoryAttacks);

    private static int countNormalPackets = 0;
    private static int countAlertPriorityLow = 0;
    private static int countAlertPriorityMediun = 0;
    private static int countAlertPriorityHigh = 0;
    private static int countAlertPriorityUnknow = 0;
    //All packets handle in switch forward IPS method, not all handle by receive method! 
    private static int countAllArrivedPackets = 0;
    private static int countPacketsToOfController = 0;
    private static int countSentLikeHub = 0;

    // IP of OpenFlow controller
    //private static int controllerOfIP = IPv4.toIPv4Address("192.168.2.111");
    private static Set<Integer> allowIPs = new HashSet<Integer>();
    static {
        allowIPs.add(IPv4.toIPv4Address("192.168.2.111")); // OpenFlow controller;
        allowIPs.add(IPv4.toIPv4Address("192.168.2.112")); // Xen Controller - on eth1;
        allowIPs.add(IPv4.toIPv4Address("172.16.2.130")); // Xen Controller - on eth0;
        allowIPs.add(IPv4.toIPv4Address("192.168.2.133")); // IDS;
    }

    // used to print messages!
    protected static Logger log = LoggerFactory.getLogger(LearningSwitchTutorialSolution.class);

    // Used to send/receive OpenFlow messages.
    protected IBeaconProvider beaconProvider;

    /*
     * Used to store switch known ports, discovered during the normal switch
     * processing. For instance, host 1 is connected on the port 3 of switch 2.
     */
    protected Map<IOFSwitch, Map<Long, Short>> macTables = new HashMap<IOFSwitch, Map<Long, Short>>();

    // TODO - verify commentary in the class:
    //private RegisteredSwitches registredSwitches = new RegisteredSwitches(beaconProvider);

    /*
     * Constants that represent respectively, HIGH bandwidth reduction, MEDIUM
     * bandwidth reduction, LOW bandwidth reduction, and BLOCK network packets.
     */
    public final static int QUEUE_BANDWIDTH_HIGH = 0;
    public final static int QUEUE_BANDWIDTH_MEDIUM = 1;
    public final static int QUEUE_BANDWIDTH_LOW = 2;
    public final static int BLOCK_PACKET = 0;

    /**
     * Processes Openflow messages that arriving on the controller.
     * 
     * @param - sw, switch that sent this message.
     * @param - OpenFlow message that was sent.
     * 
     *        Obs. This method is very important, because is automatically
     *        called when one OpenFlow packet arrive on the controller, and this
     *        will start the Of-IDPS processing to this arrived packet, this
     *        processing can be forward this packet normally installing a simple
     *        flow on the switch, installing this packet with bandwidth
     *        reduction, or block this and all subsequent packets, this will
     *        depend of rules installed on the attacks memory.
     */
    public Command receive(IOFSwitch sw, OFMessage msg) throws IOException {
        initMACTable(sw);

        if (msg instanceof OFPacketIn) {
            OFPacketIn pi = (OFPacketIn) msg;

            // Send all packets like a hub!
            // forwardAsHub(sw, pi);

            // Send packets using a switch method and with the Of-IDPS architecture.
            forwardAsLearningSwitchWithIPS(sw, pi);
        }
        return Command.CONTINUE;
    }

    /**
     * EXAMPLE CODE: Floods the packet out all switch ports except the port it
     * came in on.
     * 
     * @param sw
     *            the OpenFlow switch object
     * @param pi
     *            the OpenFlow Packet In object
     * @throws IOException
     */
    public void forwardAsHub(IOFSwitch sw, OFPacketIn pi) throws IOException {
        // Create the OFPacketOut OpenFlow object
        OFPacketOut po = new OFPacketOut();

        // Create an output action to flood the packet, put it in the
        // OFPacketOut
        OFAction action = new OFActionOutput(OFPort.OFPP_FLOOD.getValue());
        po.setActions(Collections.singletonList(action));

        // Set the port the packet originally arrived on
        po.setInPort(pi.getInPort());

        OFMatch match = new OFMatch();
        match.loadFromPacket(pi.getPacketData(), (short) 0);
        // print packet
        /*
         * log.info("PortIn {}:", pi.getInPort());
         * log.info("L2  type {}, {}->{}",match.getDataLayerType(),
         * HexString.toHexString
         * (match.getDataLayerSource()),HexString.toHexString
         * (match.getDataLayerDestination()));
         * log.info("L3 proto {}, {}->{}",match
         * .getNetworkProtocol(),IPv4.fromIPv4Address
         * (match.getNetworkSource()),IPv4
         * .fromIPv4Address(match.getNetworkDestination()));
         */
        // Reference the packet buffered at the switch by id
        po.setBufferId(pi.getBufferId());
        if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
            /**
             * The packet was NOT buffered at the switch, therefore we must copy
             * the packet's data from the OFPacketIn to our new OFPacketOut
             * message.
             */
            po.setPacketData(pi.getPacketData());
        }
        // Send the OFPacketOut to the switch
        sw.getOutputStream().write(po);
    }

    /**
     * 
     * Use learning switch method plus the Of-IDPS security rules!
     * 
     * @param sw
     *            - switch.
     * @param pi
     *            - packet in (packet that arrived on the controller).
     * @throws IOException. Forward
     *             the arrived packets like, here in order: 1) Verify if the
     *             destination port to this packet is known. If this port is
     *             unknown send this packet for all ports of switch using
     *             forwardAsHub method.
     * 
     *             2) But, if the destination port is already known the
     *             controller will submit to the rules on the memory
     *             (sensorial,short, long) attacks, in this process we will
     *             have: 2.1) if this packet don't combine with NO rules a new
     *             flow will be installed on the switch, and this packet and all
     *             subsequent will be sent normally. 2.2) if this packet combine
     *             with a low priority security rule, a new flow with soft
     *             bandwidth will be installed on the switch, and this packet
     *             and all subsequent will be sent with this bandwidth
     *             reduction. 2.3) if this packet combine with a medium priority
     *             security rule, a new flow with severe bandwidth will be
     *             installed on the switch, and this packet and all subsequent
     *             will be sent with this bandwidth reduction. 2.4) if this
     *             packet combine with a high priority security rule, no flows
     *             are installed to this packet and this will be blocked.
     * 
     *             TODO - related to 2.4, verify if is possible installing a flow that
     *             blocked a packet and subsequents on the switch, thus the
     *             subsequents won't be constantly sent to the controller. But
     *             the first task is verify if this problem really exists!
     */

    public void forwardAsLearningSwitchWithIPS(IOFSwitch sw, OFPacketIn pi) throws IOException {

        Map<Long, Short> macTable = macTables.get(sw);

        // Build the Match
        OFMatch match = OFMatch.load(pi.getPacketData(), pi.getInPort());

        // Learn the port to reach the packet's source MAC
        macTable.put(Ethernet.toLong(match.getDataLayerSource()), pi.getInPort());

        // Retrieve the port previously learned for the packet's dest MAC
        Short outPort = macTable.get(Ethernet.toLong(match.getDataLayerDestination()));

        /*
         * TODO - maybe is better create the two flows for the network
         * connection at same time, for now we create first host1->host2 and
         * after in another moment host2->host1, but maybe we can create at same
         * time this two flows host1->host2 and host2->host1.
         */

        // Firstly all packets are normal, but after the security rules on memory attacks can change this.
        int acao = AlertMessage.NORMAL_PACKET;

        /*
         * if port is unknown sent like a hub for all ports of the switch! 
         * But, if the port is know (different of null) processes in the
         * Of-IDPS!
         */
        if (outPort != null) {
            // If packet if from or to OpenFlow controller the just sent this!
            //if (controllerOfIP==match.getNetworkSource() || controllerOfIP==match.getNetworkDestination()) {
            if (allowIPs.contains(match.getNetworkSource()) || allowIPs.contains(match.getNetworkDestination())) {
                sendPacketNormally(sw, pi, match, outPort);
                log.debug(">>>>>>   ATTENTION - Packets from {}->{} "
                        + "combines with allowed IPs, thus a flow was added without be submitted to Of-IDPS security rules. "
                        + "(ex. OpenFlow controller, IDS, XenServer, etc...)!",
                        IPv4.fromIPv4Address(match.getNetworkSource()),
                        IPv4.fromIPv4Address(match.getNetworkDestination()));
                countPacketsToOfController++;
            } else {

                //            log.debug("Packet being analyzed:");
                //            printPacketMatch(match);

                if (disableOfIDPS != 1) {

                    // test print
                    // for (String key : shortMemoryAttacks.keySet()) {
                    //  MensagemAlerta regraAtual = shortMemoryAttacks.get(key);
                    //  regraAtual.printMsgAlert();
                    // }

                    // memoryAttacks.printMemoryAttacks(shortMemoryAttacks);

                    /*
                     * Get network socket from the packet that will be analyzed by
                     * Of-IDPS.
                     */
                    String analysedPacketKeySocketNetwork = getKeyNetworkSocketFromAnalysedPacket(match);
                    /*
                     * Search if the analyzed packet have one specific rule on the
                     * memory of attacks. That's, is this packet have a perfect
                     * rule, that match with all camps from packet.
                     */
                    AlertMessage alertMsg = null;
                    alertMsg = shortMemoryAttacks.get(analysedPacketKeySocketNetwork);

                    if (alertMsg != null) {
                        /*
                         * if the analyzed packet perfectly matches with an alert
                         * entry, apply the security priority associated with this
                         * alert!
                         * 
                         * Maybe the alert don't have an priority associated, due to
                         * the logic of itemsets algorithm and, then this is treated
                         * to the method handlePacketsWithoutPriority()
                         */
                        //log.debug("Packet perfectly matches with alert: ");
                        acao = alertMsg.getPriorityAlert();
                    } else {
                        /*
                         * If the analyzed packet don't matches perfectly with all
                         * camps, then will be analyzed entry by entry, searching an
                         * entry what better match with the analyzed packet.
                         * 
                         * The itemsets algorithm, produces more generic rules, this
                         * is, rules with less items to be analyzed. Then here, we
                         * will compare if exists one entry that better combine with
                         * the packet using only some camps. Attention! For this,
                         * camps with the value Integer.MAX_VALUE combine with any
                         * value, in other words, is a wildcard * (any).
                         */
                        // Zero don't combine - different of zero combine
                        int combine = 0;
                        // Number of camps from rule that combine with the analyzed
                        // packet
                        int numberCampsThatCombinePerfectly = 0;
                        // Search for all rules in short memory

                        // test
                        // This will save the key rule that better combine with the packet. We use this to keep alive this rule.
                        String matchKey = null;
                        for (String key : shortMemoryAttacks.keySet()) {
                            int auxCombine = 0;
                            int auxNumberCampsThatCombinePerfectly = 0;
                            AlertMessage currentRule = shortMemoryAttacks.get(key);

                            // Analyze NetworkSource
                            if (currentRule.getNetworkSource() == match.getNetworkSource()) {
                                // Both camps match perfectly
                                auxNumberCampsThatCombinePerfectly++;
                            } else if (currentRule.getNetworkSource() != Integer.MAX_VALUE) {
                                // If this is true, stop the analysis of rule if one
                                // camp doesn't match.
                                continue;
                                // But, if this is false, then doesn't match
                                // perfectly, but the same camp on the rule is a
                                // wildcard (Integer.MAX_VALUE), that represents any
                                // (*), that forces the matches.
                            }

                            // Analyze NetworkDestination
                            if (currentRule.getNetworkDestination() == match.getNetworkDestination()) {
                                // Both camps match perfectly
                                auxNumberCampsThatCombinePerfectly++;
                            } else if (currentRule.getNetworkDestination() != Integer.MAX_VALUE) {
                                // If this is true, stop the analysis of rule if one
                                // camp doesn't match.
                                continue;
                                // But, if this is false, then doesn't match
                                // perfectly, but the same camp on the rule is a
                                // wildcard (Integer.MAX_VALUE), that represents any
                                // (*), that forces the matches.
                            }

                            // Analyze NetworkProtocol
                            if (currentRule.getNetworkProtocol() == match.getNetworkProtocol()) {
                                // Both camps match perfectly
                                auxNumberCampsThatCombinePerfectly++;
                            } else if (currentRule.getNetworkProtocol() != Integer.MAX_VALUE) {
                                // If this is true, stop the analysis of rule if one
                                // camp doesn't match.
                                continue;
                                // But, if this is false, then doesn't match
                                // perfectly, but the same camp on the rule is a
                                // wildcard (Integer.MAX_VALUE), that represents any
                                // (*), that forces the matches.
                            }

                            // Analyze TransportSource
                            if (currentRule.getTransportSource() == match.getTransportSource()) {
                                // Both camps match perfectly
                                auxNumberCampsThatCombinePerfectly++;
                            } else if (currentRule.getTransportSource() != Integer.MAX_VALUE) {
                                // If this is true, stop the analysis of rule if one
                                // camp doesn't match.
                                continue;
                                // But, if this is false, then doesn't match
                                // perfectly, but the same camp on the rule is a
                                // wildcard (Integer.MAX_VALUE), that represents any
                                // (*), that forces the matches.
                            }

                            // Analyse TransportDestination
                            if (currentRule.getTransportDestination() == match.getTransportDestination()) {
                                // Both camps match perfectly
                                auxNumberCampsThatCombinePerfectly++;
                            } else if (currentRule.getTransportDestination() != Integer.MAX_VALUE) {
                                // If this is true, stop the analysis of rule if one
                                // camp doesn't match.
                                continue;
                                // But, if this is false, then doesn't match
                                // perfectly, but the same camp on the rule is a
                                // wildcard (Integer.MAX_VALUE), that represents any
                                // (*), that forces the matches.
                            }

                            /*
                             * If the rule processing, has reached at this point, it
                             * means that this rule match with the analysed packet.
                             */
                            if (auxNumberCampsThatCombinePerfectly > numberCampsThatCombinePerfectly) {
                                // log.debug("\tCurrent rule math with the packet, the oldest was {} the new is {}",
                                // numberCampsThatCombinePerfectly,
                                // auxNumberCampsThatCombinePerfectly);
                                numberCampsThatCombinePerfectly = auxNumberCampsThatCombinePerfectly;
                                alertMsg = currentRule;

                                /*
                                 * Attention! Maybe the alert don't have an priority
                                 * associated, due to the logic of itemsets
                                 * algorithm and, then this is treated to the method
                                 * handlePacketsWithoutPriority()
                                 */
                                acao = currentRule.getPriorityAlert();
                                // log.debug("\t>>> The priority was set by an AUTONOMIC rule, the value of priority was: "+ acao);
                                matchKey = key;
                            }
                        }

                        /*
                         * Update the counter of packets that combine with this rule! 
                         * This will revive this rules and help to show that this 
                         * rules still in use!
                         * 
                         * TODO - Maybe we should store the total of packets that combine 
                         * with this rule during all rule life... and make the average of 
                         * packets during this time! this can be useful to decide if this 
                         * packets are result of attacks or not! Mainly to detect DoS... 
                         * 
                         */
                        //TESTE
                        if (matchKey != null) {
                            AlertMessage ruleThatCombine = shortMemoryAttacks.get(matchKey);
                            ruleThatCombine.increasePacketsMatchInOfControllerPerHop();
                            /*
                             * if we use this is necessary to uncomment the code 
                             * entry.getValue().verifyAndUpdatePacketsMatchInOfController();
                             * on MemorysAttacks class.
                             */
                            ruleThatCombine.increasePacketsMatchInOfControllerPerHop();
                            /*
                             * TODO - not is more easy just increase de time live of this rule?
                             */
                            //                        ruleThatCombine.increaseLife();
                        }
                    }

                    //printIfPacketMathWithSecurityRule(alertMsg);

                    acao = handlePacketsWithoutPriority(acao);

                    // Use this else case the architecture of Of-IDPS is disable
                } else {
                    //log.debug("\t!!!!!!!! Of-IDPS DISABLE !!!!!!!  for change this setup to 0 (zero) the variable disableOfIDPS on LearningSwithTutorialSolution class...");
                    acao = AlertMessage.NORMAL_PACKET;
                }

                // TEST - Just for TEST set to bandwitdth MEDIUM all with priority different that NORMAL
                //            if(acao!=AlertMessage.NORMAL_PACKET) {
                //                acao=AlertMessage.ALERT_PRIORITY_MEDIUM;
                //                log.debug("\t\t!!!!!!CAUTION, all alerts there are BANDWITHD MEDIUM in this test!!");
                //            }

                countAllArrivedPackets++;

                // TODO - TEST
                //            if(countAllArrivedPackets<500) {
                //                acao=AlertMessage.NORMAL_PACKET;
                //            } else if (countAllArrivedPackets<1000) {
                //                acao=AlertMessage.ALERT_PRIORITY_LOW;
                //            } else if (countAllArrivedPackets<1500) {
                //                acao=AlertMessage.ALERT_PRIORITY_MEDIUM;
                //            } else {
                //                acao=AlertMessage.ALERT_PRIORITY_HIGH;
                //            }
                // TODO - TEST END.

                /*
                 * Now based on the alert priority or in his absence decide how
                 * forward this packet and subsequent.
                 */
                switch (acao) {
                case AlertMessage.NORMAL_PACKET:
                    log.debug("!$!$!$!NORMAL PACKET, forward without alerts!");
                    sendPacketNormally(sw, pi, match, outPort);
                    countNormalPackets++;
                    // enviaPacoteQueue(sw, QUEUE_LARGURA_BANDA_ALTA, match,
                    // outPort, pi);
                    break;
                case AlertMessage.ALERT_PRIORITY_LOW:
                    //log.debug("!-!-!-! LOW security priority, forward to SOFT decrease bandwidth!");
                    log.debug("LOW");
                    sendPacketUsingBandwidthQueue(sw, QUEUE_BANDWIDTH_MEDIUM, match, outPort, pi);
                    countAlertPriorityLow++;
                    break;
                case AlertMessage.ALERT_PRIORITY_MEDIUM:
                    //log.debug("!+!+!+! MEDIUM security priority, forward to SEVERE decrease bandwidth!");
                    log.debug("MEDIUM");
                    sendPacketUsingBandwidthQueue(sw, QUEUE_BANDWIDTH_LOW, match, outPort, pi);
                    countAlertPriorityMediun++;
                    break;
                case AlertMessage.ALERT_PRIORITY_HIGH:
                    log.debug("HIGH");
                    //log.debug("!*!*!*! HIGH security priority, BLOCK this packet and all subsequent.");
                    countAlertPriorityHigh++;
                    break;
                default:
                    log.debug(
                            "********ATTENTION - Packet with security PRIORITY UNKNOWN, forward normally!!!*******");
                    sendPacketNormally(sw, pi, match, outPort);
                    countAlertPriorityUnknow++;
                }

                //            log.debug("Controller arrived: {} normal, {} low, {} medium, {} high, {} unknow, total: {}",
                //                    countNormalPackets, countAlertPriorityLow, countAlertPriorityMediun, countAlertPriorityHigh, countAlertPriorityUnknow, countAllArrivedPackets);
            }
        } else {
            // Destination port unknown, flood packet to all ports
            forwardAsHub(sw, pi);
            countSentLikeHub++;
        }

        //        JSONObject ofIDPSPacketsStatus = new JSONObject();
        //        ofIDPSPacketsStatus.put("normalPkts", countNormalPackets);
        //        ofIDPSPacketsStatus.put("lowPkts", countAlertPriorityLow);
        //        ofIDPSPacketsStatus.put("mediumPkts", countAlertPriorityMediun);
        //        ofIDPSPacketsStatus.put("highPkts", countAlertPriorityHigh);
        //        ofIDPSPacketsStatus.put("highUnknowPkts", countAlertPriorityUnknow);
        //        ofIDPSPacketsStatus.put("allPkts", countAllArrivedPackets);
        //        ofIDPSPacketsStatus.put("hugPkts", countSentLikeHub);

    }

    /**
     * Print if packet in math with an extent rule.
     * 
     * @param alertMsg - alert message
     */
    private void printIfPacketMathWithSecurityRule(AlertMessage alertMsg) {
        if (alertMsg == null) {
            log.debug("\tThis packet din't match with the list of alert rules");
        } else {
            log.debug("\tThis packet match with alert rule:");
            alertMsg.printMsgAlert();
        }
    }

    /**
     * 
     * Remember, the order of analysedPacketKeySocketNetwork camps MUST be the
     * same of method getKeyFromNetworkSocket in AlertsMessage (MensagemAlerta)
     * class
     * 
     * @param match - network packet, that will be extracted the socket key 
     * @return - One string that represent the network socket.
     */
    private String getKeyNetworkSocketFromAnalysedPacket(OFMatch match) {
        String analysedPacketKeySocketNetwork = Integer.toString(match.getNetworkSource())
                + Integer.toString(match.getNetworkDestination()) + Integer.toString(match.getNetworkProtocol())
                + Integer.toString(match.getTransportSource()) + Integer.toString(match.getTransportDestination());
        return analysedPacketKeySocketNetwork;
    }

    /**
     * 
     * Select a security priority if the alert rule generated by itemset
     * algorithm don't have an priority associated. Maybe the alert don't have
     * an priority associated due to the logic of itemsets algorithm.
     * 
     * @param acao
     *            - action analyzed - if action (acao) have this value in
     *            Integer.MAX_VALUE, means that this packet matches with a rule
     *            that didn't have an associated priority.
     * @return acao - action to be applied to the packet flow.
     */
    private int handlePacketsWithoutPriority(int acao) {
        if (acao == Integer.MAX_VALUE) {
            /**
             * TODO - Alerts without priority must be configured with
             * dynamic priorities, based on the type/description from
             * attack.
             * 
             * For now, this alerts will be set with a static value.
             * 
             */
            acao = AlertMessage.ALERT_PRIORITY_HIGH;
            log.debug("This alert don't have an related priority. Setting this with a high priority {}/{}.", "HIGH",
                    acao);
        }
        //log.debug("-----> Flow from this packet was set with priority: {}", acao);
        return acao;
    }

    /**
     * Print packet that being analyzed by controller.
     * 
     * @param match
     */
    private void printPacketMatch(OFMatch match) {
        log.debug(match.getNetworkSource() + ":" + match.getTransportSource() + "->" + match.getNetworkDestination()
                + ":" + match.getTransportDestination() + " (" + match.getNetworkProtocol() + ")");
    }

    /**
     * 
     * Delete/remove flows using just IP source and destination address.
     * 
     * @param sw - Switch.
     * @param match - Network packet.
     * 
     * TODO - Verify if this method can be removed to ActuatorOpenFlow class.
     *  
     */
    private void deleteFlowUsingIPSrcIPDst(IOFSwitch sw, OFMatch match) {
        // match.setNetworkSource(msg.getNetworkSource());
        // match.setNetworkDestination(msg.getNetworkDestination());
        // match.setNetworkProtocol((byte) msg.getNetworkProtocol());
        match.setWildcards(OFMatch.OFPFW_ALL ^ (OFMatch.OFPFW_NW_SRC_MASK | OFMatch.OFPFW_NW_DST_MASK));

        OFMessage fm = ((OFFlowMod) sw.getInputStream().getMessageFactory()

                .getMessage(OFType.FLOW_MOD))

                        .setMatch(match)

                        .setCommand(OFFlowMod.OFPFC_DELETE)

                        .setOutPort(OFPort.OFPP_NONE)

                        .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));

        try {
            sw.getOutputStream().write(fm);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            log.debug("Impossvel deletar fluxo");
            e.printStackTrace();
        }
    }

    /**
     * Delete ALL flows in one switch!
     * 
     * @param sw - Switch.
     * 
     */
    private void deleteAllFlowMod(IOFSwitch sw) {
        OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
        OFMessage fm = ((OFFlowMod) sw.getInputStream().getMessageFactory()

                .getMessage(OFType.FLOW_MOD))

                        .setMatch(match)

                        .setCommand(OFFlowMod.OFPFC_DELETE)

                        .setOutPort(OFPort.OFPP_NONE)

                        .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));

        try {
            sw.getOutputStream().write(fm);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            log.debug("Impossvel deletar fluxo");
            e.printStackTrace();
        }

    }

    /**
     * Send packet normally to the network, without restrictions!
     * 
     * @param sw - Switch.
     * @param pi - Packet network in.
     * @param match - Packet been analyzed.
     * @param outPort - Known output switch port.
     * @throws IOException
     */
    private void sendPacketNormally(IOFSwitch sw, OFPacketIn pi, OFMatch match, Short outPort) throws IOException {
        // Destination port known, push down a flow
        OFFlowMod fm = new OFFlowMod();
        fm.setBufferId(pi.getBufferId());
        // Use the Flow ADD command
        fm.setCommand(OFFlowMod.OFPFC_ADD);
        // Time out the flow after 5 seconds if inactivity
        fm.setIdleTimeout((short) 5);
        // Match the packet using the match created above
        fm.setMatch(match);
        // Send matching packets to outPort
        OFAction action = new OFActionOutput(outPort);
        fm.setActions(Collections.singletonList((OFAction) action));
        // Send this OFFlowMod to the switch
        sw.getOutputStream().write(fm);

        if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
            /**
             * EXTRA CREDIT: This is a corner case, the packet was not buffered
             * at the switch so it must be sent as an OFPacketOut after sending
             * the OFFlowMod
             */
            OFPacketOut po = new OFPacketOut();
            action = new OFActionOutput(outPort);
            po.setActions(Collections.singletonList(action));
            po.setBufferId(OFPacketOut.BUFFER_ID_NONE);
            po.setInPort(pi.getInPort());
            po.setPacketData(pi.getPacketData());
            sw.getOutputStream().write(po);
        }
    }

    /**
     * 
     * Send packet using one bandwidth reduction queue to the network.
     * 
     * @param sw - Switch.
     * @param queueNumber - Queue file number - type of bandwidth reduction (soft, severe).
     * @param match - Analyzed packet network.
     * @param outPort - Known output switch port.
     * @throws IOException
     */
    private void sendPacketUsingBandwidthQueue(IOFSwitch sw, int queueNumber, OFMatch match, Short outPort,
            OFPacketIn pi) throws IOException {
        List<OFAction> act = new ArrayList<OFAction>();
        short flowModLength = (short) OFFlowMod.MINIMUM_LENGTH;

        OFActionEnqueue actionEnque = new OFActionEnqueue();
        actionEnque.setPort(outPort);
        actionEnque.setQueueId(queueNumber); // number of queue that will be used.
        flowModLength += OFActionEnqueue.MINIMUM_LENGTH;
        act.add(actionEnque);
        OFFlowMod fm = (OFFlowMod) sw.getInputStream().getMessageFactory().getMessage(OFType.FLOW_MOD);
        fm.setBufferId(-1).setIdleTimeout((short) 100).setHardTimeout((short) 100)
                .setOutPort((short) OFPort.OFPP_ALL.getValue()).setMatch(match).setActions(act)
                .setLength(U16.t(flowModLength));
        sw.getOutputStream().write(fm);

        /*
         * TODO The code below is used in the original code of Beacon Openflow,
         * we need study better what this means and if we really need this.
         */

        OFAction action = new OFActionOutput(outPort);
        fm.setActions(Collections.singletonList((OFAction) action));

        if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
            /**
             * EXTRA CREDIT: This is a corner case, the packet was not buffered
             * at the switch so it must be sent as an OFPacketOut after sending
             * the OFFlowMod
             */
            OFPacketOut po = new OFPacketOut();
            action = new OFActionOutput(outPort);
            po.setActions(Collections.singletonList(action));
            po.setBufferId(OFPacketOut.BUFFER_ID_NONE);
            po.setInPort(pi.getInPort());
            po.setPacketData(pi.getPacketData());
            sw.getOutputStream().write(po);
        }
    }

    /**
     * get a list with all switches on network.
     * 
     * TODO - verify if: Here this list is made sending OpenFlow messages to
     * discover switches on the network, this can produce overhead, be careful!
     * If this is true, we can use the registeredSwitches class to control
     * this list without need to send OpenFlow Message all the time! There are this
     * function implemented like method and on the code in others part of the
     * Of-IDPS!
     * 
     * 
     * @return A collection of switches presents on network.
     */
    private Collection<IOFSwitch> getAllSwitchesOnNetwork() {
        //log.debug("Get switches on the network");
        if (beaconProvider.getListeningIPAddress().isAnyLocalAddress()) {
            /*
             * TODO ERRO - ERROR - sometimes appear switches that aren't really of the network (ghosts)!
             * 
             * In some tests the 2 lines below eliminates ghosts switches
             */
            Collection<IOFSwitch> col = new HashSet<IOFSwitch>();
            col.clear();
            col = beaconProvider.getSwitches().values();
            return col;
        } else {
            log.debug("SORRY!!! switches weren't found in this network.");
        }
        return null;
    }

    /**
     * Delete ALL flows in all switches on the network! 
     * 
     * If do you want delete only suspicious flows, 
     * this method can be very bad, 
     * because delete everything, 
     * suspicious or legitimate.
     * 
     * be careful...
     *      
     * */
    public void deleteAllFlowsInAllSwitches() {
        log.debug("Delete ALL flows in all switches on the network!");
        Collection<IOFSwitch> switches = new HashSet<IOFSwitch>();
        switches = getAllSwitchesOnNetwork();
        for (IOFSwitch s : switches) {
            IOFSwitch sw = beaconProvider.getSwitches().get(s.getId());
            deleteAllFlowMod(sw);
        }
    }

    // ---------- NO NEED TO EDIT ANYTHING BELOW THIS LINE ----------

    /**
     * Ensure there is a MAC to port table per switch
     * 
     * @param sw
     */
    private void initMACTable(IOFSwitch sw) {
        Map<Long, Short> macTable = macTables.get(sw);
        if (macTable == null) {
            macTable = new HashMap<Long, Short>();
            macTables.put(sw, macTable);
        }
    }

    @Override
    public void addedSwitch(IOFSwitch sw) {
        /*
         * TODO - Can we use this instead than use the method that discovery all switches on
         * the network? Here we can use a list and put all registered switches
         * there, this will avoid to send OpenFlow message on network and can be
         * more fast and produce less overhead!
         */
        //registredSwitches.addSwitchOnListOfRegisteredSwitches(sw);
    }

    @Override
    public void removedSwitch(IOFSwitch sw) {
        macTables.remove(sw);
        //registredSwitches.removeSwitchOnListOfRegisteredSwitches(sw);
    }

    /**
     * @param beaconProvider
     *            the beaconProvider to set
     */
    public void setBeaconProvider(IBeaconProvider beaconProvider) {
        this.beaconProvider = beaconProvider;
    }

    public void startUp() {
        log.trace("=======================Starting=======================");
        // beaconProvider.addOFMessageListener(OFType.PACKET_IN, this);
        beaconProvider.addOFMessageListener(OFType.PACKET_IN, this);
        beaconProvider.addOFMessageListener(OFType.STATS_REPLY, this);
        beaconProvider.addOFSwitchListener(this);

        // Thread responsible for construct the attacks memory
        // memoryAttacks.startUp();
        if (disableOfIDPS != 1) {

            if (disableOfIDPS_UseOfgetStatisticsFromNetwork != 1) {
                log.debug("\tStarting OpenFlow monitor statistics...");
                sensorOF.startUp(beaconProvider);
                sensorOF.start();
            } else {
                log.debug(
                        "\t!!!!!!!! ATTENTION, Of-IDPS won't get OpenFlow statistics, then won't be able to generate autonomic rules based on OpenFlow data!!!!!!!  to change this setup to 0 (zero) the variable disableOfIDPS_UseOfgetStatisticsFromNetwork on LearningSwithTutorialSolution class...");
            }

            log.debug("\tStarting AUTONOMIC rules...");
            memoryAttacks.startUp(beaconProvider);
            memoryAttacks.start();

            if (disableOfIDPS_UseOfAlerts != 1 && disableOfIDPS_UseOfgetStatisticsFromNetwork != 1) {
                log.debug("\tStarting OpenFlow ANALYSIS...");
                analysisFlow.start();
            } else {
                log.debug(
                        "\t!!!!!!!! ATTENTION, Of-IDPS ALERT OPENFLOW STATISTICS IS DISABLED, then won't be able to generate autonomic rules based on OpenFlow data!!!!!!!  to change this setup to 0 (zero) the variableS disableOfIDPS_UseOfgetStatisticsFromNetwork and disableOfIDPS_UseOfAlerts on LearningSwithTutorialSolution class...");
            }

        } else {
            log.debug(
                    "\t!!!!!!!! ATTENTION, Of-IDPS DISABLE and AUTONOMIC RULES TOO!!!!!!!  to change this setup to 0 (zero) the variable disableOfIDPS on LearningSwithTutorialSolution class...");
        }

    }

    public void shutDown() {
        log.trace("Stopping");
        beaconProvider.removeOFMessageListener(OFType.PACKET_IN, this);
        beaconProvider.removeOFMessageListener(OFType.STATS_REPLY, this);
        beaconProvider.removeOFSwitchListener(this);
    }

    public String getName() {
        return "tutorial";
    }

}