25 #include "ns3/simulator.h"
27 #include "ns3/mac48-address.h"
28 #include "ns3/ipv4-interface.h"
29 #include "ns3/ipv4-l3-click-protocol.h"
43 #define INTERFACE_ID_KERNELTAP 0
44 #define INTERFACE_ID_FIRST 1
45 #define INTERFACE_ID_FIRST_DROP 33
49 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
54 static TypeId tid = TypeId (
"ns3::Ipv4ClickRouting")
56 .AddConstructor<Ipv4ClickRouting> ()
62 Ipv4ClickRouting::Ipv4ClickRouting ()
63 : m_nonDefaultName (false),
68 Ipv4ClickRouting::~Ipv4ClickRouting ()
73 Ipv4ClickRouting::DoStart ()
75 uint32_t
id = m_ipv4->GetObject<Node> ()->GetId ();
77 if (!m_nonDefaultName)
79 std::stringstream name;
81 m_nodeName = name.str ();
84 m_simNode =
new simclick_node_t;
85 timerclear (&m_simNode->curtime);
87 AddSimNodeToClickMapping ();
93 if (simclick_click_create (m_simNode, m_clickFile.c_str ()) >= 0)
95 NS_LOG_DEBUG (m_nodeName <<
" has initialised a Click Router");
96 m_clickInitialised =
true;
100 NS_LOG_DEBUG (
"Click Router Initialisation failed for " << m_nodeName);
101 m_clickInitialised =
false;
105 simclick_click_run (m_simNode);
109 Ipv4ClickRouting::SetIpv4 (Ptr<Ipv4> ipv4)
115 Ipv4ClickRouting::DoDispose ()
117 if (m_clickInitialised)
119 simclick_click_kill (m_simNode);
123 Ipv4RoutingProtocol::DoDispose ();
127 Ipv4ClickRouting::SetClickFile (std::string clickfile)
129 m_clickFile = clickfile;
133 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
135 m_clickRoutingTableElement = name;
139 Ipv4ClickRouting::SetNodeName (std::string name)
142 m_nonDefaultName =
true;
146 Ipv4ClickRouting::GetNodeName ()
152 Ipv4ClickRouting::GetInterfaceId (
const char *ifname)
168 if (strstr (ifname,
"tap") || strstr (ifname,
"tun"))
172 else if (
const char *devname = strstr (ifname,
"eth"))
174 while (*devname && !isdigit ((
unsigned char) *devname))
181 retval = atoi (devname) + INTERFACE_ID_FIRST;
184 else if (
const char *devname = strstr (ifname,
"drop"))
186 while (*devname && !isdigit ((
unsigned char) *devname))
192 retval = atoi (devname) + INTERFACE_ID_FIRST_DROP;
200 if (retval >= (
int) m_ipv4->GetNInterfaces ())
209 Ipv4ClickRouting::IsInterfaceReady (
int ifid)
211 if (ifid >= 0 && ifid < (
int) m_ipv4->GetNInterfaces ())
222 Ipv4ClickRouting::GetIpAddressFromInterfaceId (
int ifid)
224 std::stringstream addr;
225 m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
231 Ipv4ClickRouting::GetIpPrefixFromInterfaceId (
int ifid)
233 std::stringstream addr;
234 m_ipv4->GetAddress (ifid, 0).GetMask ().Print (addr);
240 Ipv4ClickRouting::GetMacAddressFromInterfaceId (
int ifid)
242 std::stringstream addr;
244 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
245 Address devAddr = device->GetAddress ();
246 addr << Mac48Address::ConvertFrom (devAddr);
252 Ipv4ClickRouting::AddSimNodeToClickMapping ()
254 m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode,
this));
257 Ptr<Ipv4ClickRouting>
258 Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
260 return m_clickInstanceFromSimNode[simnode];
264 Ipv4ClickRouting::GetTimevalFromNow () const
266 struct timeval curtime;
267 uint64_t remainder = 0;
290 if (curtime.tv_usec == 1000000)
301 Ipv4ClickRouting::RunClickEvent ()
303 m_simNode->curtime = GetTimevalFromNow ();
305 NS_LOG_DEBUG (
"RunClickEvent at " << m_simNode->curtime.tv_sec <<
" " <<
307 simclick_click_run (m_simNode);
311 Ipv4ClickRouting::HandleScheduleFromClick (
const struct timeval *when)
315 Time simtime = Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
318 Simulator::Schedule (simdelay, &Ipv4ClickRouting::RunClickEvent,
this);
322 Ipv4ClickRouting::HandlePacketFromClick (
int ifid,
int ptype,
const unsigned char*
data,
int len)
331 NS_LOG_DEBUG (
"Incoming packet from tap0. Sending Packet up the stack.");
332 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
334 Ptr<Packet> p = Create<Packet> (
data, len);
337 p->RemoveHeader (ipHeader);
339 ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
343 NS_LOG_DEBUG (
"Incoming packet from eth" << ifid - 1 <<
" of type " << ptype <<
". Sending packet down the stack.");
345 Ptr<Packet> p = Create<Packet> (
data, len);
347 DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
352 Ipv4ClickRouting::SendPacketToClick (
int ifid,
int ptype,
const unsigned char* data,
int len)
355 m_simNode->curtime = GetTimevalFromNow ();
359 simclick_simpacketinfo pinfo;
363 simclick_click_send (m_simNode,ifid,ptype,data,len,&pinfo);
367 Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
372 for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
374 Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
382 int len = p->GetSize ();
383 uint8_t *buf =
new uint8_t [len];
384 p->CopyData (buf, len);
387 SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
393 Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
400 for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
402 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
404 if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
410 int len = p->GetSize ();
411 uint8_t *buf =
new uint8_t [len];
412 p->CopyData (buf, len);
415 SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
421 Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
423 char *handle = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
424 std::string ret (handle);
435 Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
437 int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
449 Ipv4ClickRouting::SetPromisc (
int ifid)
451 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
453 ipv4l3->SetPromisc (ifid);
457 Ipv4ClickRouting::RouteOutput (Ptr<Packet> p,
const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
459 Ptr<Ipv4Route> rtentry;
461 std::stringstream addr;
463 header.GetDestination ().Print (addr);
466 std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
468 int pos = s.find (
" ");
470 int interfaceId = atoi (s.substr (0, pos).c_str ());
471 Ipv4Address destination (s.substr (pos + 1).c_str ());
473 if (interfaceId != -1)
475 rtentry = Create<Ipv4Route> ();
476 rtentry->SetDestination (header.GetDestination ());
481 uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
483 Ipv4InterfaceAddress ifAddr;
484 if (numOifAddresses == 1)
486 ifAddr = m_ipv4->GetAddress (interfaceId, 0);
490 NS_FATAL_ERROR (
"XXX Not implemented yet: IP aliasing and Click");
492 rtentry->SetSource (ifAddr.GetLocal ());
493 rtentry->SetGateway (destination);
494 rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
495 sockerr = Socket::ERROR_NOTERROR;
496 NS_LOG_DEBUG (
"Found route to " << rtentry->GetDestination ()
497 <<
" via nh " << rtentry->GetGateway ()
498 <<
" with source addr " << rtentry->GetSource ()
499 <<
" and output dev " << rtentry->GetOutputDevice ());
504 <<
": RouteOutput for dest=" << header.GetDestination ()
505 <<
" No route to host");
506 sockerr = Socket::ERROR_NOROUTETOHOST;
515 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p,
const Ipv4Header &header,
516 Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
517 MulticastForwardCallback mcb, LocalDeliverCallback lcb,
520 NS_FATAL_ERROR (
"Click router does not have a RouteInput() interface!");
525 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream)
const
530 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
535 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
540 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
545 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
552 static int simstrlcpy (
char *buf,
int len,
const std::string &s)
558 if ((
unsigned) len > s.length ())
571 int simclick_sim_send (simclick_node_t *simnode,
572 int ifid,
int type,
const unsigned char* data,
int len,
573 simclick_simpacketinfo *pinfo)
584 clickInstance->HandlePacketFromClick (ifid, type, data, len);
590 int simclick_sim_command (simclick_node_t *simnode,
int cmd, ...)
600 case SIMCLICK_VERSION:
606 case SIMCLICK_SUPPORTS:
608 int othercmd = va_arg (val,
int);
609 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_NODE_ID);
613 case SIMCLICK_IFID_FROM_NAME:
615 const char *ifname = va_arg (val,
const char *);
617 retval = clickInstance->GetInterfaceId (ifname);
619 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
623 case SIMCLICK_IPADDR_FROM_NAME:
625 const char *ifname = va_arg (val,
const char *);
626 char *buf = va_arg (val,
char *);
627 int len = va_arg (val,
int);
629 int ifid = clickInstance->GetInterfaceId (ifname);
633 retval = simstrlcpy (buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
640 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
644 case SIMCLICK_IPPREFIX_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->GetIpPrefixFromInterfaceId (ifid));
661 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
665 case SIMCLICK_MACADDR_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);
670 int ifid = clickInstance->GetInterfaceId (ifname);
674 retval = simstrlcpy (buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
681 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
685 case SIMCLICK_SCHEDULE:
687 const struct timeval *when = va_arg (val,
const struct timeval *);
689 clickInstance->HandleScheduleFromClick (when);
692 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_SCHEDULE at " << when->tv_sec <<
"s and " << when->tv_usec <<
"usecs.");
697 case SIMCLICK_GET_NODE_NAME:
699 char *buf = va_arg (val,
char *);
700 int len = va_arg (val,
int);
701 retval = simstrlcpy (buf, len, clickInstance->GetNodeName ());
703 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
707 case SIMCLICK_IF_PROMISC:
709 int ifid = va_arg(val,
int);
710 clickInstance->SetPromisc (ifid);
717 case SIMCLICK_IF_READY:
719 int ifid = va_arg (val,
int);
722 retval = clickInstance->IsInterfaceReady (ifid);
731 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_TRACE");
735 case SIMCLICK_GET_NODE_ID:
738 NS_LOG_DEBUG (clickInstance->GetNodeName () <<
" Received a call for SIMCLICK_GET_NODE_ID");