25#include "ns3/simulator.h" 
   27#include "ns3/random-variable-stream.h" 
   28#include "ns3/mac48-address.h" 
   29#include "ns3/ipv4-interface.h" 
   30#include "ns3/ipv4-l3-click-protocol.h" 
   44#define INTERFACE_ID_KERNELTAP 0 
   45#define INTERFACE_ID_FIRST 1 
   46#define INTERFACE_ID_FIRST_DROP 33 
   50std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
 
   55  static TypeId tid = TypeId (
"ns3::Ipv4ClickRouting")
 
   57    .AddConstructor<Ipv4ClickRouting> ()
 
   64Ipv4ClickRouting::Ipv4ClickRouting ()
 
   65  : m_nonDefaultName (false),
 
   68  m_random = CreateObject<UniformRandomVariable> ();
 
   69  m_simNode = 
new simclick_node_t;
 
   70  timerclear (&m_simNode->curtime);
 
   72  AddSimNodeToClickMapping ();
 
   75Ipv4ClickRouting::~Ipv4ClickRouting ()
 
   80Ipv4ClickRouting::DoInitialize ()
 
   82  uint32_t id = m_ipv4->GetObject<Node> ()->GetId ();
 
   84  if (!m_nonDefaultName)
 
   86      std::stringstream name;
 
   88      m_nodeName = name.str ();
 
   95  if (simclick_click_create (m_simNode, m_clickFile.c_str ()) >= 0)
 
   97      NS_LOG_DEBUG (m_nodeName << 
" has initialised a Click Router");
 
   98      m_clickInitialised = 
true;
 
  102      NS_LOG_DEBUG (
"Click Router Initialisation failed for " << m_nodeName);
 
  103      m_clickInitialised = 
false;
 
  107  simclick_click_run (m_simNode);
 
  116Ptr<UniformRandomVariable>
 
  117Ipv4ClickRouting::GetRandomVariable (
void)
 
  123Ipv4ClickRouting::DoDispose ()
 
  125  if (m_clickInitialised)
 
  127      simclick_click_kill (m_simNode);
 
  131  Ipv4RoutingProtocol::DoDispose ();
 
  135Ipv4ClickRouting::SetClickFile (std::string clickfile)
 
  137  m_clickFile = clickfile;
 
  141Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
 
  146std::map<std::string, std::string>
 
  147Ipv4ClickRouting::GetDefines (
void)
 
  153Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
 
  155  m_clickRoutingTableElement = name;
 
  159Ipv4ClickRouting::SetNodeName (std::string name)
 
  162  m_nonDefaultName = 
true;
 
  166Ipv4ClickRouting::GetNodeName ()
 
  172Ipv4ClickRouting::GetInterfaceId (
const char *ifname)
 
  188  if (strstr (ifname, 
"tap") || strstr (ifname, 
"tun"))
 
  192  else if (
const char *devname = strstr (ifname, 
"eth"))
 
  194      while (*devname && !isdigit ((
unsigned char) *devname))
 
  201          retval = atoi (devname) + INTERFACE_ID_FIRST;
 
  204  else if (
const char *devname = strstr (ifname, 
"drop"))
 
  206      while (*devname && !isdigit ((
unsigned char) *devname))
 
  212          retval = atoi (devname) + INTERFACE_ID_FIRST_DROP;
 
  220  if (retval >= (
int) m_ipv4->GetNInterfaces ())
 
  229Ipv4ClickRouting::IsInterfaceReady (
int ifid)
 
  231  if (ifid >= 0 && ifid < (
int) m_ipv4->GetNInterfaces ())
 
  242Ipv4ClickRouting::GetIpAddressFromInterfaceId (
int ifid)
 
  244  std::stringstream addr;
 
  245  m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
 
  251Ipv4ClickRouting::GetIpPrefixFromInterfaceId (
int ifid)
 
  253  std::stringstream addr;
 
  254  m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
 
  260Ipv4ClickRouting::GetMacAddressFromInterfaceId (
int ifid)
 
  262  std::stringstream addr;
 
  264  Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
 
  265  Address devAddr = device->GetAddress ();
 
  266  addr << Mac48Address::ConvertFrom (devAddr);
 
  272Ipv4ClickRouting::AddSimNodeToClickMapping ()
 
  274  m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, 
this));
 
  278Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
 
  280  return m_clickInstanceFromSimNode[simnode];
 
  284Ipv4ClickRouting::GetTimevalFromNow () const
 
  286  struct timeval curtime;
 
  287  uint64_t remainder = 0;
 
  310      if (curtime.tv_usec == 1000000)
 
  321Ipv4ClickRouting::RunClickEvent ()
 
  323  m_simNode->curtime = GetTimevalFromNow ();
 
  325  NS_LOG_DEBUG (
"RunClickEvent at " << m_simNode->curtime.tv_sec << 
" " << 
 
  327  simclick_click_run (m_simNode);
 
  331Ipv4ClickRouting::HandleScheduleFromClick (
const struct timeval *when)
 
  335  Time simtime  = Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
 
  338  Simulator::Schedule (simdelay, &Ipv4ClickRouting::RunClickEvent, 
this);
 
  342Ipv4ClickRouting::HandlePacketFromClick (
int ifid, 
int ptype, 
const unsigned char* 
data, 
int len)
 
  351      NS_LOG_DEBUG (
"Incoming packet from tap0. Sending Packet up the stack.");
 
  352      Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
 
  354      Ptr<Packet> p = Create<Packet> (
data, len);
 
  357      p->RemoveHeader (ipHeader);
 
  359      ipv4l3->LocalDeliver (p, ipHeader, (
uint32_t) ifid);
 
  363      NS_LOG_DEBUG (
"Incoming packet from eth" << ifid - 1 << 
" of type " << ptype << 
". Sending packet down the stack.");
 
  365      Ptr<Packet> p = Create<Packet> (
data, len);
 
  367      DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
 
  372Ipv4ClickRouting::SendPacketToClick (
int ifid, 
int ptype, 
const unsigned char* 
data, 
int len)
 
  375  m_simNode->curtime = GetTimevalFromNow ();
 
  379  simclick_simpacketinfo pinfo;
 
  383  simclick_click_send (m_simNode,ifid,ptype,
data,len,&pinfo);
 
  392  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
 
  394      Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
 
  402  int len = p->GetSize ();
 
  403  uint8_t *buf = 
new uint8_t [len];
 
  404  p->CopyData (buf, len);
 
  407  SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
 
  413Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
 
  420  for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
 
  422      Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
 
  424      if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
 
  430  int len = p->GetSize ();
 
  431  uint8_t *buf = 
new uint8_t [len];
 
  432  p->CopyData (buf, len);
 
  435  SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
 
  441Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
 
  443  char *handle = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
 
  444  std::string ret (handle);
 
  455Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
 
  457  int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
 
  469Ipv4ClickRouting::SetPromisc (
int ifid)
 
  471  Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
 
  473  ipv4l3->SetPromisc (ifid);
 
  477Ipv4ClickRouting::RouteOutput (Ptr<Packet> p, 
const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
 
  479  Ptr<Ipv4Route> rtentry;
 
  481  std::stringstream addr;
 
  483  header.GetDestination ().Print (addr);
 
  486  NS_LOG_DEBUG (
"Probe click routing table for " << addr.str ());
 
  487  std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
 
  488  NS_LOG_DEBUG (
"string from click routing table: " << s);
 
  490  size_t pos = s.find (
" ");
 
  491  Ipv4Address destination;
 
  493  if (pos == std::string::npos)
 
  496      destination = Ipv4Address (
"0.0.0.0");
 
  497      interfaceId = atoi (s.c_str ());
 
  498      NS_LOG_DEBUG (
"case 1:  destination " << destination << 
" interfaceId " << interfaceId);
 
  502      interfaceId = atoi (s.substr (0, pos).c_str ());
 
  503      Ipv4Address destination (s.substr (pos + 1).c_str ());
 
  504      NS_LOG_DEBUG (
"case 2:  destination " << destination << 
" interfaceId " << interfaceId);
 
  507  if (interfaceId != -1)
 
  509      rtentry = Create<Ipv4Route> ();
 
  510      rtentry->SetDestination (header.GetDestination ());
 
  515      uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
 
  517      Ipv4InterfaceAddress ifAddr;
 
  518      if (numOifAddresses == 1)
 
  520          ifAddr = m_ipv4->GetAddress (interfaceId, 0);
 
  525          NS_FATAL_ERROR (
"XXX Not implemented yet:  IP aliasing and Click");
 
  527      rtentry->SetSource (ifAddr.GetLocal ());
 
  528      rtentry->SetGateway (destination);
 
  529      rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
 
  530      sockerr = Socket::ERROR_NOTERROR;
 
  531      NS_LOG_DEBUG (
"Found route to " << rtentry->GetDestination ()
 
  532                                      << 
" via nh " << rtentry->GetGateway ()
 
  533                                      << 
" with source addr " << rtentry->GetSource ()
 
  534                                      << 
" and output dev " << rtentry->GetOutputDevice ());
 
  539                                  << 
": RouteOutput for dest=" << header.GetDestination ()
 
  540                                  << 
" No route to host");
 
  541      sockerr = Socket::ERROR_NOROUTETOHOST;
 
  550Ipv4ClickRouting::RouteInput  (Ptr<const Packet> p, 
const Ipv4Header &header,
 
  551                               Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
 
  552                               MulticastForwardCallback mcb, LocalDeliverCallback lcb,
 
  555  NS_FATAL_ERROR (
"Click router does not have a RouteInput() interface!");
 
  560Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream, 
Time::Unit unit)
 const 
  562  *stream->GetStream () << 
"\nCLICK Routing table printing is not yet implemented, skipping.\n";
 
  566Ipv4ClickRouting::NotifyInterfaceUp (
uint32_t i)
 
  571Ipv4ClickRouting::NotifyInterfaceDown (
uint32_t i)
 
  576Ipv4ClickRouting::NotifyAddAddress (
uint32_t interface, Ipv4InterfaceAddress 
address)
 
  581Ipv4ClickRouting::NotifyRemoveAddress (
uint32_t interface, Ipv4InterfaceAddress 
address)
 
  590static int simstrlcpy (
char *buf, 
int len, 
const std::string &s)
 
  596      if ((
unsigned) len > s.length ())
 
  609int simclick_sim_send (simclick_node_t *simnode,
 
  610                       int ifid, 
int type, 
const unsigned char* 
data, 
int len,
 
  611                       simclick_simpacketinfo *pinfo)
 
  622  clickInstance->HandlePacketFromClick (ifid, type, 
data, len);
 
  628int simclick_sim_command (simclick_node_t *simnode, 
int cmd, ...)
 
  638    case SIMCLICK_VERSION:
 
  644    case SIMCLICK_SUPPORTS:
 
  646        int othercmd = va_arg (val, 
int);
 
  647        retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
 
  651    case SIMCLICK_IFID_FROM_NAME:
 
  653        const char *ifname = va_arg (val, 
const char *);
 
  655        retval = clickInstance->GetInterfaceId (ifname);
 
  657        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_IFID_FROM_NAME: " << ifname << 
" " << retval);
 
  661    case SIMCLICK_IPADDR_FROM_NAME:
 
  663        const char *ifname = va_arg (val, 
const char *);
 
  664        char *buf = va_arg (val, 
char *);
 
  665        int len = va_arg (val, 
int);
 
  667        int ifid = clickInstance->GetInterfaceId (ifname);
 
  671            retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
 
  678        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_IPADDR_FROM_NAME: " << ifname << 
" " << buf << 
" " << len);
 
  682    case SIMCLICK_IPPREFIX_FROM_NAME:
 
  684        const char *ifname = va_arg (val, 
const char *);
 
  685        char *buf = va_arg (val, 
char *);
 
  686        int len = va_arg (val, 
int);
 
  688        int ifid = clickInstance->GetInterfaceId (ifname);
 
  692            retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
 
  699        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname << 
" " << buf << 
" " << len);
 
  703    case SIMCLICK_MACADDR_FROM_NAME:
 
  705        const char *ifname = va_arg (val, 
const char *);
 
  706        char *buf = va_arg (val, 
char *);
 
  707        int len = va_arg (val, 
int);
 
  708        int ifid = clickInstance->GetInterfaceId (ifname);
 
  712            retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
 
  719        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_MACADDR_FROM_NAME: " << ifname << 
" " << buf << 
" " << len);
 
  723    case SIMCLICK_SCHEDULE:
 
  725        const struct timeval *when = va_arg (val, 
const struct timeval *);
 
  727        clickInstance->HandleScheduleFromClick (when);
 
  730        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_SCHEDULE at " << when->tv_sec << 
"s and " << when->tv_usec << 
"usecs.");
 
  735    case SIMCLICK_GET_NODE_NAME:
 
  737        char *buf = va_arg (val, 
char *);
 
  738        int len = va_arg (val, 
int);
 
  739        retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
 
  741        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" SIMCLICK_GET_NODE_NAME: " << buf << 
" " << len);
 
  745    case SIMCLICK_IF_PROMISC:
 
  747        int ifid = va_arg(val, 
int);
 
  748        clickInstance->SetPromisc (ifid);
 
  755    case SIMCLICK_IF_READY:
 
  757        int ifid = va_arg (val, 
int); 
 
  760        retval = clickInstance->IsInterfaceReady (ifid);
 
  769        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" Received a call for SIMCLICK_TRACE");
 
  773    case SIMCLICK_GET_NODE_ID:
 
  776        NS_LOG_DEBUG (clickInstance->GetNodeName () << 
" Received a call for SIMCLICK_GET_NODE_ID");
 
  780    case SIMCLICK_GET_RANDOM_INT:
 
  785        *randomValue = 
static_cast<uint32_t> (clickInstance->GetRandomVariable ()->GetValue (0.0, 
static_cast<double> (maxValue) + 1.0));
 
  791    case SIMCLICK_GET_DEFINES:
 
  793        char *buf = va_arg (val, 
char *);
 
  794        size_t *size = va_arg (val, 
size_t *);
 
  803        std::map<std::string, std::string> defines = clickInstance->GetDefines ();
 
  804        std::map<std::string, std::string>::const_iterator it = defines.begin ();
 
  805        while (it != defines.end ())
 
  807            size_t available = *size - required;
 
  808            if (it->first.length() + it->second.length() + 2 <= available)
 
  810                simstrlcpy(buf + required, available, it->first);
 
  811                required += it->first.length() + 1;
 
  812                available -= it->first.length() + 1;
 
  813                simstrlcpy(buf + required, available, it->second);
 
  814                required += it->second.length() + 1;
 
  818                required += it->first.length() + it->second.length() + 2;
 
  822        if (required > *size)
 
static TypeId GetTypeId(void)
Get the type ID.
Smart pointer class similar to boost::intrusive_ptr.
static Time Now(void)
Return the current simulation virtual time.
int64_t GetFemtoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetPicoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
TypeId SetGroupName(std::string groupName)
Set the group name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Length::Unit Unit
Save some typing by defining a short alias for Length::Unit.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)