samples/main-serial-net-device-if.cc
author Tom Henderson <tomh@tomh.org>
Sun, 18 Mar 2007 14:06:51 -0700
changeset 345 47b41507a45a
parent 317 b5959aa4a02f
child 348 1802fde7996c
permissions -rw-r--r--
move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2007 University of Washington
 * All rights reserved.
 *
 * 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
 */

#if 0
#include <list>
#include <cassert>
#endif

#include "ns3/debug.h"
#include "ns3/internet-node.h"
#include "ns3/mac-address.h"
#include "ns3/packet.h"
#include "ns3/arp-ipv4-interface.h"
#include "ns3/ipv4-address.h"
#include "ns3/serial-channel.h"
#include "ns3/serial-net-device.h"
#include "ns3/trace-writer.h"
#include "ns3/drop-tail.h"
#include "ns3/arp-ipv4-interface.h"
#include "ns3/ipv4.h"
#include "ns3/trace-context.h"
#include "ns3/udp-socket.h"
#include "ns3/simulator.h"
#include "ns3/node-list.h"
#include "ns3/trace-root.h"


using namespace ns3;

class Logger : public TraceWriter{
public:
  Logger ()
  {
    NS_DEBUG_UNCOND("**** Logger()");
  }

  Logger (std::string const &filename) 
  {
    NS_DEBUG_UNCOND("**** Logger(string const &)");
    Open(filename);
  }

  Logger (char const *filename) : m_tracer(filename)
  {
    NS_DEBUG_UNCOND("**** Logger(char const *)");
    Open(filename);
  }

  ~Logger () {}

  void Log (TraceContext const &context, const Packet &p)
  {
    NodeList::NodeIndex nodeIndex;
    context.Get (nodeIndex);
    m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
    Ipv4::InterfaceIndex interfaceIndex;
    context.Get (interfaceIndex);
    m_filestr << "interface=" << interfaceIndex << " ";
    enum Queue::TraceType type;
    context.Get (type);
    switch (type) 
      {
      case Queue::ENQUEUE:
        m_filestr << "enqueue";
        break;
      case Queue::DEQUEUE:
        m_filestr << "dequeue";
        break;
      case Queue::DROP:
        m_filestr << "drop";
        break;
      }
    m_filestr << " bytes=" << p.GetSize () << std::endl;
  }

protected:
  TraceWriter m_tracer;
};

static void
GenerateTraffic (UdpSocket *socket, uint32_t size)
{
  std::cout << "Node: " << socket->GetNode()->GetId () 
            << " at=" << Simulator::Now ().GetSeconds () << "s,"
            << " tx bytes=" << size << std::endl;
  socket->SendDummy (size);
  if (size > 50)
    {
      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
    }
}

static void
UdpSocketPrinter (UdpSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
{
  std::cout << "Node: " << socket->GetNode()->GetId () 
            << " at=" << Simulator::Now ().GetSeconds () << "s,"
            << " rx bytes=" << size << std::endl;
}

static void
PrintTraffic (UdpSocket *socket)
{
  socket->SetDummyRxCallback (MakeCallback (&UdpSocketPrinter));
}


int main (int argc, char *argv[])
{
  NS_DEBUG_UNCOND("Serial Net Device Test");

  // create two nodes and a simple SerialChannel
  InternetNode a;
  InternetNode b;
  SerialChannel ch = SerialChannel ("Test Channel", 1000, Seconds (0.1));

  NodeList::Add (&a);
  NodeList::Add (&b);

  // create two NetDevices and assign one to each node
  // Note:  this would normally be done also in conjunction with
  //        creating a Channel
  //        Here, we do not care about the Device Address (point-to-point)
  //        but more generally, we would use a subclass such as MacAddress
  //        as follows:    MacAddress addra("00:00:00:00:00:01");
  //        so we'll pretend and give them simple MacAddresses here
   
  MacAddress addra("00:00:00:00:00:01");
  SerialNetDevice neta(&a, addra);

  DropTailQueue dtqa;

  neta.AddQueue(&dtqa);
  neta.SetName("a.eth0"); 

  MacAddress addrb("00:00:00:00:00:02");
  SerialNetDevice netb(&b, addrb);

  DropTailQueue dtqb;

  netb.AddQueue(&dtqb);
  netb.SetName("b.eth0"); 

  // bind the two NetDevices together by using a simple Channel
  // this method changed to do a bidirectional binding
  neta.Attach (&ch);
  netb.Attach (&ch);

  // Some simple prints to see whether it is working
  NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
  NS_DEBUG_UNCOND("netb.GetMtu() <= " << netb.GetMtu());
  NS_DEBUG_UNCOND("neta.GetAddress() <= " << neta.GetAddress());
  NS_DEBUG_UNCOND("netb.GetAddress() <= " << netb.GetAddress());

  // Note:  InternetNode constructor instantiates multiple Layer-3
  // protocols and registers them with the L3Demux object.
  // This takes care of Layer-2 -> Layer-3 bindings.
  //  XXX TODO:  will need to create a dummy IPv4 object for insertion
  //             into the Demux

  // We now need to bind the InternetNode to the various interfaces.
  // to get the Layer-3 -> Layer-2 bindings.

  // We do this by calling an "AddArpIpv4Interface(neta)" function on node a.
  // This should:  
  // i) create an Ipv4ArpInterface object (subclass of pure virtual
  //    Ipv4Interface object)
  // ii) add the Ipv4ArpInterface object to the InternetNode's internal
  //     vector of Ipv4Interfaces (keyed off of ifIndex)

  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode a");
  ArpIpv4Interface* arpipv4interfacep = new ArpIpv4Interface(&a, &neta);
  uint32_t indexA = (&a)->GetIpv4 ()->AddInterface (arpipv4interfacep);
  NS_DEBUG_UNCOND("Adding Interface " << indexA);


  // iii) give the interface an IP address

  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
  arpipv4interfacep->SetAddress(Ipv4Address("10.1.1.1"));
  arpipv4interfacep->SetNetworkMask(Ipv4Mask("255.255.255.0"));

  // iv) set the interface's state to "UP"

  NS_DEBUG_UNCOND("Setting ARP interface to UP");
  arpipv4interfacep->SetUp();

  a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);


  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
  ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
  uint32_t indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
  NS_DEBUG_UNCOND("Adding Interface " << indexB);


  // iii) give the interface an IP address

  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
  arpipv4interfacepb->SetAddress(Ipv4Address("10.1.1.2"));
  arpipv4interfacepb->SetNetworkMask(Ipv4Mask("255.255.255.0"));

  // iv) set the interface's state to "UP"

  NS_DEBUG_UNCOND("Setting ARP interface to UP");
  arpipv4interfacepb->SetUp();

  b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);


  UdpSocket *source = new UdpSocket (&a);
  UdpSocket *sink = new UdpSocket(&b);
  sink->Bind (80);
  source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);

  Logger logger("serial-net-test.log");

  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*", 
                      MakeCallback (&Logger::Log, &logger));

  PrintTraffic (sink);
  GenerateTraffic (source, 100);

  Simulator::Run ();

  Simulator::Destroy ();

  delete source;
  delete sink;

  return 0;
}