ns-3-click support for promisc mode

This commit is contained in:
Ruben Merz
2011-05-27 18:23:09 +02:00
parent b74a99b75e
commit 718ab0af81
5 changed files with 154 additions and 45 deletions
@@ -17,17 +17,23 @@
// Adaptation of examples/udp/udp-client-server.cc for
// Click based nodes running wifi.
//
// Network topology
// Network topology:
//
// (1.4)
// (( n4 ))
//
// 172.16.1.0/24
//
// (1.1) (1.2) (1.3)
// n0 )) (( n1 )) (( n2
// WLAN
//
// - UDP flows from n0 to n1
// - UDP flows from n0 to n1 and n2 to n1.
// - All nodes are Click based.
// - The single ethernet interface that each node
// uses is named 'eth0' in the Click file.
// - Node 4 is running in promiscuous mode and can listen in on
// the packets being exchanged between n0-n1 and n2-n1.
//
#include <fstream>
@@ -59,16 +65,6 @@ WriteArp (Ptr<Ipv4ClickRouting> clickRouter)
// Access the handler
NS_LOG_INFO (clickRouter->WriteHandler ("wifi/arpquerier", "insert", "172.16.1.2 00:00:00:00:00:02"));
}
void SetPromisc (Ptr<Ipv4ClickRouting> clickRouter)
{
// 4th node can listen to traffic in promisc mode
// Note: Promiscuous mode support for Click has
// been added ahead of the official Wifi support
// for promiscuous mode. Thus, the below line will
// not work until then.
clickRouter->SetPromiscuous ("eth0");
}
#endif
int
@@ -142,7 +138,14 @@ main (int argc, char *argv[])
// Install Click on the nodes
//
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (n, "src/click/examples/nsclick-wifi-single-interface.click");
clickinternet.SetClickFile (n.Get (0), "src/click/examples/nsclick-wifi-single-interface.click");
clickinternet.SetClickFile (n.Get (1), "src/click/examples/nsclick-wifi-single-interface.click");
clickinternet.SetClickFile (n.Get (2), "src/click/examples/nsclick-wifi-single-interface.click");
// Node 4 is to run in promiscuous mode. This can be verified
// from the pcap trace Node4_in_eth0.pcap generated after running
// this script.
clickinternet.SetClickFile (n.Get (3), "src/click/examples/nsclick-wifi-single-interface-promisc.click");
clickinternet.SetRoutingTableElement (n, "rt");
clickinternet.Install (n);
Ipv4AddressHelper ipv4;
@@ -180,9 +183,6 @@ main (int argc, char *argv[])
wifiPhy.EnablePcap ("nsclick-udp-client-server-wifi", d);
// Call SetPromiscuous mode on Click Router for node 4
Simulator::Schedule (Seconds (0.1), &SetPromisc, n.Get (3)->GetObject<Ipv4ClickRouting> ());
// Force the MAC address of the second node: The current ARP
// implementation of Click sends only one ARP request per incoming
// packet for an unknown destination and does not retransmit if no
@@ -0,0 +1,114 @@
// nsclick-wifi-single-interface.click
//
// Copyright (c) 2011, Deutsche Telekom Laboratories
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version
// 2 as published by the Free Software Foundation;
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Author: Ruben Merz <ruben@net.t-labs.tu-berlin.de>
//
// This is a single host Click configuration for wifi.
// Sets the interface in promiscuous mode
// The node broadcasts ARP requests if it wants to find a destination
// address, and it responds to ARP requests made for it.
elementclass WiFiSimHost {
$ipaddr, $hwaddr |
cl::Classifier(12/0806 20/0001,12/0806 20/0002, -);
forhost::IPClassifier(dst host $ipaddr,-);
arpquerier::ARPQuerier(eth0);
arpresponder::ARPResponder(eth0);
ethout::Queue
-> ToDump(out_eth0.pcap,PER_NODE 1)
-> ToSimDevice(eth0);
// All packets received on eth0 are silently
// dropped if they are destined for another location
FromSimDevice(eth0,4096, PROMISC true)
-> ToDump(in_eth0.pcap,PER_NODE 1,ENCAP ETHER)
-> cl;
// ARP queries from other nodes go to the ARP responder element
cl[0] -> arpresponder;
// ARP responses go to our ARP query element
cl[1] -> [1]arpquerier;
// All other packets get checked whether they are meant for us
cl[2]
-> Strip (14)
-> CheckIPHeader2
-> MarkIPHeader
-> GetIPAddress(16) // Sets destination IP address annotation from packet data
-> forhost;
// Packets for us are pushed outside
forhost[0]
->[0]output;
// Packets for other folks or broadcast packets get sent to output 1
forhost[1]
-> ToDump(discard.pcap,2000,PER_NODE 1,ENCAP IP)
-> [1]output;
// Incoming packets get pushed into the ARP query module
input[0]
-> arpquerier;
// Both the ARP query and response modules send data out to
// the simulated network device, eth0.
arpquerier
-> ToDump(out_arpquery.pcap,PER_NODE 1)
-> ethout;
arpresponder
-> ToDump(out_arprespond.pcap,PER_NODE 1)
-> ethout;
}
elementclass TapSimHost {
$dev |
// Packets go to "tap0" which sends them to the kernel
input[0]
-> ToDump(tokernel.pcap,2000,IP,PER_NODE 1)
-> ToSimDevice($dev,IP);
// Packets sent out by the "kernel" get pushed outside
FromSimDevice($dev,4096)
-> CheckIPHeader2
-> ToDump(fromkernel.pcap,2000,IP,PER_NODE 1)
-> GetIPAddress(16)
-> [0]output;
}
// Instantiate elements
wifi::WiFiSimHost(eth0:ip,eth0:eth);
kernel::TapSimHost(tap0);
// Users can do some processing between the two elements
wifi[0] -> kernel;
kernel -> wifi;
// Packets not for us are discarded
wifi[1] -> Discard;
// It is mandatory to use an IPRouteTable element with ns-3-click
// (but we do not use it in this example)
rt :: LinearIPLookup (172.16.1.0/24 0.0.0.0 1);
// We are actually not using the routing table
Idle () -> rt;
rt[0] -> Discard;
rt[1] -> Discard;
+13 -6
View File
@@ -388,14 +388,11 @@ Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName
}
void
Ipv4ClickRouting::SetPromiscuous (std::string ifName)
Ipv4ClickRouting::SetPromisc (int ifid)
{
Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
NS_ASSERT (ipv4l3);
// Interface ethN gets index 1+N, but netdevice will start at 0
// To ensure this, install a Click stack on a node only after
// all NetDevices have been installed.
ipv4l3->SetPromisc (GetInterfaceId (ifName.c_str ()) - 1);
NS_ASSERT(ipv4l3);
ipv4l3->SetPromisc (ifid);
}
Ptr<Ipv4Route>
@@ -628,6 +625,16 @@ int simclick_sim_command (simclick_node_t *simnode, int cmd, ...)
break;
}
case SIMCLICK_IF_PROMISC:
{
int ifid = va_arg(val, int);
clickInstance->SetPromisc (ifid);
retval = 0;
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_PROMISC: " << ifid << " " << ns3::Simulator::Now ());
break;
}
case SIMCLICK_IF_READY:
{
int ifid = va_arg (val, int); // Commented out so that optimized build works
+2 -1
View File
@@ -108,7 +108,8 @@ public:
*
* \brief Sets an interface to run on promiscuous mode.
*/
void SetPromiscuous (std::string ifName);
void SetPromisc (int ifid);
private:
simclick_node_t *m_simNode;
+9 -22
View File
@@ -574,35 +574,22 @@ Ipv4L3ClickProtocol::SetForwarding (uint32_t i, bool val)
void
Ipv4L3ClickProtocol::SetPromisc (uint32_t i)
{
NS_ASSERT (i <= m_node->GetNDevices ());
if (i > m_promiscDeviceList.size ())
{
m_promiscDeviceList.resize (i);
}
std::vector<bool>::iterator it = m_promiscDeviceList.begin ();
std::advance (it, i);
m_promiscDeviceList.insert (it, true);
NS_ASSERT(i <= m_node->GetNDevices ());
Ptr<NetDevice> netdev = GetNetDevice (i);
NS_ASSERT (netdev);
Ptr<Node> node = GetObject<Node> ();
NS_ASSERT (node);
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
0, netdev,true);
}
uint32_t
Ipv4L3ClickProtocol::AddInterface (Ptr<NetDevice> device)
{
NS_LOG_FUNCTION (this << &device);
Ptr<Node> node = GetObject<Node> ();
NS_LOG_DEBUG ("Size:" << m_promiscDeviceList.size () << " Interface index" << device->GetIfIndex ());
if (m_promiscDeviceList.size () > 0
&& (m_promiscDeviceList.size () >= device->GetIfIndex ())
&& (m_promiscDeviceList[device->GetIfIndex ()]))
{
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
0, device,true);
}
else
{
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
Ipv4L3ClickProtocol::PROT_NUMBER, device);
}
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
Ipv4L3ClickProtocol::PROT_NUMBER, device);
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
ArpL3Protocol::PROT_NUMBER, device);