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> ()
63 Ipv4ClickRouting::Ipv4ClickRouting ()
64 : m_nonDefaultName (false),
67 m_random = CreateObject<UniformRandomVariable> ();
68 m_simNode =
new simclick_node_t;
69 timerclear (&m_simNode->curtime);
71 AddSimNodeToClickMapping ();
74 Ipv4ClickRouting::~Ipv4ClickRouting ()
79 Ipv4ClickRouting::DoInitialize ()
81 uint32_t
id = m_ipv4->GetObject<Node> ()->GetId ();
83 if (!m_nonDefaultName)
85 std::stringstream name;
87 m_nodeName = name.str ();
94 if (simclick_click_create (m_simNode, m_clickFile.c_str ()) >= 0)
96 NS_LOG_DEBUG (m_nodeName <<
" has initialised a Click Router");
97 m_clickInitialised =
true;
101 NS_LOG_DEBUG (
"Click Router Initialisation failed for " << m_nodeName);
102 m_clickInitialised =
false;
106 simclick_click_run (m_simNode);
115 Ptr<UniformRandomVariable>
116 Ipv4ClickRouting::GetRandomVariable (
void)
122 Ipv4ClickRouting::DoDispose ()
124 if (m_clickInitialised)
126 simclick_click_kill (m_simNode);
130 Ipv4RoutingProtocol::DoDispose ();
134 Ipv4ClickRouting::SetClickFile (std::string clickfile)
136 m_clickFile = clickfile;
140 Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
145 std::map<std::string, std::string>
146 Ipv4ClickRouting::GetDefines (
void)
152 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
154 m_clickRoutingTableElement = name;
158 Ipv4ClickRouting::SetNodeName (std::string name)
161 m_nonDefaultName =
true;
165 Ipv4ClickRouting::GetNodeName ()
171 Ipv4ClickRouting::GetInterfaceId (
const char *ifname)
187 if (strstr (ifname,
"tap") || strstr (ifname,
"tun"))
191 else if (
const char *devname = strstr (ifname,
"eth"))
193 while (*devname && !isdigit ((
unsigned char) *devname))
200 retval = atoi (devname) + INTERFACE_ID_FIRST;
203 else if (
const char *devname = strstr (ifname,
"drop"))
205 while (*devname && !isdigit ((
unsigned char) *devname))
211 retval = atoi (devname) + INTERFACE_ID_FIRST_DROP;
219 if (retval >= (
int) m_ipv4->GetNInterfaces ())
228 Ipv4ClickRouting::IsInterfaceReady (
int ifid)
230 if (ifid >= 0 && ifid < (
int) m_ipv4->GetNInterfaces ())
241 Ipv4ClickRouting::GetIpAddressFromInterfaceId (
int ifid)
243 std::stringstream addr;
244 m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
250 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (
int ifid)
252 std::stringstream addr;
253 m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
259 Ipv4ClickRouting::GetMacAddressFromInterfaceId (
int ifid)
261 std::stringstream addr;
263 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
264 Address devAddr = device->GetAddress ();
265 addr << Mac48Address::ConvertFrom (devAddr);
271 Ipv4ClickRouting::AddSimNodeToClickMapping ()
273 m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode,
this));
276 Ptr<Ipv4ClickRouting>
277 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
279 return m_clickInstanceFromSimNode[simnode];
283 Ipv4ClickRouting::GetTimevalFromNow () const
285 struct timeval curtime;
286 uint64_t remainder = 0;
309 if (curtime.tv_usec == 1000000)
320 Ipv4ClickRouting::RunClickEvent ()
322 m_simNode->curtime = GetTimevalFromNow ();
324 NS_LOG_DEBUG (
"RunClickEvent at " << m_simNode->curtime.tv_sec <<
" " <<
326 simclick_click_run (m_simNode);
330 Ipv4ClickRouting::HandleScheduleFromClick (
const struct timeval *when)
334 Time simtime = Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
337 Simulator::Schedule (simdelay, &Ipv4ClickRouting::RunClickEvent,
this);
341 Ipv4ClickRouting::HandlePacketFromClick (
int ifid,
int ptype,
const unsigned char*
data,
int len)
350 NS_LOG_DEBUG (
"Incoming packet from tap0. Sending Packet up the stack.");
351 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
353 Ptr<Packet> p = Create<Packet> (
data, len);
356 p->RemoveHeader (ipHeader);
358 ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
362 NS_LOG_DEBUG (
"Incoming packet from eth" << ifid - 1 <<
" of type " << ptype <<
". Sending packet down the stack.");
364 Ptr<Packet> p = Create<Packet> (
data, len);
366 DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
371 Ipv4ClickRouting::SendPacketToClick (
int ifid,
int ptype,
const unsigned char* data,
int len)
374 m_simNode->curtime = GetTimevalFromNow ();
378 simclick_simpacketinfo pinfo;
382 simclick_click_send (m_simNode,ifid,ptype,data,len,&pinfo);
386 Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
391 for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
393 Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
401 int len = p->GetSize ();
402 uint8_t *buf =
new uint8_t [len];
403 p->CopyData (buf, len);
406 SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
412 Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
419 for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
421 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
423 if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
429 int len = p->GetSize ();
430 uint8_t *buf =
new uint8_t [len];
431 p->CopyData (buf, len);
434 SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
440 Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
442 char *handle = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
443 std::string ret (handle);
454 Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
456 int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
468 Ipv4ClickRouting::SetPromisc (
int ifid)
470 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
472 ipv4l3->SetPromisc (ifid);
476 Ipv4ClickRouting::RouteOutput (Ptr<Packet> p,
const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
478 Ptr<Ipv4Route> rtentry;
480 std::stringstream addr;
482 header.GetDestination ().Print (addr);
485 std::string
s = ReadHandler (m_clickRoutingTableElement, addr.str ());
487 int pos = s.find (
" ");
489 int interfaceId = atoi (s.substr (0, pos).c_str ());
490 Ipv4Address destination (s.substr (pos + 1).c_str ());
492 if (interfaceId != -1)
494 rtentry = Create<Ipv4Route> ();
495 rtentry->SetDestination (header.GetDestination ());
500 uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
502 Ipv4InterfaceAddress ifAddr;
503 if (numOifAddresses == 1)
505 ifAddr = m_ipv4->GetAddress (interfaceId, 0);
510 NS_FATAL_ERROR (
"XXX Not implemented yet: IP aliasing and Click");
512 rtentry->SetSource (ifAddr.GetLocal ());
513 rtentry->SetGateway (destination);
514 rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
515 sockerr = Socket::ERROR_NOTERROR;
516 NS_LOG_DEBUG (
"Found route to " << rtentry->GetDestination ()
517 <<
" via nh " << rtentry->GetGateway ()
518 <<
" with source addr " << rtentry->GetSource ()
519 <<
" and output dev " << rtentry->GetOutputDevice ());
524 <<
": RouteOutput for dest=" << header.GetDestination ()
525 <<
" No route to host");
526 sockerr = Socket::ERROR_NOROUTETOHOST;
535 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p,
const Ipv4Header &header,
536 Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
537 MulticastForwardCallback mcb, LocalDeliverCallback lcb,
540 NS_FATAL_ERROR (
"Click router does not have a RouteInput() interface!");
545 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream)
const
550 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
555 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
560 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress
address)
565 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress
address)
572 static int simstrlcpy (
char *buf,
int len,
const std::string &s)
578 if ((
unsigned) len > s.length ())
591 int simclick_sim_send (simclick_node_t *simnode,
592 int ifid,
int type,
const unsigned char* data,
int len,
593 simclick_simpacketinfo *pinfo)
604 clickInstance->HandlePacketFromClick (ifid, type, data, len);
610 int simclick_sim_command (simclick_node_t *simnode,
int cmd, ...)
620 case SIMCLICK_VERSION:
626 case SIMCLICK_SUPPORTS:
628 int othercmd = va_arg (val,
int);
629 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
633 case SIMCLICK_IFID_FROM_NAME:
635 const char *ifname = va_arg (val,
const char *);
637 retval = clickInstance->GetInterfaceId (ifname);
639 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
643 case SIMCLICK_IPADDR_FROM_NAME:
645 const char *ifname = va_arg (val,
const char *);
646 char *buf = va_arg (val,
char *);
647 int len = va_arg (val,
int);
649 int ifid = clickInstance->GetInterfaceId (ifname);
653 retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
660 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
664 case SIMCLICK_IPPREFIX_FROM_NAME:
666 const char *ifname = va_arg (val,
const char *);
667 char *buf = va_arg (val,
char *);
668 int len = va_arg (val,
int);
670 int ifid = clickInstance->GetInterfaceId (ifname);
674 retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
681 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
685 case SIMCLICK_MACADDR_FROM_NAME:
687 const char *ifname = va_arg (val,
const char *);
688 char *buf = va_arg (val,
char *);
689 int len = va_arg (val,
int);
690 int ifid = clickInstance->GetInterfaceId (ifname);
694 retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
701 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
705 case SIMCLICK_SCHEDULE:
707 const struct timeval *when = va_arg (val,
const struct timeval *);
709 clickInstance->HandleScheduleFromClick (when);
712 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_SCHEDULE at " << when->tv_sec <<
"s and " << when->tv_usec <<
"usecs.");
717 case SIMCLICK_GET_NODE_NAME:
719 char *buf = va_arg (val,
char *);
720 int len = va_arg (val,
int);
721 retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
723 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
727 case SIMCLICK_IF_PROMISC:
729 int ifid = va_arg(val,
int);
730 clickInstance->SetPromisc (ifid);
737 case SIMCLICK_IF_READY:
739 int ifid = va_arg (val,
int);
742 retval = clickInstance->IsInterfaceReady (ifid);
751 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_TRACE");
755 case SIMCLICK_GET_NODE_ID:
758 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_GET_NODE_ID");
762 case SIMCLICK_GET_RANDOM_INT:
764 uint32_t *randomValue = va_arg (val, uint32_t *);
765 uint32_t maxValue = va_arg (val, uint32_t);
767 *randomValue =
static_cast<uint32_t
> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
773 case SIMCLICK_GET_DEFINES:
775 char *buf = va_arg (val,
char *);
776 size_t *size = va_arg (val,
size_t *);
777 uint32_t required = 0;
785 std::map<std::string, std::string> defines = clickInstance->GetDefines ();
786 std::map<std::string, std::string>::const_iterator it = defines.begin ();
787 while (it != defines.end ())
789 size_t available = *size - required;
790 if (it->first.length() + it->second.length() + 2 <= available)
792 simstrlcpy(buf + required, available, it->first);
793 required += it->first.length() + 1;
794 available -= it->first.length() + 1;
795 simstrlcpy(buf + required, available, it->second);
796 required += it->second.length() + 1;
800 required += it->first.length() + it->second.length() + 2;
804 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 the class in the ns-3 factory.
#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.
static Time Now(void)
Return the "current simulation 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.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)