 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation;
  *
  * 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 received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */

#include "ns3/network-module.h"
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/dce-module.h"
#include "ns3/quagga-helper.h"
#include "ns3/point-to-point-helper.h"
#include "ns3/netanim-module.h"
#include "ns3/ipv4-dce-routing-helper.h"
#include "ns3/constant-position-mobility-model.h"
#include "ns3/applications-module.h"
#include "ns3/gnuplot.h"
#include "ns3/csma-module.h"
#include "ns3/mobility-module.h"

using namespace ns3;
double endTime = 300.0;
NS_LOG_COMPONENT_DEFINE ("BGP_routing");

/*
 *  -------------------- Metoda pro vypadek --------------------
*/
//VYPADEK: Metoda pro simulaci vypadku

int main (int argc, char *argv[])
{
LogComponentEnable ("BGP_routing", LOG_LEVEL_INFO);
/*
 *  -------------------- Vytvoreni uzlu --------------------
*/
NodeContainer nodes;
nodes.Create (4); //PRIDANI AS-5: Zvysit pocet uzlu pro n4 na 5
                  //PRIDANI AS-6: Zvysit pocet uzlu pro n5 na 6

NodeContainer serverLanNodes;
serverLanNodes.Add(nodes.Get(0));
serverLanNodes.Create (1);

NodeContainer clientLanNodes;
clientLanNodes.Add(nodes.Get(3));
clientLanNodes.Create(1);

NS_LOG_INFO ("Nodes created.");

/*
 *  -------------------- Vytvorenı prenosovych kanalu --------------------
*/
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

NS_LOG_INFO ("Channel Attribues set.");

/*
 *  -------------------- Prirazeni spoju --------------------
*/
NetDeviceContainer n0server1 = pointToPoint.Install(nodes.Get (0), serverLanNodes.Get (1));
NetDeviceContainer n0n1 = pointToPoint.Install(nodes.Get (0), nodes.Get (1));
NetDeviceContainer n1n2 = pointToPoint.Install(nodes.Get (1), nodes.Get (2));
NetDeviceContainer n2n3 = pointToPoint.Install(nodes.Get (2), nodes.Get (3));
NetDeviceContainer n3client1 = pointToPoint.Install (nodes.Get (3), clientLanNodes.Get(1));

//PRIDANI AS-5: Zde doplnte pridani spoje n4n0

//PRIDANI AS-5: Zde doplnte pridani spoje n4n3


//PRIDANI AS-6: Pridani spoje pro n5n1

//PRIDANI AS-6: Pridani spoje pro n5n2

//PRIDANI AS-6: Pridani spoje pro n5n3

NS_LOG_INFO ("Links created.");

/*
 *  -------------------- Prirazenı IP adres --------------------
*/
Ipv4AddressHelper ipv4AddrHelper;
InternetStackHelper stack;   
Ipv4DceRoutingHelper ipv4RoutingHelper;
stack.SetRoutingHelper(ipv4RoutingHelper);
stack.Install(nodes);
stack.Install(serverLanNodes.Get(1));
stack.Install(clientLanNodes.Get(1));
NS_LOG_INFO ("Stacks installed.");

ipv4AddrHelper.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer i0iserver1 = ipv4AddrHelper.Assign (n0server1);

ipv4AddrHelper.SetBase ("10.0.1.0", "255.255.255.252");
Ipv4InterfaceContainer i0i1 = ipv4AddrHelper.Assign (n0n1); 

ipv4AddrHelper.SetBase ("10.0.2.0", "255.255.255.252");
Ipv4InterfaceContainer i1i2 = ipv4AddrHelper.Assign (n1n2); 

ipv4AddrHelper.SetBase ("10.0.3.0", "255.255.255.252");
Ipv4InterfaceContainer i2i3 = ipv4AddrHelper.Assign (n2n3); 

ipv4AddrHelper.SetBase ("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer i3iclient1 = ipv4AddrHelper.Assign(n3client1);

//PRIDANI AS-5: Zde doplnte vyber adresniho rozsahu a prirazeni IP adres pro spoj n4n0


//PRIDANI AS-5: Zde doplnte vyber adresniho rozsahu a prirazeni IP adres pro spoj n4n3


//PRIDANI AS-6: Vyber adresniho rozsahu a priradzeni IP adres pro spoj n5n1


//PRIDANI AS-6: Vyber adresniho rozsahu a priradzeni IP adres pro spoj n5n2


//PRIDANI AS-6: Vyber adresniho rozsahu a priradzeni IP adres pro spoj n5n3

NS_LOG_INFO ("IP addresses assigned.");

// -------------------- Staticke cesty pro serverLanNode a clientLanNode --------------------
Ipv4StaticRoutingHelper staticHelper;
Ptr<Ipv4> ipv4 = serverLanNodes.Get(1)->GetObject<Ipv4>();
Ptr<Ipv4StaticRouting> Ipv4stat = staticHelper.GetStaticRouting(ipv4);
Ipv4stat->SetDefaultRoute(i0iserver1.GetAddress(0,0), 1, 0);

Ptr<Ipv4> ipv4_1 = clientLanNodes.Get(1)->GetObject<Ipv4>();
Ptr<Ipv4StaticRouting> Ipv4stat_1 = staticHelper.GetStaticRouting(ipv4_1);
Ipv4stat_1->SetDefaultRoute(i3iclient1.GetAddress(0), 1, 0);
NS_LOG_INFO ("Static routes set.");

/*
 *  -------------------- Konfigurace BGP --------------------
*/
DceManagerHelper processManager;
processManager.SetNetworkStack ("ns3::Ns3SocketFdFactory");
processManager.Install (nodes);
processManager.Install (serverLanNodes.Get(1));
processManager.Install (clientLanNodes.Get(1));

QuaggaHelper quagga;
quagga.EnableBgp (nodes);
// n0-n1
quagga.BgpAddNeighbor (nodes.Get(0), "10.0.1.2", quagga.GetAsn (nodes.Get (1)));
quagga.BgpAddNeighbor (nodes.Get(1), "10.0.1.1", quagga.GetAsn (nodes.Get (0)));
// n1-n2
quagga.BgpAddNeighbor (nodes.Get(1), "10.0.2.2", quagga.GetAsn (nodes.Get (2)));
quagga.BgpAddNeighbor (nodes.Get(2), "10.0.2.1", quagga.GetAsn (nodes.Get (1)));
//VYCHOZI TOPOLOGIE: Zde dopiste vytvoreni sousedstvi mezi smerovaci n2 a n3 (sit 10.0.3.0/30)
//n2-n3

//PRIDANI AS-5: Zde doplnte vytvoreni sousedstva mezi n4-n0

//PRIDANI AS-5: Zde doplnte vytvoreni sousedstva mezi n4-n3


//PEERLINK: Zde doplnte pridani PeerLinku na smerovaci n4


//PRIDANI AS-6: Pridani sousedstvi mezi n5-n1


//PRIDANI AS-6: Pridani sousedstvi mezi n5-n2


//PRIDANI AS-6: Pridani sousedstvi mezi n5-n3


quagga.EnableZebraDebug (nodes);
quagga.Install (nodes);
quagga.Install (clientLanNodes.Get(1));
NS_LOG_INFO ("BGP neighborhoods set.");

/*
 *  -------------------- UDP aplikace - generovani provozu --------------------
*/
UdpEchoServerHelper echoServer (7) ;
ApplicationContainer serverApps = echoServer.Install(serverLanNodes.Get(1));
serverApps.Start (Seconds (20.0)) ;
serverApps.Stop (Seconds (endTime)) ;

UdpEchoClientHelper echoClient (i0iserver1.GetAddress(1) , 7) ;
echoClient.SetAttribute ("MaxPackets", UintegerValue(5)) ;
echoClient.SetAttribute ("Interval", TimeValue (Seconds(1.0))) ;
echoClient.SetAttribute ("PacketSize", UintegerValue (1024)) ;

ApplicationContainer clientApps = echoClient.Install(clientLanNodes.Get(1));
clientApps.Start(Seconds (21.0)); //PEERLINK: Zmena casu na 23s
clientApps.Stop(Seconds (endTime));

//VYPADEK: Zde doplnte dalsi posilani paketu:
//PEERLINK: Zakomentovat preposilani paketu:

NS_LOG_INFO ("UDP application set.");

/*
 *  -------------------- Definice vystupu --------------------
*/
pointToPoint.EnablePcapAll ("bgp_start/p2p_nodes");
NS_LOG_INFO ("Pcaps enabled.");

Ptr<OutputStreamWrapper> routingTable_server = 
Create<OutputStreamWrapper>("bgp_start/bgp-RT_server.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(
  Seconds(50), serverLanNodes.Get(1), routingTable_server);

Ptr<OutputStreamWrapper> routingTable_n0 = Create<OutputStreamWrapper>("bgp_start/bgp-RT_n0.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(Seconds(50), nodes.Get(0), routingTable_n0);

Ptr<OutputStreamWrapper> routingTable_n1 = Create<OutputStreamWrapper>("bgp_start/bgp-RT_n1.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(Seconds(50), nodes.Get(1), routingTable_n1);

Ptr<OutputStreamWrapper> routingTable_n2 = Create<OutputStreamWrapper>("bgp_start/bgp-RT_n2.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(Seconds(50), nodes.Get(2), routingTable_n2);

Ptr<OutputStreamWrapper> routingTable_n3 = Create<OutputStreamWrapper>("bgp_start/bgp-RT_n3.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(Seconds(50), nodes.Get(3), routingTable_n3);

Ptr<OutputStreamWrapper> routingTable_client = Create<OutputStreamWrapper>("bgp_start/bgp-RT_client.log", std::ios::out);
ipv4RoutingHelper.PrintRoutingTableEvery(Seconds(50), clientLanNodes.Get(1), routingTable_client);

NS_LOG_INFO ("Routing tables printing set.");

//PRIDANI AS-5: Zde doplnte vytvoreni smerovaci tabulky pro smerovac n4


//PRIDANI AS-6: Pridani smerovaci tabulky pro n5


MobilityHelper mobility;
    mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                   "MinX", DoubleValue (10),
                                   "MinY", DoubleValue (10),
                                   "DeltaX", DoubleValue (1.0),
                                   "DeltaY", DoubleValue (1.0),
                                   "GridWidth", UintegerValue (10),
                                   "LayoutType", StringValue ("RowFirst"));
    mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
    mobility.Install (nodes);
    mobility.Install (serverLanNodes.Get(1));
    mobility.Install (clientLanNodes.Get(1));

AnimationInterface anim("bgp_animation.xml");
  anim.SetConstantPosition(serverLanNodes.Get(1), 1.0, 8.0, 0);
  anim.UpdateNodeDescription(serverLanNodes.Get(1), "Server");
  anim.UpdateNodeColor(serverLanNodes.Get(1), 50, 205, 50);

  anim.SetConstantPosition(nodes.Get(0), 1.0, 6.0, 0);
  anim.UpdateNodeDescription(nodes.Get(0), "AS-1");
  anim.UpdateNodeColor(nodes.Get(0), 50, 50, 205);

  anim.SetConstantPosition(nodes.Get(1), 4.0, 6.0, 0);
  anim.UpdateNodeDescription(nodes.Get(1), "AS-2");
  anim.UpdateNodeColor(nodes.Get(1), 255, 219, 88);

  anim.SetConstantPosition(nodes.Get(2), 7.0, 6.0, 0);
  anim.UpdateNodeDescription(nodes.Get(2), "AS-3");
  anim.UpdateNodeColor(nodes.Get(2), 255, 165, 0);

  anim.SetConstantPosition(nodes.Get(3), 10.0, 6.0, 0);
  anim.UpdateNodeDescription(nodes.Get(3), "AS-4");
  anim.UpdateNodeColor(nodes.Get(3), 255, 0, 0);

  anim.SetConstantPosition(clientLanNodes.Get(1), 10.0, 8.0, 0);
  anim.UpdateNodeDescription(clientLanNodes.Get(1), "Client");
  anim.UpdateNodeColor(clientLanNodes.Get(1), 255, 0, 0);

  //PRIDANI AS-5: Zde doplnte vytvoreni ikonky pro smerovac n4

  //PRIDANI AS-6: Zde doplnte vytvoreni ikonky pro smerovac n5


/*
 *  -------------------- Spusteni simulace --------------------
*/

//VYPADEK: Zde doplnte radek pro pridani vypadku:
    //PEERLINK: Zakomentovat vypadek

NS_LOG_INFO ("Run simulation.");
Simulator::Stop (Seconds (endTime));
NS_LOG_INFO ("Wait for simulation to end.");
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Simulation end.");

  return 0;
}
