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.
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)