13#include "ns3/ipv4-interface.h"
15#include "ns3/mac48-address.h"
17#include "ns3/random-variable-stream.h"
18#include "ns3/simulator.h"
20#include <click/simclick.h>
32#define INTERFACE_ID_KERNELTAP 0
33#define INTERFACE_ID_FIRST 1
34#define INTERFACE_ID_FIRST_DROP 33
45 .AddConstructor<Ipv4ClickRouting>()
46 .SetGroupName(
"Click");
52 : m_nonDefaultName(false),
73 std::stringstream name;
133std::map<std::string, std::string>
175 if (strstr(ifname,
"tap") || strstr(ifname,
"tun"))
179 else if (
const char* devname = strstr(ifname,
"eth"))
181 while (*devname && !isdigit((
unsigned char)*devname))
191 else if (
const char* devname = strstr(ifname,
"drop"))
193 while (*devname && !isdigit((
unsigned char)*devname))
224 std::stringstream addr;
233 std::stringstream addr;
242 std::stringstream addr;
245 Address devAddr = device->GetAddress();
266 struct timeval curtime;
267 uint64_t remainder = 0;
269 Time now = Simulator::Now();
274 switch (Time::GetResolution())
292 if (curtime.tv_usec == 1000000)
315 NS_LOG_DEBUG(
"HandleScheduleFromClick at " << when->tv_sec <<
" " << when->tv_usec <<
" "
335 NS_LOG_DEBUG(
"Incoming packet from tap0. Sending Packet up the stack.");
341 p->RemoveHeader(ipHeader);
343 ipv4l3->LocalDeliver(p, ipHeader, (
uint32_t)ifid);
347 NS_LOG_DEBUG(
"Incoming packet from eth" << ifid - 1 <<
" of type " << ptype
348 <<
". Sending packet down the stack.");
364 simclick_simpacketinfo pinfo;
368 simclick_click_send(
m_simNode, ifid, ptype,
data, len, &pinfo);
387 int len = p->GetSize();
388 auto buf =
new uint8_t[len];
389 p->CopyData(buf, len);
415 int len = p->GetSize();
416 auto buf =
new uint8_t[len];
417 p->CopyData(buf, len);
428 char* handle = simclick_click_read_handler(
m_simNode,
433 std::string ret(handle);
445 std::string handlerName,
446 std::string writeString)
448 int r = simclick_click_write_handler(
m_simNode,
451 writeString.c_str());
467 ipv4l3->SetPromisc(ifid);
478 std::stringstream addr;
483 NS_LOG_DEBUG(
"Probe click routing table for " << addr.str());
487 size_t pos = s.find(
' ');
490 if (pos == std::string::npos)
494 interfaceId = atoi(s.c_str());
495 NS_LOG_DEBUG(
"case 1: destination " << destination <<
" interfaceId " << interfaceId);
499 interfaceId = atoi(s.substr(0, pos).c_str());
500 Ipv4Address destination(s.substr(pos + 1).c_str());
501 NS_LOG_DEBUG(
"case 2: destination " << destination <<
" interfaceId " << interfaceId);
504 if (interfaceId != -1)
515 if (numOifAddresses == 1)
524 rtentry->SetSource(ifAddr.
GetLocal());
525 rtentry->SetGateway(destination);
528 NS_LOG_DEBUG(
"Found route to " << rtentry->GetDestination() <<
" via nh "
529 << rtentry->GetGateway() <<
" with source addr "
530 << rtentry->GetSource() <<
" and output dev "
531 << rtentry->GetOutputDevice());
554 NS_FATAL_ERROR(
"Click router does not have a RouteInput() interface!");
561 *stream->GetStream() <<
"\nCLICK Routing table printing is not yet implemented, skipping.\n";
595 if ((
unsigned)len > s.length())
612 const unsigned char*
data,
614 simclick_simpacketinfo* pinfo)
617 << ifid <<
" " << type <<
" " <<
data <<
" "
628 clickInstance->HandlePacketFromClick(ifid, type,
data, len);
646 case SIMCLICK_VERSION: {
651 case SIMCLICK_SUPPORTS: {
652 int othercmd = va_arg(val,
int);
653 retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES);
657 case SIMCLICK_IFID_FROM_NAME: {
658 const char* ifname = va_arg(val,
const char*);
660 retval = clickInstance->GetInterfaceId(ifname);
663 <<
" SIMCLICK_IFID_FROM_NAME: " << ifname <<
" " << retval);
667 case SIMCLICK_IPADDR_FROM_NAME: {
668 const char* ifname = va_arg(val,
const char*);
669 char* buf = va_arg(val,
char*);
670 int len = va_arg(val,
int);
672 int ifid = clickInstance->GetInterfaceId(ifname);
676 retval =
simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId(ifid));
684 <<
" SIMCLICK_IPADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
688 case SIMCLICK_IPPREFIX_FROM_NAME: {
689 const char* ifname = va_arg(val,
const char*);
690 char* buf = va_arg(val,
char*);
691 int len = va_arg(val,
int);
693 int ifid = clickInstance->GetInterfaceId(ifname);
697 retval =
simstrlcpy(buf, len, clickInstance->GetIpPrefixFromInterfaceId(ifid));
705 <<
" SIMCLICK_IPPREFIX_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
709 case SIMCLICK_MACADDR_FROM_NAME: {
710 const char* ifname = va_arg(val,
const char*);
711 char* buf = va_arg(val,
char*);
712 int len = va_arg(val,
int);
713 int ifid = clickInstance->GetInterfaceId(ifname);
717 retval =
simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId(ifid));
725 <<
" SIMCLICK_MACADDR_FROM_NAME: " << ifname <<
" " << buf <<
" " << len);
729 case SIMCLICK_SCHEDULE: {
730 const struct timeval* when = va_arg(val,
const struct timeval*);
732 clickInstance->HandleScheduleFromClick(when);
735 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" SIMCLICK_SCHEDULE at " << when->tv_sec
736 <<
"s and " << when->tv_usec <<
"usecs.");
741 case SIMCLICK_GET_NODE_NAME: {
742 char* buf = va_arg(val,
char*);
743 int len = va_arg(val,
int);
744 retval =
simstrlcpy(buf, len, clickInstance->GetNodeName());
747 <<
" SIMCLICK_GET_NODE_NAME: " << buf <<
" " << len);
751 case SIMCLICK_IF_PROMISC: {
752 int ifid = va_arg(val,
int);
753 clickInstance->SetPromisc(ifid);
761 case SIMCLICK_IF_READY: {
762 int ifid = va_arg(val,
int);
765 retval = clickInstance->IsInterfaceReady(ifid);
772 case SIMCLICK_TRACE: {
774 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" Received a call for SIMCLICK_TRACE");
778 case SIMCLICK_GET_NODE_ID: {
780 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" Received a call for SIMCLICK_GET_NODE_ID");
784 case SIMCLICK_GET_RANDOM_INT: {
788 *randomValue =
static_cast<uint32_t>(
789 clickInstance->GetRandomVariable()->GetValue(0.0,
static_cast<double>(maxValue) + 1.0));
791 NS_LOG_DEBUG(clickInstance->GetNodeName() <<
" SIMCLICK_RANDOM: " << *randomValue <<
" "
796 case SIMCLICK_GET_DEFINES: {
797 char* buf = va_arg(val,
char*);
798 size_t* size = va_arg(val,
size_t*);
807 std::map<std::string, std::string> defines = clickInstance->GetDefines();
809 for (
auto it = defines.begin(); it != defines.end(); it++)
811 size_t available = *size - required;
812 if (it->first.length() + it->second.length() + 2 <= available)
814 simstrlcpy(buf + required, available, it->first);
815 required += it->first.length() + 1;
816 available -= it->first.length() + 1;
817 simstrlcpy(buf + required, available, it->second);
818 required += it->second.length() + 1;
822 required += it->first.length() + it->second.length() + 2;
825 if (required > *size)
a polymophic address class
Ipv4 addresses are stored in host order in this class.
void Print(std::ostream &os) const
Print this address to the given output stream.
Class to allow a node to use Click for external routing.
void SetDefines(std::map< std::string, std::string > defines)
Click defines to be used by the node's Click Instance.
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
std::string GetIpAddressFromInterfaceId(int ifid)
Provides for SIMCLICK_IPADDR_FROM_NAME.
void RunClickEvent()
This method has to be scheduled every time Click calls SIMCLICK_SCHEDULE.
Ipv4ClickRouting()
Constructor.
simclick_node_t * m_simNode
Pointer to the simclick node.
bool IsInterfaceReady(int ifid)
Provides for SIMCLICK_IF_READY.
int WriteHandler(std::string elementName, std::string handlerName, std::string writeString)
Write Handler interface for a node's Click Elements.
void AddSimNodeToClickMapping()
Used internally in DoInitialize () to Add a mapping to m_clickInstanceFromSimNode mapping.
bool m_clickInitialised
Whether click has been initialized.
void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address) override
void SetPromisc(int ifid)
Sets an interface to run on promiscuous mode.
void DoDispose() override
Destructor implementation.
std::string m_nodeName
Name of the node.
void DoInitialize() override
Initialize() implementation.
std::string GetMacAddressFromInterfaceId(int ifid)
Provides for SIMCLICK_MACADDR_FROM_NAME.
void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address) override
bool m_nonDefaultName
Whether a non-default name has been set.
void Send(Ptr< Packet > p, Ipv4Address src, Ipv4Address dest)
Allow a higher layer to send data through Click.
~Ipv4ClickRouting() override
Ptr< Ipv4 > m_ipv4
Pointer to the IPv4 object.
void NotifyInterfaceDown(uint32_t interface) override
struct timeval GetTimevalFromNow() const
Get current simulation time as a timeval.
std::map< std::string, std::string > GetDefines()
Provides for SIMCLICK_GET_DEFINES.
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
void SetClickFile(std::string clickfile)
Click configuration file to be used by the node's Click Instance.
Ptr< UniformRandomVariable > m_random
Uniform random variable.
int GetInterfaceId(const char *ifname)
Provides for SIMCLICK_IFID_FROM_NAME.
void SetIpv4(Ptr< Ipv4 > ipv4) override
Set the Ipv4 instance to be used.
std::map< std::string, std::string > m_defines
Defines for .click configuration file parsing.
void SendPacketToClick(int ifid, int type, const unsigned char *data, int len)
Sends a packet to Click.
static Ptr< Ipv4ClickRouting > GetClickInstanceFromSimNode(simclick_node_t *simnode)
Allows the Click service methods, which reside outside Ipv4ClickRouting, to get the required Ipv4Clic...
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
std::string m_clickFile
Name of .click configuration file.
std::string ReadHandler(std::string elementName, std::string handlerName)
Read Handler interface for a node's Click Elements.
static TypeId GetTypeId()
Get type ID.
void HandleScheduleFromClick(const struct timeval *when)
Schedules simclick_click_run to run at the given time.
static std::map< simclick_node_t *, Ptr< Ipv4ClickRouting > > m_clickInstanceFromSimNode
Provide a mapping between the node reference used by Click and the corresponding Ipv4ClickRouting ins...
std::string GetIpPrefixFromInterfaceId(int ifid)
Provides for SIMCLICK_IPPREFIX_FROM_NAME.
void HandlePacketFromClick(int ifid, int type, const unsigned char *data, int len)
Receives a packet from Click.
void SetClickRoutingTableElement(std::string name)
Name of the routing table element being used by Click.
void SetNodeName(std::string name)
Name of the node as to be used by Click.
Ptr< UniformRandomVariable > GetRandomVariable()
Get the uniform random variable.
void Receive(Ptr< Packet > p, Mac48Address receiverAddr, Mac48Address dest)
Allow a lower layer to send data to Click.
std::string GetNodeName()
Provides for SIMCLICK_GET_NODE_NAME.
void NotifyInterfaceUp(uint32_t interface) override
std::string m_clickRoutingTableElement
Name of the routing table element.
virtual uint32_t GetNAddresses(uint32_t interface) const =0
virtual Ipv4InterfaceAddress GetAddress(uint32_t interface, uint32_t addressIndex) const =0
Because addresses can be removed, the addressIndex is not guaranteed to be static across calls to thi...
virtual Ptr< NetDevice > GetNetDevice(uint32_t interface)=0
virtual uint32_t GetNInterfaces() const =0
a class to store IPv4 address information on an interface
Ipv4Mask GetMask() const
Get the network mask.
Ipv4Address GetLocal() const
Get the local address.
void Print(std::ostream &os) const
Print this mask to the given output stream.
Abstract base class for IPv4 routing protocols.
static Mac48Address ConvertFrom(const Address &address)
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
virtual void DoDispose()
Destructor implementation.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
SocketErrno
Enumeration of the possible errors returned by a socket.
Simulation virtual time values and global simulation resolution.
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.
Unit
The unit to use to interpret a number representing time.
int64_t GetPicoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
static Time FromInteger(uint64_t value, Unit unit)
Create a Time equal to value in unit unit.
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#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 ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
int simclick_sim_send(simclick_node_t *simnode, int ifid, int type, const unsigned char *data, int len, simclick_simpacketinfo *pinfo)
int simclick_sim_command(simclick_node_t *simnode, int cmd,...)
#define INTERFACE_ID_FIRST
#define INTERFACE_ID_FIRST_DROP
static int simstrlcpy(char *buf, int len, const std::string &s)
struct simclick_node simclick_node_t
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.