24 #include "ns3/ipv4-interface.h"
25 #include "ns3/ipv4-l3-click-protocol.h"
27 #include "ns3/mac48-address.h"
29 #include "ns3/random-variable-stream.h"
30 #include "ns3/simulator.h"
32 #include <click/simclick.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>();
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()
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()
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)
332 NS_LOG_DEBUG(
"HandleScheduleFromClick at " << when->tv_sec <<
" " << when->tv_usec <<
" "
336 Time::FromInteger(when->tv_sec, Time::S) + Time::FromInteger(when->tv_usec, Time::US);
339 Simulator::Schedule(simdelay, &Ipv4ClickRouting::RunClickEvent,
this);
343 Ipv4ClickRouting::HandlePacketFromClick(
int ifid,
int ptype,
const unsigned char*
data,
int len)
352 NS_LOG_DEBUG(
"Incoming packet from tap0. Sending Packet up the stack.");
353 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
355 Ptr<Packet> p = Create<Packet>(
data, len);
358 p->RemoveHeader(ipHeader);
360 ipv4l3->LocalDeliver(p, ipHeader, (uint32_t)ifid);
364 NS_LOG_DEBUG(
"Incoming packet from eth" << ifid - 1 <<
" of type " << ptype
365 <<
". Sending packet down the stack.");
367 Ptr<Packet> p = Create<Packet>(
data, len);
369 DynamicCast<Ipv4L3ClickProtocol>(m_ipv4)->SendDown(p, ifid);
374 Ipv4ClickRouting::SendPacketToClick(
int ifid,
int ptype,
const unsigned char*
data,
int len)
377 m_simNode->curtime = GetTimevalFromNow();
381 simclick_simpacketinfo pinfo;
385 simclick_click_send(m_simNode, ifid, ptype,
data, len, &pinfo);
394 for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
396 Ipv4Address addr = m_ipv4->GetAddress(ifid, 0).GetLocal();
404 int len = p->GetSize();
405 uint8_t* buf =
new uint8_t[len];
406 p->CopyData(buf, len);
409 SendPacketToClick(0, SIMCLICK_PTYPE_IP, buf, len);
415 Ipv4ClickRouting::Receive(Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
422 for (ifid = 0; ifid < m_ipv4->GetNInterfaces(); ifid++)
424 Ptr<NetDevice> device = m_ipv4->GetNetDevice(ifid);
426 if (Mac48Address::ConvertFrom(device->GetAddress()) == receiverAddr)
432 int len = p->GetSize();
433 uint8_t* buf =
new uint8_t[len];
434 p->CopyData(buf, len);
437 SendPacketToClick(ifid, SIMCLICK_PTYPE_ETHER, buf, len);
443 Ipv4ClickRouting::ReadHandler(std::string elementName, std::string handlerName)
445 char* handle = simclick_click_read_handler(m_simNode,
450 std::string ret(handle);
461 Ipv4ClickRouting::WriteHandler(std::string elementName,
462 std::string handlerName,
463 std::string writeString)
465 int r = simclick_click_write_handler(m_simNode,
468 writeString.c_str());
480 Ipv4ClickRouting::SetPromisc(
int ifid)
482 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
484 ipv4l3->SetPromisc(ifid);
488 Ipv4ClickRouting::RouteOutput(Ptr<Packet> p,
489 const Ipv4Header& header,
491 Socket::SocketErrno& sockerr)
493 Ptr<Ipv4Route> rtentry;
495 std::stringstream addr;
497 header.GetDestination().Print(addr);
500 NS_LOG_DEBUG(
"Probe click routing table for " << addr.str());
501 std::string s = ReadHandler(m_clickRoutingTableElement, addr.str());
504 size_t pos = s.find(
' ');
505 Ipv4Address destination;
507 if (pos == std::string::npos)
510 destination = Ipv4Address(
"0.0.0.0");
511 interfaceId = atoi(s.c_str());
512 NS_LOG_DEBUG(
"case 1: destination " << destination <<
" interfaceId " << interfaceId);
516 interfaceId = atoi(s.substr(0, pos).c_str());
517 Ipv4Address destination(s.substr(pos + 1).c_str());
518 NS_LOG_DEBUG(
"case 2: destination " << destination <<
" interfaceId " << interfaceId);
521 if (interfaceId != -1)
523 rtentry = Create<Ipv4Route>();
524 rtentry->SetDestination(header.GetDestination());
529 uint32_t numOifAddresses = m_ipv4->GetNAddresses(interfaceId);
531 Ipv4InterfaceAddress ifAddr;
532 if (numOifAddresses == 1)
534 ifAddr = m_ipv4->GetAddress(interfaceId, 0);
541 rtentry->SetSource(ifAddr.GetLocal());
542 rtentry->SetGateway(destination);
543 rtentry->SetOutputDevice(m_ipv4->GetNetDevice(interfaceId));
544 sockerr = Socket::ERROR_NOTERROR;
545 NS_LOG_DEBUG(
"Found route to " << rtentry->GetDestination() <<
" via nh "
546 << rtentry->GetGateway() <<
" with source addr "
547 << rtentry->GetSource() <<
" and output dev "
548 << rtentry->GetOutputDevice());
552 NS_LOG_DEBUG(
"Click node " << m_nodeName <<
": RouteOutput for dest="
553 << header.GetDestination() <<
" No route to host");
554 sockerr = Socket::ERROR_NOROUTETOHOST;
563 Ipv4ClickRouting::RouteInput(Ptr<const Packet> p,
564 const Ipv4Header& header,
565 Ptr<const NetDevice> idev,
566 UnicastForwardCallback ucb,
567 MulticastForwardCallback mcb,
568 LocalDeliverCallback lcb,
571 NS_FATAL_ERROR(
"Click router does not have a RouteInput() interface!");
576 Ipv4ClickRouting::PrintRoutingTable(Ptr<OutputStreamWrapper> stream,
Time::Unit unit)
const
578 *stream->GetStream() <<
"\nCLICK Routing table printing is not yet implemented, skipping.\n";
582 Ipv4ClickRouting::NotifyInterfaceUp(uint32_t i)
587 Ipv4ClickRouting::NotifyInterfaceDown(uint32_t i)
592 Ipv4ClickRouting::NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress
address)
597 Ipv4ClickRouting::NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress
address)
606 simstrlcpy(
char* buf,
int len,
const std::string& s)
612 if ((
unsigned)len > s.length())
629 const unsigned char*
data,
631 simclick_simpacketinfo* pinfo)
634 << ifid <<
" " <<
type <<
" " <<
data <<
" "
643 ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
645 clickInstance->HandlePacketFromClick(ifid,
type,
data, len);
660 ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode(simnode);
663 case SIMCLICK_VERSION: {
668 case SIMCLICK_SUPPORTS: {
669 int othercmd = va_arg(val,
int);
670 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
674 case SIMCLICK_IFID_FROM_NAME: {
675 const char* ifname = va_arg(val,
const char*);
677 retval = clickInstance->GetInterfaceId(ifname);
680 <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
684 case SIMCLICK_IPADDR_FROM_NAME: {
685 const char* ifname = va_arg(val,
const char*);
686 char* buf = va_arg(val,
char*);
687 int len = va_arg(val,
int);
689 int ifid = clickInstance->GetInterfaceId(ifname);
693 retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId(ifid));
701 <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
705 case SIMCLICK_IPPREFIX_FROM_NAME: {
706 const char* ifname = va_arg(val,
const char*);
707 char* buf = va_arg(val,
char*);
708 int len = va_arg(val,
int);
710 int ifid = clickInstance->GetInterfaceId(ifname);
714 retval = simstrlcpy(buf, len, clickInstance->GetIpPrefixFromInterfaceId(ifid));
722 <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
726 case SIMCLICK_MACADDR_FROM_NAME: {
727 const char* ifname = va_arg(val,
const char*);
728 char* buf = va_arg(val,
char*);
729 int len = va_arg(val,
int);
730 int ifid = clickInstance->GetInterfaceId(ifname);
734 retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId(ifid));
742 <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
746 case SIMCLICK_SCHEDULE: {
747 const struct timeval* when = va_arg(val,
const struct timeval*);
749 clickInstance->HandleScheduleFromClick(when);
752 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" SIMCLICK_SCHEDULE at " << when->tv_sec
753 <<
"s and " << when->tv_usec <<
"usecs.");
758 case SIMCLICK_GET_NODE_NAME: {
759 char* buf = va_arg(val,
char*);
760 int len = va_arg(val,
int);
761 retval = simstrlcpy(buf, len, clickInstance->GetNodeName());
764 <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
768 case SIMCLICK_IF_PROMISC: {
769 int ifid = va_arg(val,
int);
770 clickInstance->SetPromisc(ifid);
778 case SIMCLICK_IF_READY: {
779 int ifid = va_arg(val,
int);
782 retval = clickInstance->IsInterfaceReady(ifid);
789 case SIMCLICK_TRACE: {
791 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" Received a call for SIMCLICK_TRACE");
795 case SIMCLICK_GET_NODE_ID: {
797 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" Received a call for SIMCLICK_GET_NODE_ID");
801 case SIMCLICK_GET_RANDOM_INT: {
802 uint32_t* randomValue = va_arg(val, uint32_t*);
803 uint32_t maxValue = va_arg(val, uint32_t);
805 *randomValue =
static_cast<uint32_t
>(
806 clickInstance->GetRandomVariable()->GetValue(0.0,
static_cast<double>(maxValue) + 1.0));
808 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" SIMCLICK_RANDOM: " << *randomValue <<
" "
813 case SIMCLICK_GET_DEFINES: {
814 char* buf = va_arg(val,
char*);
815 size_t* size = va_arg(val,
size_t*);
816 uint32_t required = 0;
824 std::map<std::string, std::string> defines = clickInstance->GetDefines();
825 std::map<std::string, std::string>::const_iterator it = defines.begin();
826 while (it != defines.end())
828 size_t available = *size - required;
829 if (it->first.length() + it->second.length() + 2 <= available)
831 simstrlcpy(buf + required, available, it->first);
832 required += it->first.length() + 1;
833 available -= it->first.length() + 1;
834 simstrlcpy(buf + required, available, it->second);
835 required += it->second.length() + 1;
839 required += it->first.length() + it->second.length() + 2;
843 if (required > *size)
static TypeId GetTypeId()
Get the type ID.
Smart pointer class similar to boost::intrusive_ptr.
static Time Now()
Return the current simulation virtual time.
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetPicoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
TypeId SetGroupName(std::string groupName)
Set the group name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
Time Now()
create an ns3::Time instance which contains the current simulation time.
struct simclick_node simclick_node_t
Length::Unit Unit
Save some typing by defining a short alias for Length::Unit.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetIpv4(const char *deviceName, const char *ip, const char *netmask)