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)