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 
   50 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
 
   55   static TypeId tid = TypeId (
"ns3::Ipv4ClickRouting")
 
   57     .AddConstructor<Ipv4ClickRouting> ()
 
   64 Ipv4ClickRouting::Ipv4ClickRouting ()
 
   65   : m_nonDefaultName (false),
 
   68   m_random = CreateObject<UniformRandomVariable> ();
 
   69   m_simNode = 
new simclick_node_t;
 
   70   timerclear (&m_simNode->curtime);
 
   72   AddSimNodeToClickMapping ();
 
   75 Ipv4ClickRouting::~Ipv4ClickRouting ()
 
   80 Ipv4ClickRouting::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);
 
  116 Ptr<UniformRandomVariable>
 
  117 Ipv4ClickRouting::GetRandomVariable (
void)
 
  123 Ipv4ClickRouting::DoDispose ()
 
  125   if (m_clickInitialised)
 
  127       simclick_click_kill (m_simNode);
 
  131   Ipv4RoutingProtocol::DoDispose ();
 
  135 Ipv4ClickRouting::SetClickFile (std::string clickfile)
 
  137   m_clickFile = clickfile;
 
  141 Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
 
  146 std::map<std::string, std::string>
 
  147 Ipv4ClickRouting::GetDefines (
void)
 
  153 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
 
  155   m_clickRoutingTableElement = name;
 
  159 Ipv4ClickRouting::SetNodeName (std::string name)
 
  162   m_nonDefaultName = 
true;
 
  166 Ipv4ClickRouting::GetNodeName ()
 
  172 Ipv4ClickRouting::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 ())
 
  229 Ipv4ClickRouting::IsInterfaceReady (
int ifid)
 
  231   if (ifid >= 0 && ifid < (
int) m_ipv4->GetNInterfaces ())
 
  242 Ipv4ClickRouting::GetIpAddressFromInterfaceId (
int ifid)
 
  244   std::stringstream addr;
 
  245   m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
 
  251 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (
int ifid)
 
  253   std::stringstream addr;
 
  254   m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
 
  260 Ipv4ClickRouting::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);
 
  272 Ipv4ClickRouting::AddSimNodeToClickMapping ()
 
  274   m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, 
this));
 
  277 Ptr<Ipv4ClickRouting>
 
  278 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
 
  280   return m_clickInstanceFromSimNode[simnode];
 
  284 Ipv4ClickRouting::GetTimevalFromNow () const
 
  286   struct timeval curtime;
 
  287   uint64_t remainder = 0;
 
  310       if (curtime.tv_usec == 1000000)
 
  321 Ipv4ClickRouting::RunClickEvent ()
 
  323   m_simNode->curtime = GetTimevalFromNow ();
 
  325   NS_LOG_DEBUG (
"RunClickEvent at " << m_simNode->curtime.tv_sec << 
" " << 
 
  327   simclick_click_run (m_simNode);
 
  331 Ipv4ClickRouting::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);
 
  342 Ipv4ClickRouting::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);
 
  372 Ipv4ClickRouting::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);
 
  413 Ipv4ClickRouting::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);
 
  441 Ipv4ClickRouting::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);
 
  455 Ipv4ClickRouting::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 ());
 
  469 Ipv4ClickRouting::SetPromisc (
int ifid)
 
  471   Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
 
  473   ipv4l3->SetPromisc (ifid);
 
  477 Ipv4ClickRouting::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;
 
  550 Ipv4ClickRouting::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!");
 
  560 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream, 
Time::Unit unit)
 const 
  562   *stream->GetStream () << 
"\nCLICK Routing table printing is not yet implemented, skipping.\n";
 
  566 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
 
  571 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
 
  576 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress 
address)
 
  581 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress 
address)
 
  590 static int simstrlcpy (
char *buf, 
int len, 
const std::string &s)
 
  596       if ((
unsigned) len > s.length ())
 
  609 int 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);
 
  628 int 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:
 
  782         uint32_t *randomValue = va_arg (val, uint32_t *);
 
  783         uint32_t maxValue = va_arg (val, uint32_t);
 
  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 *);
 
  795         uint32_t required = 0;
 
  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.
 
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)