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);
387 Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
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 std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
488 int pos = s.find (
" ");
490 int interfaceId = atoi (s.substr (0, pos).c_str ());
491 Ipv4Address destination (s.substr (pos + 1).c_str ());
493 if (interfaceId != -1)
495 rtentry = Create<Ipv4Route> ();
496 rtentry->SetDestination (header.GetDestination ());
501 uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
503 Ipv4InterfaceAddress ifAddr;
504 if (numOifAddresses == 1)
506 ifAddr = m_ipv4->GetAddress (interfaceId, 0);
511 NS_FATAL_ERROR (
"XXX Not implemented yet: IP aliasing and Click");
513 rtentry->SetSource (ifAddr.GetLocal ());
514 rtentry->SetGateway (destination);
515 rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
516 sockerr = Socket::ERROR_NOTERROR;
517 NS_LOG_DEBUG (
"Found route to " << rtentry->GetDestination ()
518 <<
" via nh " << rtentry->GetGateway ()
519 <<
" with source addr " << rtentry->GetSource ()
520 <<
" and output dev " << rtentry->GetOutputDevice ());
525 <<
": RouteOutput for dest=" << header.GetDestination ()
526 <<
" No route to host");
527 sockerr = Socket::ERROR_NOROUTETOHOST;
536 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p,
const Ipv4Header &header,
537 Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
538 MulticastForwardCallback mcb, LocalDeliverCallback lcb,
541 NS_FATAL_ERROR (
"Click router does not have a RouteInput() interface!");
546 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream)
const
551 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
556 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
561 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress
address)
566 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress
address)
575 static int simstrlcpy (
char *buf,
int len,
const std::string &s)
581 if ((
unsigned) len > s.length ())
594 int simclick_sim_send (simclick_node_t *simnode,
595 int ifid,
int type,
const unsigned char* data,
int len,
596 simclick_simpacketinfo *pinfo)
607 clickInstance->HandlePacketFromClick (ifid, type, data, len);
613 int simclick_sim_command (simclick_node_t *simnode,
int cmd, ...)
623 case SIMCLICK_VERSION:
629 case SIMCLICK_SUPPORTS:
631 int othercmd = va_arg (val,
int);
632 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
636 case SIMCLICK_IFID_FROM_NAME:
638 const char *ifname = va_arg (val,
const char *);
640 retval = clickInstance->GetInterfaceId (ifname);
642 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
646 case SIMCLICK_IPADDR_FROM_NAME:
648 const char *ifname = va_arg (val,
const char *);
649 char *buf = va_arg (val,
char *);
650 int len = va_arg (val,
int);
652 int ifid = clickInstance->GetInterfaceId (ifname);
656 retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
663 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
667 case SIMCLICK_IPPREFIX_FROM_NAME:
669 const char *ifname = va_arg (val,
const char *);
670 char *buf = va_arg (val,
char *);
671 int len = va_arg (val,
int);
673 int ifid = clickInstance->GetInterfaceId (ifname);
677 retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
684 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
688 case SIMCLICK_MACADDR_FROM_NAME:
690 const char *ifname = va_arg (val,
const char *);
691 char *buf = va_arg (val,
char *);
692 int len = va_arg (val,
int);
693 int ifid = clickInstance->GetInterfaceId (ifname);
697 retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
704 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
708 case SIMCLICK_SCHEDULE:
710 const struct timeval *when = va_arg (val,
const struct timeval *);
712 clickInstance->HandleScheduleFromClick (when);
715 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_SCHEDULE at " << when->tv_sec <<
"s and " << when->tv_usec <<
"usecs.");
720 case SIMCLICK_GET_NODE_NAME:
722 char *buf = va_arg (val,
char *);
723 int len = va_arg (val,
int);
724 retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
726 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
730 case SIMCLICK_IF_PROMISC:
732 int ifid = va_arg(val,
int);
733 clickInstance->SetPromisc (ifid);
740 case SIMCLICK_IF_READY:
742 int ifid = va_arg (val,
int);
745 retval = clickInstance->IsInterfaceReady (ifid);
754 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_TRACE");
758 case SIMCLICK_GET_NODE_ID:
761 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_GET_NODE_ID");
765 case SIMCLICK_GET_RANDOM_INT:
767 uint32_t *randomValue = va_arg (val, uint32_t *);
768 uint32_t maxValue = va_arg (val, uint32_t);
770 *randomValue =
static_cast<uint32_t
> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
776 case SIMCLICK_GET_DEFINES:
778 char *buf = va_arg (val,
char *);
779 size_t *size = va_arg (val,
size_t *);
780 uint32_t required = 0;
788 std::map<std::string, std::string> defines = clickInstance->GetDefines ();
789 std::map<std::string, std::string>::const_iterator it = defines.begin ();
790 while (it != defines.end ())
792 size_t available = *size - required;
793 if (it->first.length() + it->second.length() + 2 <= available)
795 simstrlcpy(buf + required, available, it->first);
796 required += it->first.length() + 1;
797 available -= it->first.length() + 1;
798 simstrlcpy(buf + required, available, it->second);
799 required += it->second.length() + 1;
803 required += it->first.length() + it->second.length() + 2;
807 if (required > *size)
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)
Smart pointer class similar to boost::intrusive_ptr.
#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.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_FATAL_ERROR(msg)
Fatal error handling.
int64_t GetFemtoSeconds(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 GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
TypeId SetGroupName(std::string groupName)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static Time Now(void)
Return the current simulation virtual time.
int64_t GetNanoSeconds(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.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)