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 
   50std::map<simclick_node_t*, Ptr<Ipv4ClickRouting>> Ipv4ClickRouting::m_clickInstanceFromSimNode;
 
   55    static TypeId tid = TypeId(
"ns3::Ipv4ClickRouting")
 
   57                            .AddConstructor<Ipv4ClickRouting>()
 
   63Ipv4ClickRouting::Ipv4ClickRouting()
 
   64    : m_nonDefaultName(false),
 
   67    m_random = CreateObject<UniformRandomVariable>();
 
   69    timerclear(&m_simNode->curtime);
 
   71    AddSimNodeToClickMapping();
 
   74Ipv4ClickRouting::~Ipv4ClickRouting()
 
   79Ipv4ClickRouting::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);
 
  115Ptr<UniformRandomVariable>
 
  116Ipv4ClickRouting::GetRandomVariable()
 
  122Ipv4ClickRouting::DoDispose()
 
  124    if (m_clickInitialised)
 
  126        simclick_click_kill(m_simNode);
 
  130    Ipv4RoutingProtocol::DoDispose();
 
  134Ipv4ClickRouting::SetClickFile(std::string clickfile)
 
  136    m_clickFile = clickfile;
 
  140Ipv4ClickRouting::SetDefines(std::map<std::string, std::string> defines)
 
  145std::map<std::string, std::string>
 
  146Ipv4ClickRouting::GetDefines()
 
  152Ipv4ClickRouting::SetClickRoutingTableElement(std::string name)
 
  154    m_clickRoutingTableElement = name;
 
  158Ipv4ClickRouting::SetNodeName(std::string name)
 
  161    m_nonDefaultName = 
true;
 
  165Ipv4ClickRouting::GetNodeName()
 
  171Ipv4ClickRouting::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())
 
  228Ipv4ClickRouting::IsInterfaceReady(
int ifid)
 
  230    if (ifid >= 0 && ifid < (
int)m_ipv4->GetNInterfaces())
 
  241Ipv4ClickRouting::GetIpAddressFromInterfaceId(
int ifid)
 
  243    std::stringstream addr;
 
  244    m_ipv4->GetAddress(ifid, 0).GetLocal().Print(addr);
 
  250Ipv4ClickRouting::GetIpPrefixFromInterfaceId(
int ifid)
 
  252    std::stringstream addr;
 
  253    m_ipv4->GetAddress(ifid, 0).GetMask().Print(addr);
 
  259Ipv4ClickRouting::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);
 
  271Ipv4ClickRouting::AddSimNodeToClickMapping()
 
  273    m_clickInstanceFromSimNode.insert(std::make_pair(m_simNode, 
this));
 
  279    return m_clickInstanceFromSimNode[simnode];
 
  283Ipv4ClickRouting::GetTimevalFromNow() const
 
  285    struct timeval curtime;
 
  286    uint64_t remainder = 0;
 
  309        if (curtime.tv_usec == 1000000)
 
  320Ipv4ClickRouting::RunClickEvent()
 
  322    m_simNode->curtime = GetTimevalFromNow();
 
  324    NS_LOG_DEBUG(
"RunClickEvent at " << m_simNode->curtime.tv_sec << 
" " 
  326    simclick_click_run(m_simNode);
 
  330Ipv4ClickRouting::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);
 
  343Ipv4ClickRouting::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);
 
  374Ipv4ClickRouting::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);
 
  415Ipv4ClickRouting::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);
 
  443Ipv4ClickRouting::ReadHandler(std::string elementName, std::string handlerName)
 
  445    char* handle = simclick_click_read_handler(m_simNode,
 
  450    std::string ret(handle);
 
  461Ipv4ClickRouting::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());
 
  480Ipv4ClickRouting::SetPromisc(
int ifid)
 
  482    Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol>(m_ipv4);
 
  484    ipv4l3->SetPromisc(ifid);
 
  488Ipv4ClickRouting::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;
 
  563Ipv4ClickRouting::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!");
 
  576Ipv4ClickRouting::PrintRoutingTable(Ptr<OutputStreamWrapper> stream, 
Time::Unit unit)
 const 
  578    *stream->GetStream() << 
"\nCLICK Routing table printing is not yet implemented, skipping.\n";
 
  582Ipv4ClickRouting::NotifyInterfaceUp(
uint32_t i)
 
  587Ipv4ClickRouting::NotifyInterfaceDown(
uint32_t i)
 
  592Ipv4ClickRouting::NotifyAddAddress(
uint32_t interface, Ipv4InterfaceAddress 
address)
 
  597Ipv4ClickRouting::NotifyRemoveAddress(
uint32_t interface, Ipv4InterfaceAddress 
address)
 
  606simstrlcpy(
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: {
 
  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*);
 
  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)