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)
574 static int simstrlcpy (
char *buf,
int len,
const std::string &s)
580 if ((
unsigned) len > s.length ())
593 int simclick_sim_send (simclick_node_t *simnode,
594 int ifid,
int type,
const unsigned char* data,
int len,
595 simclick_simpacketinfo *pinfo)
606 clickInstance->HandlePacketFromClick (ifid, type, data, len);
612 int simclick_sim_command (simclick_node_t *simnode,
int cmd, ...)
622 case SIMCLICK_VERSION:
628 case SIMCLICK_SUPPORTS:
630 int othercmd = va_arg (val,
int);
631 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
635 case SIMCLICK_IFID_FROM_NAME:
637 const char *ifname = va_arg (val,
const char *);
639 retval = clickInstance->GetInterfaceId (ifname);
641 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
645 case SIMCLICK_IPADDR_FROM_NAME:
647 const char *ifname = va_arg (val,
const char *);
648 char *buf = va_arg (val,
char *);
649 int len = va_arg (val,
int);
651 int ifid = clickInstance->GetInterfaceId (ifname);
655 retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
662 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
666 case SIMCLICK_IPPREFIX_FROM_NAME:
668 const char *ifname = va_arg (val,
const char *);
669 char *buf = va_arg (val,
char *);
670 int len = va_arg (val,
int);
672 int ifid = clickInstance->GetInterfaceId (ifname);
676 retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
683 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
687 case SIMCLICK_MACADDR_FROM_NAME:
689 const char *ifname = va_arg (val,
const char *);
690 char *buf = va_arg (val,
char *);
691 int len = va_arg (val,
int);
692 int ifid = clickInstance->GetInterfaceId (ifname);
696 retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
703 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
707 case SIMCLICK_SCHEDULE:
709 const struct timeval *when = va_arg (val,
const struct timeval *);
711 clickInstance->HandleScheduleFromClick (when);
714 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_SCHEDULE at " << when->tv_sec <<
"s and " << when->tv_usec <<
"usecs.");
719 case SIMCLICK_GET_NODE_NAME:
721 char *buf = va_arg (val,
char *);
722 int len = va_arg (val,
int);
723 retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
725 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
729 case SIMCLICK_IF_PROMISC:
731 int ifid = va_arg(val,
int);
732 clickInstance->SetPromisc (ifid);
739 case SIMCLICK_IF_READY:
741 int ifid = va_arg (val,
int);
744 retval = clickInstance->IsInterfaceReady (ifid);
753 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_TRACE");
757 case SIMCLICK_GET_NODE_ID:
760 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_GET_NODE_ID");
764 case SIMCLICK_GET_RANDOM_INT:
766 uint32_t *randomValue = va_arg (val, uint32_t *);
767 uint32_t maxValue = va_arg (val, uint32_t);
769 *randomValue =
static_cast<uint32_t
> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
775 case SIMCLICK_GET_DEFINES:
777 char *buf = va_arg (val,
char *);
778 size_t *size = va_arg (val,
size_t *);
779 uint32_t required = 0;
787 std::map<std::string, std::string> defines = clickInstance->GetDefines ();
788 std::map<std::string, std::string>::const_iterator it = defines.begin ();
789 while (it != defines.end ())
791 size_t available = *size - required;
792 if (it->first.length() + it->second.length() + 2 <= available)
794 simstrlcpy(buf + required, available, it->first);
795 required += it->first.length() + 1;
796 available -= it->first.length() + 1;
797 simstrlcpy(buf + required, available, it->second);
798 required += it->second.length() + 1;
802 required += it->first.length() + it->second.length() + 2;
806 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.
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)