Md Rackybul Hashan
unread,Apr 2, 2025, 8:06:18 AMApr 2Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to ofswitch13-users
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/ofswitch13-module.h"
#include "ns3/csma-module.h"
#include "ns3/applications-module.h"
using namespace ns3;
static inline struct ofl_match_tlv*
oxm_match_lookup(uint32_t oxm, struct ofl_match *match) {
struct ofl_match_tlv *tlv;
HMAP_FOR_EACH (tlv, struct ofl_match_tlv, hmap_node, &match->match_fields) {
if (ntohl(tlv->header) >> 16 == oxm) {
return tlv;
}
}
return NULL;
}
class TTLController : public OFSwitch13Controller
{
public:
static TypeId GetTypeId(void)
{
static TypeId tid = TypeId("TTLController")
.SetParent<OFSwitch13Controller>()
.AddConstructor<TTLController>();
return tid;
}
void InstallFlowRule(Ptr<OFSwitch13Device> swtch)
{
std::ostringstream cmd;
// <<< Fix spot: Correct syntax to "output:controller"
cmd << "flow-mod cmd=add,table=0 eth_type=0x0800 output:controller";
DpctlExecute(swtch->GetDatapathId(), cmd.str());
std::cout << "Installed flow rule: IPv4 packets to controller" << std::endl;
}
protected:
void SendIcmpTimeExceeded(Ptr<const RemoteSwitch> swtch, Ptr<Packet> packet, uint32_t inPort) {
Ipv4Header ipHeader;
packet->PeekHeader(ipHeader);
Ipv4Address srcAddr = ipHeader.GetSource();
Ptr<OFSwitch13Device> switchDev = OFSwitch13Device::GetDevice(swtch->GetDpId());
Ptr<Node> switchNode = switchDev->GetObject<Node>();
Ptr<Ipv4> ipv4 = switchNode->GetObject<Ipv4>();
// FIX: Use interface index 0 instead of 1
Ipv4Address switchIp = ipv4->GetAddress(0, 0).GetLocal(); // <<< Critical fix here
Icmpv4TimeExceeded icmp;
icmp.SetData(packet);
Ptr<Packet> icmpPkt = Create<Packet>();
icmpPkt->AddHeader(icmp);
Ipv4Header icmpIpHeader;
icmpIpHeader.SetSource(switchIp);
icmpIpHeader.SetDestination(srcAddr);
icmpIpHeader.SetProtocol(1);
icmpIpHeader.SetTtl(64);
icmpIpHeader.SetPayloadSize(icmpPkt->GetSize());
icmpPkt->AddHeader(icmpIpHeader);
struct ofl_msg_packet_out outMsg;
memset(&outMsg, 0, sizeof(outMsg));
outMsg.header.type = OFPT_PACKET_OUT;
outMsg.buffer_id = OFP_NO_BUFFER;
outMsg.in_port = inPort;
struct ofl_action_output* action = (struct ofl_action_output*)xmalloc(sizeof(struct ofl_action_output));
action->header.type = OFPAT_OUTPUT;
action->port = OFPP_CONTROLLER;
action->max_len = 0;
outMsg.actions_num = 1;
outMsg.actions = (struct ofl_action_header**)&action;
uint8_t* icmpBuffer = new uint8_t[icmpPkt->GetSize()];
icmpPkt->CopyData(icmpBuffer, icmpPkt->GetSize());
outMsg.data = icmpBuffer;
outMsg.data_length = icmpPkt->GetSize();
SendToSwitch(swtch, (struct ofl_msg_header*)&outMsg, 0);
delete[] icmpBuffer;
free(action);
}
ofl_err HandlePacketIn(
struct ofl_msg_packet_in *msg,
Ptr<const RemoteSwitch> swtch,
uint32_t xid) override
{
Ptr<Packet> packet = Create<Packet>(msg->data, msg->data_length);
Ipv4Header ipHeader;
// Extract input port from match fields
uint32_t inPort = 0;
struct ofl_match* match = (struct ofl_match*)msg->match;
struct ofl_match_tlv* tlv = oxm_match_lookup(OFPXMT_OFB_IN_PORT, match);
if (tlv) {
inPort = ntohl(*((uint32_t*)tlv->value));
}
if (packet->RemoveHeader(ipHeader))
{
uint8_t ttl = ipHeader.GetTtl();
if (ttl <= 1)
{
SendIcmpTimeExceeded(swtch, packet, inPort);
return 0;
}
// Decrement TTL and forward
ipHeader.SetTtl(ttl - 1);
packet->AddHeader(ipHeader);
// Simple forwarding logic
uint32_t outPort = (ipHeader.GetDestination() == Ipv4Address("10.1.1.2")) ? 2 : 1;
struct ofl_msg_packet_out outMsg;
memset(&outMsg, 0, sizeof(outMsg));
outMsg.header.type = OFPT_PACKET_OUT;
outMsg.buffer_id = OFP_NO_BUFFER;
outMsg.in_port = inPort;
struct ofl_action_output* action = (struct ofl_action_output*)xmalloc(sizeof(struct ofl_action_output));
action->header.type = OFPAT_OUTPUT;
action->port = outPort;
action->max_len = 0;
outMsg.actions_num = 1;
outMsg.actions = (struct ofl_action_header**)&action;
uint8_t* buffer = new uint8_t[packet->GetSize()];
packet->CopyData(buffer, packet->GetSize());
outMsg.data = buffer;
outMsg.data_length = packet->GetSize();
SendToSwitch(swtch, (struct ofl_msg_header*)&outMsg, xid);
delete[] buffer;
free(action);
}
return 0;
}
};
class CustomTraceroute : public Application
{
public:
static TypeId GetTypeId(void)
{
static TypeId tid = TypeId("CustomTraceroute")
.SetParent<Application>()
.AddConstructor<CustomTraceroute>()
.AddAttribute("Remote",
"Destination address",
Ipv4AddressValue(),
MakeIpv4AddressAccessor(&CustomTraceroute::m_remote),
MakeIpv4AddressChecker())
.AddAttribute("MaxTtl",
"Maximum TTL",
UintegerValue(5),
MakeUintegerAccessor(&CustomTraceroute::m_maxTtl),
MakeUintegerChecker<uint32_t>())
.AddAttribute("Interval",
"Probing interval",
TimeValue(Seconds(1)),
MakeTimeAccessor(&CustomTraceroute::m_interval),
MakeTimeChecker());
return tid;
}
CustomTraceroute() : m_socket(0), m_seq(0) {}
virtual ~CustomTraceroute() {}
protected:
virtual void DoDispose(void)
{
if (m_socket) m_socket->Close();
Application::DoDispose();
}
virtual void StartApplication(void)
{
m_socket = Socket::CreateSocket(GetNode(), TypeId::LookupByName("ns3::Ipv4RawSocketFactory"));
m_socket->SetAttribute("Protocol", UintegerValue(1)); // ICMP
m_socket->SetRecvCallback(MakeCallback(&CustomTraceroute::HandleRead, this));
Simulator::Schedule(Seconds(0), &CustomTraceroute::SendProbe, this, 1);
}
virtual void StopApplication(void)
{
if (m_socket) m_socket->Close();
}
private:
void SendProbe(uint8_t ttl)
{
if (ttl > m_maxTtl)
{
std::cout << "Traceroute complete" << std::endl;
return;
}
Ptr<Packet> p = Create<Packet>();
Icmpv4Echo echo;
echo.SetSequenceNumber(m_seq++);
echo.SetIdentifier(0);
p->AddHeader(echo);
Icmpv4Header icmp;
icmp.SetType(Icmpv4Header::ICMPV4_ECHO);
icmp.SetCode(0);
p->AddHeader(icmp);
m_socket->SetIpTtl(ttl);
m_socket->SendTo(p, 0, InetSocketAddress(m_remote, 0));
std::cout << "Sent probe with TTL=" << (int)ttl << std::endl;
Simulator::Schedule(m_interval, &CustomTraceroute::SendProbe, this, ttl + 1);
}
void HandleRead(Ptr<Socket> socket)
{
Ptr<Packet> packet = socket->Recv();
Ipv4Header ipHeader;
Icmpv4Header icmpHeader;
packet->RemoveHeader(ipHeader);
packet->PeekHeader(icmpHeader);
if (icmpHeader.GetType() == Icmpv4Header::ICMPV4_TIME_EXCEEDED)
{
Icmpv4TimeExceeded timeExceeded;
packet->RemoveHeader(timeExceeded);
// Extract original IP header from payload
Ipv4Header originalIpHeader;
if (packet->PeekHeader(originalIpHeader))
{
std::cout << "Hop " << (int)originalIpHeader.GetTtl()
<< ": " << ipHeader.GetSource()
<< " (ICMP Time Exceeded)" << std::endl;
}
}
else if (icmpHeader.GetType() == Icmpv4Header::ICMPV4_ECHO_REPLY)
{
std::cout << "Destination reached: " << ipHeader.GetSource() << std::endl;
}
}
Ptr<Socket> m_socket;
Ipv4Address m_remote;
uint32_t m_maxTtl;
Time m_interval;
uint16_t m_seq;
};
int main(int argc, char* argv[])
{
uint16_t simTime = 10;
bool verbose = false;
bool trace = false;
CommandLine cmd;
cmd.AddValue("simTime", "Simulation time", simTime);
cmd.AddValue("verbose", "Enable verbose", verbose);
cmd.AddValue("trace", "Enable tracing", trace);
cmd.Parse(argc, argv);
if (verbose)
{
OFSwitch13Helper::EnableDatapathLogs();
LogComponentEnable("CustomTraceroute", LOG_LEVEL_ALL);
}
// Create nodes
NodeContainer hosts;
hosts.Create(2);
Ptr<Node> switchNode = CreateObject<Node>();
Ptr<Node> controllerNode = CreateObject<Node>();
// Create CSMA links
CsmaHelper csmaHelper;
csmaHelper.SetChannelAttribute("DataRate", StringValue("100Mbps"));
csmaHelper.SetChannelAttribute("Delay", StringValue("2ms"));
NetDeviceContainer hostDevices, switchPorts;
for (uint32_t i = 0; i < hosts.GetN(); i++) {
NetDeviceContainer link = csmaHelper.Install(NodeContainer(hosts.Get(i), switchNode));
hostDevices.Add(link.Get(0));
switchPorts.Add(link.Get(1));
}
// Install OpenFlow
Ptr<OFSwitch13InternalHelper> of13Helper = CreateObject<OFSwitch13InternalHelper>();
Ptr<TTLController> controller = CreateObject<TTLController>();
of13Helper->InstallController(controllerNode, controller);
// <<< Fix spot: Declare switchDevice and assign it
Ptr<OFSwitch13Device> switchDevice = of13Helper->InstallSwitch(switchNode, switchPorts);
controller->InstallFlowRule(switchDevice); // Use the declared switchDevice
of13Helper->CreateOpenFlowChannels();
// Install internet stack
InternetStackHelper internet;
internet.Install(hosts);
internet.Install(switchNode); // Critical for ICMP generation
// Assign IP addresses
Ipv4AddressHelper address;
address.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer hostIfaces = address.Assign(hostDevices);
Ipv4InterfaceContainer switchIfaces = address.Assign(switchPorts); // Critical for switch IP
// Install traceroute on host 0
Ptr<CustomTraceroute> traceroute = CreateObject<CustomTraceroute>();
traceroute->SetAttribute("Remote", Ipv4AddressValue(hostIfaces.GetAddress(1)));
hosts.Get(0)->AddApplication(traceroute);
traceroute->SetStartTime(Seconds(1));
traceroute->SetStopTime(Seconds(simTime));
// Enable tracing
if (trace)
{
csmaHelper.EnablePcap("host", hostDevices);
csmaHelper.EnablePcap("switch", switchPorts);
}
Simulator::Stop(Seconds(simTime));
Simulator::Run();
Simulator::Destroy();
return 0;
} hi im new user of the ns3 and sdn i needs to traceroute to intermediate routing nodes between the host but im getting this error 0$ ./ns3 run scratch/t1
[0/2] Re-checking globbed directories...
[2/2] Linking CXX executable ../build/scratch/ns3.40-t1-default
Installed flow rule: IPv4 packets to controller
Error parsing instruction: output:controller.
Command 'build/scratch/ns3.40-t1-default' returned non-zero exit status 1.