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
51 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
56 static TypeId tid = TypeId (
"ns3::Ipv4ClickRouting")
58 .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)
573 static int simstrlcpy (
char *buf,
int len,
const std::string &s)
579 if ((
unsigned) len > s.length ())
592 int simclick_sim_send (simclick_node_t *simnode,
593 int ifid,
int type,
const unsigned char* data,
int len,
594 simclick_simpacketinfo *pinfo)
605 clickInstance->HandlePacketFromClick (ifid, type, data, len);
611 int simclick_sim_command (simclick_node_t *simnode,
int cmd, ...)
621 case SIMCLICK_VERSION:
627 case SIMCLICK_SUPPORTS:
629 int othercmd = va_arg (val,
int);
630 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
634 case SIMCLICK_IFID_FROM_NAME:
636 const char *ifname = va_arg (val,
const char *);
638 retval = clickInstance->GetInterfaceId (ifname);
640 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
644 case SIMCLICK_IPADDR_FROM_NAME:
646 const char *ifname = va_arg (val,
const char *);
647 char *buf = va_arg (val,
char *);
648 int len = va_arg (val,
int);
650 int ifid = clickInstance->GetInterfaceId (ifname);
654 retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
661 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
665 case SIMCLICK_IPPREFIX_FROM_NAME:
667 const char *ifname = va_arg (val,
const char *);
668 char *buf = va_arg (val,
char *);
669 int len = va_arg (val,
int);
671 int ifid = clickInstance->GetInterfaceId (ifname);
675 retval = simstrlcpy (buf, len, clickInstance->GetIpPrefixFromInterfaceId (ifid));
682 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
686 case SIMCLICK_MACADDR_FROM_NAME:
688 const char *ifname = va_arg (val,
const char *);
689 char *buf = va_arg (val,
char *);
690 int len = va_arg (val,
int);
691 int ifid = clickInstance->GetInterfaceId (ifname);
695 retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
702 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
706 case SIMCLICK_SCHEDULE:
708 const struct timeval *when = va_arg (val,
const struct timeval *);
710 clickInstance->HandleScheduleFromClick (when);
713 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_SCHEDULE at " << when->tv_sec <<
"s and " << when->tv_usec <<
"usecs.");
718 case SIMCLICK_GET_NODE_NAME:
720 char *buf = va_arg (val,
char *);
721 int len = va_arg (val,
int);
722 retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
724 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
728 case SIMCLICK_IF_PROMISC:
730 int ifid = va_arg(val,
int);
731 clickInstance->SetPromisc (ifid);
738 case SIMCLICK_IF_READY:
740 int ifid = va_arg (val,
int);
743 retval = clickInstance->IsInterfaceReady (ifid);
752 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_TRACE");
756 case SIMCLICK_GET_NODE_ID:
759 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_GET_NODE_ID");
763 case SIMCLICK_GET_RANDOM_INT:
765 uint32_t *randomValue = va_arg (val, uint32_t *);
766 uint32_t maxValue = va_arg (val, uint32_t);
768 *randomValue =
static_cast<uint32_t
> (clickInstance->GetRandomVariable ()->GetValue (0.0, static_cast<double> (maxValue) + 1.0));
774 case SIMCLICK_GET_DEFINES:
776 char *buf = va_arg (val,
char *);
777 size_t *size = va_arg (val,
size_t *);
778 uint32_t required = 0;
786 std::map<std::string, std::string> defines = clickInstance->GetDefines ();
787 std::map<std::string, std::string>::const_iterator it = defines.begin ();
788 while (it != defines.end ())
790 size_t available = *size - required;
791 if (it->first.length() + it->second.length() + 2 <= available)
793 simstrlcpy(buf + required, available, it->first);
794 required += it->first.length() + 1;
795 available -= it->first.length() + 1;
796 simstrlcpy(buf + required, available, it->second);
797 required += it->second.length() + 1;
801 required += it->first.length() + it->second.length() + 2;
805 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)
#define NS_ASSERT(condition)
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
#define NS_LOG_COMPONENT_DEFINE(name)
int64_t GetFemtoSeconds(void) const
#define NS_FATAL_ERROR(msg)
fatal error handling
double GetSeconds(void) const
int64_t GetMicroSeconds(void) const
static Time Now(void)
Return the "current simulation time".
int64_t GetNanoSeconds(void) const
int64_t GetPicoSeconds(void) const
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
#define NS_LOG_DEBUG(msg)
static TypeId GetTypeId(void)
Get the type ID.
TypeId SetParent(TypeId tid)