NS-3 Click Integration merge

This commit is contained in:
Lalith Suresh
2011-02-23 17:50:31 +00:00
parent 352348d296
commit 78cbfb976c
21 changed files with 4388 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2010 Lalith Suresh
*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
/**
* \ingroup routing
* \defgroup click Click
*
* \section model Model
*
* This model implements the interface to the Click Modular Router and
* provides the Ipv4ClickRouting class to allow a node to use Click
* for external routing. Unlike normal Ipv4RoutingProtocol sub types,
* Ipv4ClickRouting doesn't use a RouteInput() method, but instead,
* receives a packet on the appropriate interface and processes it
* accordingly. Note that you need to have a routing table type element
* in your Click graph to use Click for external routing. This is needed
* by the RouteOutput() function inherited from Ipv4RoutingProtocol.
* Furthermore, a Click based node uses a different kind of L3 in the
* form of Ipv4L3ClickProtocol, which is a trimmed down version of
* Ipv4L3Protocol. Ipv4L3ClickProtocol passes on packets passing through
* the stack to Ipv4ClickRouting for processing.
*
* \section build Build Instructions
*
* The first step is to build Click. At the top of your Click source directory:
*
* $: ./configure --enable-userlevel --disable-linuxmodule --enable-nsclick --enable-wifi
* $: make
*
* The --enable wifi flag can be skipped in case you don't intend on using
* Click with Wifi.
* *Note: You don't need to do a 'make install'.
*
* Once Click has been built successfully, we proceed to configure ns-3 with
* Click Integration support:
*
* $: ./waf configure --with-nsclick=/path/to/click/source
*
* If it says 'enabled' beside 'NS-3 Click Integration Support', then you're
* good to go.
*
* Next, try running one of the examples:
*
* $: ./waf --run nsclick-simple-lan
*
* You will find a lot of output being generated. This is because of the
* IPPrint and Print elements present in the nsclick-simple-lan.click
* configuration file that the example script uses.
*
* \section clickgraph Click Graph Instructions
*
* The following should be kept in mind when making your Click graph:
* - Only userlevel elements can be used.
* - You will need to replace FromDevice and ToDevice elements
* with FromSimDevice and ToSimDevice elements.
* - Packets to the kernel are sent up using ToSimDevice(tap0,IP).
* - For any node, the 0th device will be tap0. The remaining devices
* should be eth0, eth1 and so forth (even if you're using wifi).
* Please note that the device numbering should begin from 0.
* - A routing table element is a mandatory. The OUTports of the routing
* table element should correspond to the interface number of the device
* through which the packet will ultimately be sent out. Violating this
* rule will lead to really weird packet traces. This routing table element's
* name should then be passed to the Ipv4ClickRouting protocol object as
* a simulation parameter. See the Click examples for details.
* - When using Wifi with ns-3-click, do not use wifi specific elements like
* WifiEncap, ExtraEncap, MadWifiRate etc. for outgoing packets. Incoming
* packets should have their Wifi headers removed using WifiDecap + ExtraDecap
* or Strip elements. See the nsclick-raw-wlan.click file for an idea of the same.
* - The current implementation leaves Click with mainly L3 functionality,
* with ns-3 handling L2. We will soon begin working to support the use of
* MAC protocols on Click as well.
*
* \section usage Usage
*
* To have a node run Click, the easiest way would be to use the ClickInternetStackHelper
* class in your simulation script. For instance:
*
* ClickInternetStackHelper click;
* click.SetClickFile (myNodeContainer, "nsclick-simple-lan.click");
* click.SetRoutingTableElement (myNodeContainer, "u/rt");
* click.Install (myNodeContainer);
*
* The example scripts inside examples/click/ demonstrate the use of Click based
* nodes in different scenarios.
*
*
*/

View File

@@ -0,0 +1,82 @@
// Generated by make-ip-conf.pl
// eth0 172.16.1.2 00:00:00:00:00:02
// eth1 172.16.2.1 00:00:00:00:00:03
elementclass IPRouter {
$myaddr1, $myaddr_ethernet1, $myaddr2, $myaddr_ethernet2 |
// Shared IP input path and routing table
ip :: Strip(14)
-> CheckIPHeader2(INTERFACES 172.16.1.2/255.255.255.0 172.16.2.1/255.255.255.0)
-> rt :: StaticIPLookup(
172.16.1.2/32 0,
172.16.1.255/32 0,
172.16.1.0/32 0,
172.16.2.1/32 0,
172.16.2.255/32 0,
172.16.2.0/32 0,
172.16.1.0/255.255.255.0 1,
172.16.2.0/255.255.255.0 2,
255.255.255.255/32 0.0.0.0 0,
0.0.0.0/32 0,
0.0.0.0/0.0.0.0 18.26.4.1 1);
// ARP responses are copied to each ARPQuerier and the host.
arpt :: Tee(3);
// Input and output paths for eth0
c0 :: Classifier(12/0806 20/0001, 12/0806 20/0002, 12/0800, -);
FromSimDevice(eth0, 4096) -> c0;
out0 :: Queue(200) -> todevice0 :: ToSimDevice(eth0);
c0[0] -> ar0 :: ARPResponder(eth0) -> out0;
arpq0 :: ARPQuerier(eth0) -> out0;
c0[1] -> arpt;
arpt[0] -> [1]arpq0;
c0[2] -> Paint(1) -> ip;
c0[3] -> Discard;
// Input and output paths for eth1
c1 :: Classifier(12/0806 20/0001, 12/0806 20/0002, 12/0800, -);
FromSimDevice(eth1, 4096) -> c1;
out1 :: Queue(200) -> todevice1 :: ToSimDevice(eth1);
c1[0] -> ar1 :: ARPResponder(eth0) -> out1;
arpq1 :: ARPQuerier(eth1) -> out1;
c1[1] -> arpt;
arpt[1] -> [1]arpq1;
c1[2] -> Paint(2) -> ip;
c1[3] -> Discard;
// Local delivery
//toh :: ToSimDevice(tap0,IP);
arpt[2] -> Discard;
rt[0] -> Discard;
// Forwarding path for eth0
rt[1] -> DropBroadcasts
-> cp0 :: PaintTee(1)
-> gio0 :: IPGWOptions($myaddr1)
-> FixIPSrc($myaddr1)
-> dt0 :: DecIPTTL
-> fr0 :: IPFragmenter(1500)
-> [0]arpq0;
dt0[1] -> ICMPError($myaddr1, timeexceeded) -> rt;
fr0[1] -> ICMPError($myaddr1, unreachable, needfrag) -> rt;
gio0[1] -> ICMPError($myaddr1, parameterproblem) -> rt;
cp0[1] -> ICMPError($myaddr1, redirect, host) -> rt;
// Forwarding path for eth1
rt[2] -> DropBroadcasts
-> cp1 :: PaintTee(2)
-> gio1 :: IPGWOptions($myaddr2)
-> FixIPSrc($myaddr2)
-> dt1 :: DecIPTTL
-> fr1 :: IPFragmenter(1500)
-> [0]arpq1;
dt1[1] -> ICMPError($myaddr2, timeexceeded) -> rt;
fr1[1] -> ICMPError($myaddr2, unreachable, needfrag) -> rt;
gio1[1] -> ICMPError($myaddr2, parameterproblem) -> rt;
cp1[1] -> ICMPError($myaddr2, redirect, host) -> rt;
}
u :: IPRouter(eth0,eth0,eth1,eth1);

View File

@@ -0,0 +1,113 @@
// nsclick-lan-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 a LAN.
// The node broadcasts ARP requests if it wants to find a destination
// address, and it responds to ARP requests made for it.
elementclass LanSimHost {
$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)
-> 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
lan::LanSimHost(eth0:ip,eth0:eth);
kernel::TapSimHost(tap0);
// Users can do some processing between the two elements
lan[0] -> kernel;
kernel -> lan;
// Packets for others or broadcasts are discarded
lan[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;

View File

@@ -0,0 +1,142 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
// Scenario: node A (using Click) sends packets to node B (not using
// Click)
//
// (Click) (non-Click)
// A ))) WLAN ((( B
// (172.16.1.1) (172.16.1.2)
// (eth0)
//
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/helper-module.h"
#include "ns3/click-internet-stack-helper.h"
#include "ns3/log.h"
using namespace ns3;
void ReceivePacket (Ptr<Socket> socket)
{
NS_LOG_UNCOND ("Received one packet!");
}
int main (int argc, char *argv[])
{
#ifdef NS3_CLICK
double rss = -80;
Time interPacketInterval = Seconds(1.0);
// Setup nodes
NodeContainer wifiNodes;
wifiNodes.Create (2);
// Get Wifi devices installed on both nodes.
// Adapted from examples/wireless/wifi-simple-adhoc.cc
std::string phyMode ("DsssRate1Mbps");
// disable fragmentation for frames below 2200 bytes
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
// turn off RTS/CTS for frames below 2200 bytes
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
// Fix non-unicast data rate to be the same as that of unicast
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
StringValue (phyMode));
WifiHelper wifi;
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
// This is one parameter that matters when using FixedRssLossModel
// set it to zero; otherwise, gain will be added
wifiPhy.Set ("RxGain", DoubleValue (0) );
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
YansWifiChannelHelper wifiChannel ;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
// The below FixedRssLossModel will cause the rss to be fixed regardless
// of the distance between the two stations, and the transmit power
wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue(rss));
wifiPhy.SetChannel (wifiChannel.Create ());
// Add a non-QoS upper mac, and disable rate control
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue(phyMode),
"ControlMode",StringValue(phyMode));
// Set it to adhoc mode
wifiMac.SetType ("ns3::AdhocWifiMac");
NetDeviceContainer wifiDevices = wifi.Install (wifiPhy, wifiMac, wifiNodes);
// Setup mobility models
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
positionAlloc->Add (Vector (5.0, 0.0, 0.0));
mobility.SetPositionAllocator (positionAlloc);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiNodes);
// Install normal internet stack on node B
InternetStackHelper internet;
internet.Install (wifiNodes.Get (1));
// Install Click on node A
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (wifiNodes.Get (0), "src/routing/click/examples/nsclick-wifi-single-interface.click");
clickinternet.SetRoutingTableElement(wifiNodes.Get (0), "rt");
clickinternet.Install (wifiNodes.Get (0));
// Configure IP addresses
Ipv4AddressHelper ipv4;
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
ipv4.Assign (wifiDevices);
// Setup traffic application and sockets
Address LocalAddress (InetSocketAddress (Ipv4Address::GetAny (), 50000));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", LocalAddress);
ApplicationContainer recvapp = packetSinkHelper.Install (wifiNodes.Get (1));
recvapp.Start (Seconds (5.0));
recvapp.Stop (Seconds (10.0));
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
onOffHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
onOffHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
ApplicationContainer appcont;
AddressValue remoteAddress (InetSocketAddress (Ipv4Address ("172.16.1.2"), 50000));
onOffHelper.SetAttribute ("Remote", remoteAddress);
appcont.Add (onOffHelper.Install (wifiNodes.Get (0)));
appcont.Start (Seconds (5.0));
appcont.Stop (Seconds (10.0));
// For tracing
wifiPhy.EnablePcap ("nsclick-raw-wlan", wifiDevices);
Simulator::Stop (Seconds(20.0));
Simulator::Run();
return 0;
#else
NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in");
#endif
}

View File

@@ -0,0 +1,112 @@
// nsclick-lan-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 a LAN.
// The node broadcasts ARP requests if it wants to find a destination
// address, and it responds to ARP requests made for it.
elementclass LanSimHost {
$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)
-> 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 |
// It is mandatory to use an IPRouteTable element with ns-3-click
rt :: LinearIPLookup (172.16.1.0/24 0.0.0.0 1, 172.16.2.0/24 172.16.1.2 1);
// 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)
-> rt
-> [0]output;
rt[1] -> [0] output;
}
// Instantiate elements
lan::LanSimHost(eth0:ip,eth0:eth);
kernel::TapSimHost(tap0);
// Users can do some processing between the two elements
lan[0] -> kernel;
kernel -> lan;
// Packets for others or broadcasts are discarded
lan[1] -> Discard;

View File

@@ -0,0 +1,112 @@
// nsclick-lan-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 a LAN.
// The node broadcasts ARP requests if it wants to find a destination
// address, and it responds to ARP requests made for it.
elementclass LanSimHost {
$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)
-> 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 |
// It is mandatory to use an IPRouteTable element with ns-3-click
rt :: LinearIPLookup (172.16.2.0/24 0.0.0.0 1,172.16.1.0/24 172.16.1.2 1);
// 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)
-> rt
-> [0]output;
rt[1] -> [0] output;
}
// Instantiate elements
lan::LanSimHost(eth0:ip,eth0:eth);
kernel::TapSimHost(tap0);
// Users can do some processing between the two elements
lan[0] -> kernel;
kernel -> lan;
// Packets for others or broadcasts are discarded
lan[1] -> Discard;

View File

@@ -0,0 +1,134 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
// Network topology
//
//
// 172.16.1.0/24
// (1.1) (1.2) (1.3) (1.4)
//
// eth0 eth0 eth1 eth0
// n0 ========= n1 ========= n2
// LAN 1 LAN 2
//
// - UDP flows from n0 to n2 via n1.
// - All nodes are Click based.
//
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/helper-module.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/ipv4-l3-click-protocol.h"
#include "ns3/click-internet-stack-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("NsclickRouting");
int
main (int argc, char *argv[])
{
#ifdef NS3_CLICK
//
// Enable logging for UdpClient and
//
LogComponentEnable ("NsclickRoutingClient", LOG_LEVEL_INFO);
LogComponentEnable ("NsclickRoutingServer", LOG_LEVEL_INFO);
//
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
NodeContainer n;
n.Create (3);
//
// Install Click on the nodes
//
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (n.Get (0), "src/routing/click/examples/nsclick-routing-node0.click");
clickinternet.SetClickFile (n.Get (1), "src/routing/click/examples/nsclick-ip-router.click");
clickinternet.SetClickFile (n.Get (2), "src/routing/click/examples/nsclick-routing-node2.click");
clickinternet.SetRoutingTableElement (n.Get (0), "kernel/rt");
clickinternet.SetRoutingTableElement (n.Get (1), "u/rt");
clickinternet.SetRoutingTableElement (n.Get (2), "kernel/rt");
clickinternet.Install (n);
NS_LOG_INFO ("Create channels.");
//
// Explicitly create the channels required by the topology (shown above).
//
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
NetDeviceContainer d01 = csma.Install (NodeContainer (n.Get (0), n.Get (1)));
NetDeviceContainer d12 = csma.Install (NodeContainer (n.Get (1), n.Get (2)));
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
Ipv4InterfaceContainer i01 = ipv4.Assign (d01);
ipv4.SetBase ("172.16.2.0", "255.255.255.0");
Ipv4InterfaceContainer i12 = ipv4.Assign (d12);
NS_LOG_INFO ("Create Applications.");
//
// Create one udpServer applications on node one.
//
uint16_t port = 4000;
UdpServerHelper server (port);
ApplicationContainer apps = server.Install (n.Get(2));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
//
// Create one UdpClient application to send UDP datagrams from node zero to
// node one.
//
uint32_t MaxPacketSize = 1024;
Time interPacketInterval = Seconds (0.05);
uint32_t maxPacketCount = 320;
UdpClientHelper client (i12.GetAddress (1), port);
client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));
apps = client.Install (NodeContainer (n.Get (0)));
apps.Start (Seconds (2.0));
apps.Stop (Seconds (10.0));
csma.EnablePcap ("nsclick-routing", d01, false);
csma.EnablePcap ("nsclick-routing", d12, false);
//
// Now, do the actual simulation.
//
NS_LOG_INFO ("Run Simulation.");
Simulator::Stop (Seconds(20.0));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
#else
NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in");
#endif
}

View File

@@ -0,0 +1,97 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
// Scenario:
//
// (Click) CSMA (non-Click)
// A ================ B
// (172.16.1.1) (172.16.1.2)
// (eth0)
//
//
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/helper-module.h"
#include "ns3/click-internet-stack-helper.h"
#include "ns3/log.h"
using namespace ns3;
void ReceivePacket (Ptr<Socket> socket)
{
NS_LOG_UNCOND ("Received one packet!");
}
int main (int argc, char *argv[])
{
#ifdef NS3_CLICK
NodeContainer csmaNodes;
csmaNodes.Create (2);
// Setup CSMA channel between the nodes
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
NetDeviceContainer csmaDevices = csma.Install (csmaNodes);
// Install normal internet stack on node B
InternetStackHelper internet;
internet.Install (csmaNodes.Get (1));
// Install Click on node A
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (csmaNodes.Get (0), "src/routing/click/examples/nsclick-lan-single-interface.click");
clickinternet.SetRoutingTableElement (csmaNodes.Get (0), "rt");
clickinternet.Install (csmaNodes.Get (0));
// Configure IP addresses for the nodes
Ipv4AddressHelper ipv4;
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
ipv4.Assign (csmaDevices);
// Configure traffic application and sockets
Address LocalAddress (InetSocketAddress (Ipv4Address::GetAny (), 50000));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", LocalAddress);
ApplicationContainer recvapp = packetSinkHelper.Install (csmaNodes.Get (1));
recvapp.Start (Seconds (5.0));
recvapp.Stop (Seconds (10.0));
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
onOffHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
onOffHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
ApplicationContainer appcont;
AddressValue remoteAddress (InetSocketAddress (Ipv4Address ("172.16.1.2"), 50000));
onOffHelper.SetAttribute ("Remote", remoteAddress);
appcont.Add (onOffHelper.Install (csmaNodes.Get (0)));
appcont.Start (Seconds (5.0));
appcont.Stop (Seconds (10.0));
// For tracing
csma.EnablePcap ("nsclick-simple-lan", csmaDevices, false);
Simulator::Stop (Seconds(20.0));
Simulator::Run();
return 0;
#else
NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in");
#endif
}

View File

@@ -0,0 +1,126 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*/
// Adaptation of examples/udp/udp-client-server.cc for
// Click based nodes.
//
// Network topology
//
// 172.16.1.0/24
// (1.1) (1.2) (1.3)
// n0 n1 n2
// | | |
// =============
// LAN
//
// - 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.
//
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/helper-module.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/click-internet-stack-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("NsclickUdpClientServerCsma");
int
main (int argc, char *argv[])
{
#ifdef NS3_CLICK
//
// Enable logging for UdpClient and
//
LogComponentEnable ("NsclickUdpClientServerCsma", LOG_LEVEL_INFO);
//
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
NodeContainer n;
n.Create (3);
NS_LOG_INFO ("Create channels.");
//
// Explicitly create the channels required by the topology (shown above).
//
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
NetDeviceContainer d = csma.Install (n);
//
// Install Click on the nodes
//
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (n, "src/routing/click/examples/nsclick-lan-single-interface.click");
clickinternet.SetRoutingTableElement (n, "rt");
clickinternet.Install (n);
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
NS_LOG_INFO ("Create Applications.");
//
// Create one udpServer applications on node one.
//
uint16_t port = 4000;
UdpServerHelper server (port);
ApplicationContainer apps = server.Install (n.Get(1));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
//
// Create one UdpClient application to send UDP datagrams from node zero to
// node one.
//
uint32_t MaxPacketSize = 1024;
Time interPacketInterval = Seconds (0.05);
uint32_t maxPacketCount = 320;
UdpClientHelper client (i.GetAddress (1), port);
client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));
apps = client.Install (NodeContainer (n.Get (0), n.Get (2)));
apps.Start (Seconds (2.0));
apps.Stop (Seconds (10.0));
csma.EnablePcap ("nsclick-udp-client-server-csma", d, false);
//
// Now, do the actual simulation.
//
NS_LOG_INFO ("Run Simulation.");
Simulator::Stop (Seconds(20.0));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
#else
NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in");
#endif
}

View File

@@ -0,0 +1,199 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* 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
*/
// Adaptation of examples/udp/udp-client-server.cc for
// Click based nodes running wifi.
//
// Network topology
//
// 172.16.1.0/24
// (1.1) (1.2) (1.3)
// n0 )) (( n1 )) (( n2
// WLAN
//
// - UDP flows from n0 to n1
// - All nodes are Click based.
// - The single ethernet interface that each node
// uses is named 'eth0' in the Click file.
//
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/helper-module.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/click-internet-stack-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("NsclickUdpClientServerWifi");
#ifdef NS3_CLICK
void
readArp(Ptr<Ipv4ClickRouting> clickRouter)
{
// Access the handlers
NS_LOG_INFO(clickRouter->ReadHandler ("wifi/arpquerier", "table"));
NS_LOG_INFO(clickRouter->ReadHandler ("wifi/arpquerier", "stats"));
}
void
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"));
}
#endif
int
main (int argc, char *argv[])
{
#ifdef NS3_CLICK
//
// Enable logging
//
LogComponentEnable ("NsclickUdpClientServerWifi", LOG_LEVEL_INFO);
//
// Explicitly create the nodes required by the topology (shown above).
//
NS_LOG_INFO ("Create nodes.");
NodeContainer n;
n.Create (4);
NS_LOG_INFO ("Create channels.");
//
// Explicitly create the channels required by the topology (shown above).
//
std::string phyMode ("DsssRate1Mbps");
// disable fragmentation for frames below 2200 bytes
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
// turn off RTS/CTS for frames below 2200 bytes
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
// Fix non-unicast data rate to be the same as that of unicast
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
StringValue (phyMode));
WifiHelper wifi;
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
// This is one parameter that matters when using FixedRssLossModel
// set it to zero; otherwise, gain will be added
wifiPhy.Set ("RxGain", DoubleValue (0) );
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
YansWifiChannelHelper wifiChannel ;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
// The below FixedRssLossModel will cause the rss to be fixed regardless
// of the distance between the two stations, and the transmit power
wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue(-80));
wifiPhy.SetChannel (wifiChannel.Create ());
// Add a non-QoS upper mac, and disable rate control
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue(phyMode),
"ControlMode",StringValue(phyMode));
// Set it to adhoc mode
wifiMac.SetType ("ns3::AdhocWifiMac");
NetDeviceContainer d = wifi.Install (wifiPhy, wifiMac, n);
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
positionAlloc->Add (Vector (10.0, 0.0, 0.0));
positionAlloc->Add (Vector (20.0, 0.0, 0.0));
positionAlloc->Add (Vector (0.0, 10.0, 0.0));
mobility.SetPositionAllocator (positionAlloc);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (n);
//
// Install Click on the nodes
//
ClickInternetStackHelper clickinternet;
clickinternet.SetClickFile (n, "src/routing/click/examples/nsclick-wifi-single-interface.click");
clickinternet.SetRoutingTableElement (n, "rt");
clickinternet.Install (n);
// 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.
n.Get(3)->GetObject<Ipv4ClickRouting>()->SetPromiscuous ("eth0");
Ipv4AddressHelper ipv4;
//
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_LOG_INFO ("Assign IP Addresses.");
ipv4.SetBase ("172.16.1.0", "255.255.255.0");
Ipv4InterfaceContainer i = ipv4.Assign (d);
NS_LOG_INFO ("Create Applications.");
//
// Create one udpServer applications on node one.
//
uint16_t port = 4000;
UdpServerHelper server (port);
ApplicationContainer apps = server.Install (n.Get(1));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
//
// Create one UdpClient application to send UDP datagrams from node zero to
// node one.
//
uint32_t MaxPacketSize = 1024;
Time interPacketInterval = Seconds (0.5);
uint32_t maxPacketCount = 320;
UdpClientHelper client (i.GetAddress (1), port);
client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
client.SetAttribute ("Interval", TimeValue (interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));
apps = client.Install (NodeContainer (n.Get (0), n.Get (2)));
apps.Start (Seconds (2.0));
apps.Stop (Seconds (10.0));
wifiPhy.EnablePcap ("nsclick-udp-client-server-wifi", d);
// 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
// response is received. With the scenario of this example, all ARP
// requests of node 3 are lost due to interference from node
// 1. Hence, we fill in the ARP table of node 2 before at the
// beginning of the simulation
Simulator::Schedule (Seconds (0.5), &readArp,n.Get(2)->GetObject<Ipv4ClickRouting>());
Simulator::Schedule (Seconds (0.6), &writeArp,n.Get(2)->GetObject<Ipv4ClickRouting>());
Simulator::Schedule (Seconds (0.7), &readArp,n.Get(2)->GetObject<Ipv4ClickRouting>());
//
// Now, do the actual simulation.
//
NS_LOG_INFO ("Run Simulation.");
Simulator::Stop (Seconds(20.0));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
#else
NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in");
#endif
}

View File

@@ -0,0 +1,113 @@
// 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.
// 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)
-> 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;

View File

@@ -0,0 +1,22 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
obj = bld.create_ns3_program('nsclick-simple-lan',
['click', 'csma', 'internet-stack'])
obj.source = 'nsclick-simple-lan.cc'
obj = bld.create_ns3_program('nsclick-raw-wlan',
['click', 'wifi', 'internet-stack'])
obj.source = 'nsclick-raw-wlan.cc'
obj = bld.create_ns3_program('nsclick-udp-client-server-csma',
['click', 'csma', 'internet-stack'])
obj.source = 'nsclick-udp-client-server-csma.cc'
obj = bld.create_ns3_program('nsclick-udp-client-server-wifi',
['click', 'wifi', 'internet-stack'])
obj.source = 'nsclick-udp-client-server-wifi.cc'
obj = bld.create_ns3_program('nsclick-routing',
['click', 'csma', 'internet-stack'])
obj.source = 'nsclick-routing.cc'

View File

@@ -0,0 +1,503 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2008 INRIA
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
* Author: Faker Moatamri <faker.moatamri@sophia.inria.fr>
* Author: Lalith Suresh <suresh.lalith@gmail.com>
*/
#ifdef NS3_CLICK
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/object.h"
#include "ns3/names.h"
#include "ns3/ipv4.h"
#include "ns3/packet-socket-factory.h"
#include "ns3/config.h"
#include "ns3/simulator.h"
#include "ns3/string.h"
#include "ns3/net-device.h"
#include "ns3/callback.h"
#include "ns3/node.h"
#include "ns3/core-config.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/ipv4-l3-click-protocol.h"
#include "ns3/trace-helper.h"
#include "click-internet-stack-helper.h"
#include <limits>
#include <map>
NS_LOG_COMPONENT_DEFINE ("ClickInternetStackHelper");
namespace ns3 {
#define INTERFACE_CONTEXT
typedef std::pair<Ptr<Ipv4>, uint32_t> InterfacePairIpv4;
typedef std::map<InterfacePairIpv4, Ptr<PcapFileWrapper> > InterfaceFileMapIpv4;
typedef std::map<InterfacePairIpv4, Ptr<OutputStreamWrapper> > InterfaceStreamMapIpv4;
static InterfaceFileMapIpv4 g_interfaceFileMapIpv4; /**< A mapping of Ipv4/interface pairs to pcap files */
static InterfaceStreamMapIpv4 g_interfaceStreamMapIpv4; /**< A mapping of Ipv4/interface pairs to ascii streams */
ClickInternetStackHelper::ClickInternetStackHelper ()
: m_ipv4Enabled (true)
{
Initialize ();
}
// private method called by both constructor and Reset ()
void
ClickInternetStackHelper::Initialize ()
{
SetTcp ("ns3::TcpL4Protocol");
}
ClickInternetStackHelper::~ClickInternetStackHelper ()
{
}
ClickInternetStackHelper::ClickInternetStackHelper (const ClickInternetStackHelper &o)
{
m_ipv4Enabled = o.m_ipv4Enabled;
m_tcpFactory = o.m_tcpFactory;
}
ClickInternetStackHelper &
ClickInternetStackHelper::operator = (const ClickInternetStackHelper &o)
{
if (this == &o)
{
return *this;
}
return *this;
}
void
ClickInternetStackHelper::Reset (void)
{
m_ipv4Enabled = true;
Initialize ();
}
void
ClickInternetStackHelper::SetTcp (const std::string tid)
{
m_tcpFactory.SetTypeId (tid);
}
void
ClickInternetStackHelper::SetTcp (std::string tid, std::string n0, const AttributeValue &v0)
{
m_tcpFactory.SetTypeId (tid);
m_tcpFactory.Set (n0,v0);
}
void
ClickInternetStackHelper::SetClickFile (NodeContainer c, std::string clickfile)
{
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
SetClickFile (*i, clickfile);
}
}
void
ClickInternetStackHelper::SetClickFile (Ptr<Node> node, std::string clickfile)
{
m_nodeToClickFileMap.insert (std::make_pair (node, clickfile));
}
void
ClickInternetStackHelper::SetRoutingTableElement (NodeContainer c, std::string rt)
{
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
SetRoutingTableElement (*i, rt);
}
}
void
ClickInternetStackHelper::SetRoutingTableElement (Ptr<Node> node, std::string rt)
{
m_nodeToRoutingTableElementMap.insert (std::make_pair (node, rt));
}
void
ClickInternetStackHelper::Install (NodeContainer c) const
{
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
Install (*i);
}
}
void
ClickInternetStackHelper::InstallAll (void) const
{
Install (NodeContainer::GetGlobal ());
}
void
ClickInternetStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId)
{
ObjectFactory factory;
factory.SetTypeId (typeId);
Ptr<Object> protocol = factory.Create <Object> ();
node->AggregateObject (protocol);
}
void
ClickInternetStackHelper::Install (Ptr<Node> node) const
{
if (m_ipv4Enabled)
{
if (node->GetObject<Ipv4> () != 0)
{
NS_FATAL_ERROR ("ClickInternetStackHelper::Install (): Aggregating "
"an InternetStack to a node with an existing Ipv4 object");
return;
}
CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3ClickProtocol");
CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
node->AggregateObject (m_tcpFactory.Create<Object> ());
Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
node->AggregateObject (factory);
// Set routing
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> ipv4Routing = CreateObject<Ipv4ClickRouting> ();
std::map< Ptr<Node>, std::string >::const_iterator it;
it = m_nodeToClickFileMap.find (node);
if (it != m_nodeToClickFileMap.end ())
{
ipv4Routing->SetClickFile (it->second);
}
it = m_nodeToRoutingTableElementMap.find (node);
if (it != m_nodeToRoutingTableElementMap.end ())
{
ipv4Routing->SetClickRoutingTableElement (it->second);
}
ipv4->SetRoutingProtocol (ipv4Routing);
node->AggregateObject (ipv4Routing);
}
}
void
ClickInternetStackHelper::Install (std::string nodeName) const
{
Ptr<Node> node = Names::Find<Node> (nodeName);
Install (node);
}
static void
Ipv4L3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ipv4> ipv4, uint32_t interface)
{
NS_LOG_FUNCTION (p << ipv4 << interface);
//
// Since trace sources are independent of interface, if we hook a source
// on a particular protocol we will get traces for all of its interfaces.
// We need to filter this to only report interfaces for which the user
// has expressed interest.
//
InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
if (g_interfaceFileMapIpv4.find (pair) == g_interfaceFileMapIpv4.end ())
{
NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
return;
}
Ptr<PcapFileWrapper> file = g_interfaceFileMapIpv4[pair];
file->Write(Simulator::Now(), p);
}
bool
ClickInternetStackHelper::PcapHooked (Ptr<Ipv4> ipv4)
{
for ( InterfaceFileMapIpv4::const_iterator i = g_interfaceFileMapIpv4.begin ();
i != g_interfaceFileMapIpv4.end ();
++i)
{
if ((*i).first.first == ipv4)
{
return true;
}
}
return false;
}
void
ClickInternetStackHelper::EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename)
{
NS_LOG_FUNCTION (prefix << ipv4 << interface);
if (!m_ipv4Enabled)
{
NS_LOG_INFO ("Call to enable Ipv4 pcap tracing but Ipv4 not enabled");
return;
}
//
// We have to create a file and a mapping from protocol/interface to file
// irrespective of how many times we want to trace a particular protocol.
//
PcapHelper pcapHelper;
std::string filename;
if (explicitFilename)
{
filename = prefix;
}
else
{
filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
}
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
//
// However, we only hook the trace source once to avoid multiple trace sink
// calls per event (connect is independent of interface).
//
if (!PcapHooked (ipv4))
{
//
// Ptr<Ipv4> is aggregated to node and Ipv4L3Protocol is aggregated to
// node so we can get to Ipv4L3Protocol through Ipv4.
//
Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ();
NS_ASSERT_MSG (ipv4L3Protocol, "ClickInternetStackHelper::EnablePcapIpv4Internal(): "
"m_ipv4Enabled and ipv4L3Protocol inconsistent");
bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&Ipv4L3ProtocolRxTxSink));
NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4Internal(): "
"Unable to connect ipv4L3Protocol \"Tx\"");
result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&Ipv4L3ProtocolRxTxSink));
NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EnablePcapIpv4Internal(): "
"Unable to connect ipv4L3Protocol \"Rx\"");
}
g_interfaceFileMapIpv4[std::make_pair (ipv4, interface)] = file;
}
static void
Ipv4L3ProtocolDropSinkWithoutContext (
Ptr<OutputStreamWrapper> stream,
Ipv4Header const &header,
Ptr<const Packet> packet,
Ipv4L3Protocol::DropReason reason,
Ptr<Ipv4> ipv4,
uint32_t interface)
{
//
// Since trace sources are independent of interface, if we hook a source
// on a particular protocol we will get traces for all of its interfaces.
// We need to filter this to only report interfaces for which the user
// has expressed interest.
//
InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
{
NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
return;
}
Ptr<Packet> p = packet->Copy ();
p->AddHeader (header);
*stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
}
static void
Ipv4L3ProtocolDropSinkWithContext (
Ptr<OutputStreamWrapper> stream,
std::string context,
Ipv4Header const &header,
Ptr<const Packet> packet,
Ipv4L3Protocol::DropReason reason,
Ptr<Ipv4> ipv4,
uint32_t interface)
{
//
// Since trace sources are independent of interface, if we hook a source
// on a particular protocol we will get traces for all of its interfaces.
// We need to filter this to only report interfaces for which the user
// has expressed interest.
//
InterfacePairIpv4 pair = std::make_pair (ipv4, interface);
if (g_interfaceStreamMapIpv4.find (pair) == g_interfaceStreamMapIpv4.end ())
{
NS_LOG_INFO ("Ignoring packet to/from interface " << interface);
return;
}
Ptr<Packet> p = packet->Copy ();
p->AddHeader (header);
#ifdef INTERFACE_CONTEXT
*stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << interface << ") "
<< *p << std::endl;
#else
*stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
#endif
}
bool
ClickInternetStackHelper::AsciiHooked (Ptr<Ipv4> ipv4)
{
for ( InterfaceStreamMapIpv4::const_iterator i = g_interfaceStreamMapIpv4.begin ();
i != g_interfaceStreamMapIpv4.end ();
++i)
{
if ((*i).first.first == ipv4)
{
return true;
}
}
return false;
}
void
ClickInternetStackHelper::EnableAsciiIpv4Internal (
Ptr<OutputStreamWrapper> stream,
std::string prefix,
Ptr<Ipv4> ipv4,
uint32_t interface,
bool explicitFilename)
{
if (!m_ipv4Enabled)
{
NS_LOG_INFO ("Call to enable Ipv4 ascii tracing but Ipv4 not enabled");
return;
}
//
// Our trace sinks are going to use packet printing, so we have to
// make sure that is turned on.
//
Packet::EnablePrinting ();
//
// If we are not provided an OutputStreamWrapper, we are expected to create
// one using the usual trace filename conventions and hook WithoutContext
// since there will be one file per context and therefore the context would
// be redundant.
//
if (stream == 0)
{
//
// Set up an output stream object to deal with private ofstream copy
// constructor and lifetime issues. Let the helper decide the actual
// name of the file given the prefix.
//
// We have to create a stream and a mapping from protocol/interface to
// stream irrespective of how many times we want to trace a particular
// protocol.
//
AsciiTraceHelper asciiTraceHelper;
std::string filename;
if (explicitFilename)
{
filename = prefix;
}
else
{
filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
}
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
//
// However, we only hook the trace sources once to avoid multiple trace sink
// calls per event (connect is independent of interface).
//
if (!AsciiHooked (ipv4))
{
//
// We can use the default drop sink for the ArpL3Protocol since it has
// the usual signature. We can get to the Ptr<ArpL3Protocol> through
// our Ptr<Ipv4> since they must both be aggregated to the same node.
//
Ptr<ArpL3Protocol> arpL3Protocol = ipv4->GetObject<ArpL3Protocol> ();
asciiTraceHelper.HookDefaultDropSinkWithoutContext<ArpL3Protocol> (arpL3Protocol, "Drop", theStream);
//
// The drop sink for the Ipv4L3Protocol uses a different signature than
// the default sink, so we have to cook one up for ourselves. We can get
// to the Ptr<Ipv4L3Protocol> through our Ptr<Ipv4> since they must both
// be aggregated to the same node.
//
Ptr<Ipv4L3Protocol> ipv4L3Protocol = ipv4->GetObject<Ipv4L3Protocol> ();
bool __attribute__ ((unused)) result = ipv4L3Protocol->TraceConnectWithoutContext ("Drop",
MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithoutContext,
theStream));
NS_ASSERT_MSG (result == true, "ClickInternetStackHelper::EanableAsciiIpv4Internal(): "
"Unable to connect ipv4L3Protocol \"Drop\"");
}
g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = theStream;
return;
}
//
// If we are provided an OutputStreamWrapper, we are expected to use it, and
// to provide a context. We are free to come up with our own context if we
// want, and use the AsciiTraceHelper Hook*WithContext functions, but for
// compatibility and simplicity, we just use Config::Connect and let it deal
// with the context.
//
// We need to associate the ipv4/interface with a stream to express interest
// in tracing events on that pair, however, we only hook the trace sources
// once to avoid multiple trace sink calls per event (connect is independent
// of interface).
//
if (!AsciiHooked (ipv4))
{
Ptr<Node> node = ipv4->GetObject<Node> ();
std::ostringstream oss;
//
// For the ARP Drop, we are going to use the default trace sink provided by
// the ascii trace helper. There is actually no AsciiTraceHelper in sight
// here, but the default trace sinks are actually publicly available static
// functions that are always there waiting for just such a case.
//
oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop";
Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
//
// This has all kinds of parameters coming with, so we have to cook up our
// own sink.
//
oss.str ("");
oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop";
Config::Connect (oss.str (), MakeBoundCallback (&Ipv4L3ProtocolDropSinkWithContext, stream));
}
g_interfaceStreamMapIpv4[std::make_pair (ipv4, interface)] = stream;
}
} // namespace ns3
#endif // NS3_CLICK

View File

@@ -0,0 +1,230 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2008 INRIA
*
* 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
* Author: Lalith Suresh <suresh.lalith@gmail.com>
*/
#ifdef NS3_CLICK
#ifndef CLICK_INTERNET_STACK_HELPER_H
#define CLICK_INTERNET_STACK_HELPER_H
#include "ns3/node-container.h"
#include "ns3/net-device-container.h"
#include "ns3/packet.h"
#include "ns3/ptr.h"
#include "ns3/object-factory.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/trace-helper.h"
#include <map>
namespace ns3 {
class Node;
class Ipv4RoutingHelper;
/**
* \brief aggregate Click/IP/TCP/UDP functionality to existing Nodes.
*
* This helper has been adapted from the InternetStackHelper class and
* nodes will not be able to use Ipv6 functionalities.
*
*/
class ClickInternetStackHelper : public PcapHelperForIpv4, public AsciiTraceHelperForIpv4
{
public:
/**
* Create a new ClickInternetStackHelper which uses Ipv4ClickRouting for routing
*/
ClickInternetStackHelper(void);
/**
* Destroy the ClickInternetStackHelper
*/
virtual ~ClickInternetStackHelper(void);
ClickInternetStackHelper (const ClickInternetStackHelper &);
ClickInternetStackHelper &operator = (const ClickInternetStackHelper &o);
/**
* Return helper internal state to that of a newly constructed one
*/
void Reset (void);
/**
* Aggregate implementations of the ns3::Ipv4L3ClickProtocol, ns3::ArpL3Protocol,
* ns3::Udp, and ns3::Tcp classes onto the provided node. This method will
* assert if called on a node that already has an Ipv4 object aggregated to it.
*
* \param nodeName The name of the node on which to install the stack.
*/
void Install (std::string nodeName) const;
/**
* Aggregate implementations of the ns3::Ipv4L3ClickProtocol, ns3::ArpL3Protocol,
* ns3::Udp, and ns3::Tcp classes onto the provided node. This method will
* assert if called on a node that already has an Ipv4 object aggregated to it.
*
* \param node The node on which to install the stack.
*/
void Install (Ptr<Node> node) const;
/**
* For each node in the input container, aggregate implementations of the
* ns3::Ipv4L3ClickProtocol, ns3::ArpL3Protocol, ns3::Udp, and, ns3::Tcp classes.
* The program will assert if this method is called on a container with a
* node that already has an Ipv4 object aggregated to it.
*
* \param c NodeContainer that holds the set of nodes on which to install the
* new stacks.
*/
void Install (NodeContainer c) const;
/**
* Aggregate IPv4, UDP, and TCP stacks to all nodes in the simulation
*/
void InstallAll (void) const;
/**
* \brief set the Tcp stack which will not need any other parameter.
*
* This function sets up the tcp stack to the given TypeId. It should not be
* used for NSC stack setup because the nsc stack needs the Library attribute
* to be setup, please use instead the version that requires an attribute
* and a value. If you choose to use this function anyways to set nsc stack
* the default value for the linux library will be used: "liblinux2.6.26.so".
*
* \param tid the type id, typically it is set to "ns3::TcpL4Protocol"
*/
void SetTcp(std::string tid);
/**
* \brief This function is used to setup the Network Simulation Cradle stack with library value.
*
* Give the NSC stack a shared library file name to use when creating the
* stack implementation. The attr string is actually the attribute name to
* be setup and val is its value. The attribute is the stack implementation
* to be used and the value is the shared library name.
*
* \param tid The type id, for the case of nsc it would be "ns3::NscTcpL4Protocol"
* \param attr The attribute name that must be setup, for example "Library"
* \param val The attribute value, which will be in fact the shared library name (example:"liblinux2.6.26.so")
*/
void SetTcp (std::string tid, std::string attr, const AttributeValue &val);
/**
* \brief Set a Click file to be used for a group of nodes.
* \param c NodeContainer of nodes
* \param clickfile Click file to be used
*/
void SetClickFile (NodeContainer c, std::string clickfile);
/**
* \brief Set a Click file to be used for a node.
* \param node Node for which Click file is to be set
* \param clickfile Click file to be used
*/
void SetClickFile (Ptr<Node> node, std::string clickfile);
/**
* \brief Set a Click routing table element for a group of nodes.
* \param c NodeContainer of nodes
* \param rt Click Routing Table element name
*/
void SetRoutingTableElement (NodeContainer c, std::string rt);
/**
* \brief Set a Click routing table element for a node.
* \param node Node for which Click file is to be set
* \param rt Click Routing Table element name
*/
void SetRoutingTableElement (Ptr<Node> node, std::string rt);
private:
/**
* @brief Enable pcap output the indicated Ipv4 and interface pair.
* @internal
*
* @param prefix Filename prefix to use for pcap files.
* @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv4 on which you want to enable tracing.
*/
virtual void EnablePcapIpv4Internal (std::string prefix,
Ptr<Ipv4> ipv4,
uint32_t interface,
bool explicitFilename);
/**
* @brief Enable ascii trace output on the indicated Ipv4 and interface pair.
* @internal
*
* @param stream An OutputStreamWrapper representing an existing file to use
* when writing trace data.
* @param prefix Filename prefix to use for ascii trace files.
* @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing.
* @param interface Interface ID on the Ipv4 on which you want to enable tracing.
*/
virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
Ptr<Ipv4> ipv4,
uint32_t interface,
bool explicitFilename);
void Initialize (void);
ObjectFactory m_tcpFactory;
/**
* \internal
*/
static void CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId);
/**
* \internal
*/
static void Cleanup (void);
/**
* \internal
*/
bool PcapHooked (Ptr<Ipv4> ipv4);
/**
* \internal
*/
bool AsciiHooked (Ptr<Ipv4> ipv4);
/**
* \brief IPv4 install state (enabled/disabled) ?
*/
bool m_ipv4Enabled;
/**
* \brief Node to Click file mapping
*/
std::map < Ptr<Node>, std::string > m_nodeToClickFileMap;
/**
* \brief Node to Routing Table Element mapping
*/
std::map < Ptr<Node>, std::string > m_nodeToRoutingTableElementMap;
};
} // namespace ns3
#endif /* CLICK_INTERNET_STACK_HELPER_H */
#endif // NS3_CLICK

View File

@@ -0,0 +1,646 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2010 Lalith Suresh
*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
#ifdef NS3_CLICK
#include "ns3/node.h"
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/mac48-address.h"
#include "ns3/ipv4-interface.h"
#include "ns3/ipv4-l3-click-protocol.h"
#include "ipv4-click-routing.h"
#include <string>
#include <map>
#include <cstdlib>
#include <cstdarg>
NS_LOG_COMPONENT_DEFINE ("Ipv4ClickRouting");
namespace ns3 {
// Values from nsclick ExtRouter implementation
#define INTERFACE_ID_KERNELTAP 0
#define INTERFACE_ID_FIRST 1
#define INTERFACE_ID_FIRST_DROP 33
NS_OBJECT_ENSURE_REGISTERED (Ipv4ClickRouting);
std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickInstanceFromSimNode;
TypeId
Ipv4ClickRouting::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Ipv4ClickRouting")
.SetParent<Ipv4RoutingProtocol> ()
.AddConstructor<Ipv4ClickRouting> ()
;
return tid;
}
Ipv4ClickRouting::Ipv4ClickRouting ()
: m_nonDefaultName (false),
m_ipv4 (0)
{
}
Ipv4ClickRouting::~Ipv4ClickRouting ()
{
}
void
Ipv4ClickRouting::DoStart ()
{
uint32_t id = m_ipv4->GetObject<Node> ()->GetId ();
if (!m_nonDefaultName)
{
std::stringstream name;
name << "Node" << id;
m_nodeName = name.str ();
}
m_simNode = new simclick_node_t;
timerclear (&m_simNode->curtime);
AddSimNodeToClickMapping ();
NS_ASSERT (m_clickFile.length () > 0);
// Even though simclick_click_create() will halt programme execution
// if it is unable to initialise a Click router, we play safe
if (simclick_click_create (m_simNode, m_clickFile.c_str ()) >= 0)
{
NS_LOG_DEBUG (m_nodeName << " has initialised a Click Router");
m_clickInitialised = true;
}
else
{
NS_LOG_DEBUG ("Click Router Initialisation failed for " << m_nodeName);
m_clickInitialised = false;
}
NS_ASSERT (m_clickInitialised == true);
simclick_click_run (m_simNode);
}
void
Ipv4ClickRouting::SetIpv4 (Ptr<Ipv4> ipv4)
{
m_ipv4 = ipv4;
}
void
Ipv4ClickRouting::DoDispose ()
{
m_ipv4 = 0;
delete m_simNode;
Ipv4RoutingProtocol::DoDispose ();
}
void
Ipv4ClickRouting::SetClickFile (std::string clickfile)
{
m_clickFile = clickfile;
}
void
Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
{
m_clickRoutingTableElement = name;
}
void
Ipv4ClickRouting::SetNodeName (std::string name)
{
m_nodeName = name;
m_nonDefaultName = true;
}
std::string
Ipv4ClickRouting::GetNodeName ()
{
return m_nodeName;
}
int
Ipv4ClickRouting::GetInterfaceId (const char *ifname)
{
int retval = -1;
// The below hard coding of interface names follows the
// same approach as used in the original nsclick code for
// ns-2. The interface names map directly to what is to
// be used in the Click configuration files.
// Thus eth0 will refer to the first network device of
// the node, and is to be named so in the Click graph.
// This function is called by Click during the intialisation
// phase of the Click graph, during which it tries to map
// interface IDs to interface names. The return value
// corresponds to the interface ID that Click will use.
// Tap/tun devices refer to the kernel devices
if (strstr(ifname, "tap") || strstr(ifname, "tun"))
{
retval = 0;
}
else if (const char *devname = strstr(ifname, "eth"))
{
while (*devname && !isdigit((unsigned char) *devname))
{
devname++;
}
if (*devname)
{
retval = atoi(devname) + INTERFACE_ID_FIRST;
}
}
else if (const char *devname = strstr(ifname, "drop"))
{
while (*devname && !isdigit((unsigned char) *devname))
{
devname++;
}
if (*devname)
{
retval = atoi(devname) + INTERFACE_ID_FIRST_DROP;
}
}
return retval;
}
bool
Ipv4ClickRouting::IsInterfaceReady (int ifid)
{
if (ifid >= 0 && ifid < (int) m_ipv4->GetNInterfaces ())
{
return true;
}
else
{
return false;
}
}
std::string
Ipv4ClickRouting::GetIpAddressFromInterfaceId (int ifid)
{
std::stringstream addr;
m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr);
return addr.str ();
}
std::string
Ipv4ClickRouting::GetMacAddressFromInterfaceId (int ifid)
{
std::stringstream addr;
Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
Address devAddr = device->GetAddress ();
addr << Mac48Address::ConvertFrom(devAddr);
return addr.str ();
}
void
Ipv4ClickRouting::AddSimNodeToClickMapping ()
{
m_clickInstanceFromSimNode.insert (std::make_pair (m_simNode, this));
}
Ptr<Ipv4ClickRouting>
Ipv4ClickRouting::GetClickInstanceFromSimNode (simclick_node_t *simnode)
{
return m_clickInstanceFromSimNode[simnode];
}
void
Ipv4ClickRouting::RunClickEvent ()
{
m_simNode->curtime.tv_sec = Simulator::Now ().GetSeconds ();
m_simNode->curtime.tv_usec = Simulator::Now ().GetMicroSeconds () % 1000000;
simclick_click_run (m_simNode);
}
void
Ipv4ClickRouting::HandleScheduleFromClick (const struct timeval *when)
{
NS_LOG_DEBUG ("HandleScheduleFromClick at " << when->tv_sec << " " << when->tv_usec << " " << Simulator::Now ());
double simtime = when->tv_sec + (when->tv_usec / 1.0e6);
double simdelay = simtime - Simulator::Now ().GetMicroSeconds () / 1.0e6;
Simulator::Schedule (Seconds (simdelay), &Ipv4ClickRouting::RunClickEvent, this);
}
void
Ipv4ClickRouting::HandlePacketFromClick (int ifid, int ptype, const unsigned char* data, int len)
{
NS_LOG_DEBUG ("HandlePacketFromClick");
// Figure out packet's destination here:
// If ifid == 0, then the packet's going up
// else, the packet's going down
if (ifid == 0)
{
NS_LOG_DEBUG ("Incoming packet from tap0. Sending Packet up the stack.");
Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
Ptr<Packet> p = Create<Packet> (data, len);
Ipv4Header ipHeader;
p->RemoveHeader (ipHeader);
ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
}
else if (ifid)
{
NS_LOG_DEBUG ("Incoming packet from eth" << ifid - 1 << " of type " << ptype <<". Sending packet down the stack.");
Ptr<Packet> p = Create<Packet> (data, len);
DynamicCast<Ipv4L3ClickProtocol> (m_ipv4)->SendDown (p, ifid);
}
}
void
Ipv4ClickRouting::SendPacketToClick (int ifid, int ptype, const unsigned char* data, int len)
{
NS_LOG_FUNCTION (this << ifid);
m_simNode->curtime.tv_sec = Simulator::Now ().GetSeconds ();
m_simNode->curtime.tv_usec = Simulator::Now ().GetMicroSeconds () % 1000000;
// Since packets in ns-3 don't have global Packet ID's and Flow ID's, we
// feed dummy values into pinfo. This avoids the need to make changes in the Click code
simclick_simpacketinfo pinfo;
pinfo.id = 0;
pinfo.fid = 0;
simclick_click_send(m_simNode,ifid,ptype,data,len,&pinfo);
}
void
Ipv4ClickRouting::Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dst)
{
uint32_t ifid;
// Find out which interface holds the src address of the packet...
for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
{
Ipv4Address addr = m_ipv4->GetAddress (ifid, 0).GetLocal ();
if (addr == src)
{
break;
}
}
int len = p->GetSize ();
uint8_t *buf = new uint8_t [len];
p->CopyData (buf, len);
// ... and send the packet on the corresponding Click interface.
SendPacketToClick (0, SIMCLICK_PTYPE_IP, buf, len);
delete [] buf;
}
void
Ipv4ClickRouting::Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest)
{
NS_LOG_FUNCTION (this << p << receiverAddr << dest);
uint32_t ifid;
// Find out which device this packet was received from...
for (ifid = 0; ifid < m_ipv4->GetNInterfaces (); ifid++)
{
Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid);
if (Mac48Address::ConvertFrom (device->GetAddress ()) == receiverAddr)
{
break;
}
}
int len = p->GetSize ();
uint8_t *buf = new uint8_t [len];
p->CopyData (buf, len);
//... and send the packet to the corresponding Click interface
SendPacketToClick (ifid, SIMCLICK_PTYPE_ETHER, buf, len);
delete [] buf;
}
std::string
Ipv4ClickRouting::ReadHandler (std::string elementName, std::string handlerName)
{
std::string s = simclick_click_read_handler (m_simNode, elementName.c_str (), handlerName.c_str (), 0, 0);
return s;
}
int
Ipv4ClickRouting::WriteHandler (std::string elementName, std::string handlerName, std::string writeString)
{
int r = simclick_click_write_handler (m_simNode, elementName.c_str (), handlerName.c_str (), writeString.c_str ());
// Note: There are probably use-cases for returning
// a write handler's error code, so don't assert.
// For example, the 'add' handler for IPRouteTable
// type elements fails if the route to be added
// already exists.
return r;
}
void
Ipv4ClickRouting::SetPromiscuous (std::string ifName)
{
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);
}
Ptr<Ipv4Route>
Ipv4ClickRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
{
Ptr<Ipv4Route> rtentry;
std::stringstream addr;
addr << "lookup ";
header.GetDestination ().Print (addr);
// Probe the Click Routing Table for the required IP
// This returns a string of the form "InterfaceID GatewayAddr"
std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
int pos = s.find (" ");
int interfaceId = atoi (s.substr (0, pos).c_str ());
Ipv4Address destination (s.substr (pos + 1).c_str ());
if (interfaceId != -1)
{
rtentry = Create<Ipv4Route> ();
rtentry->SetDestination (header.GetDestination ());
// the source address is the interface address that matches
// the destination address (when multiple are present on the
// outgoing interface, one is selected via scoping rules)
NS_ASSERT (m_ipv4);
uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceId);
NS_ASSERT (numOifAddresses > 0);
Ipv4InterfaceAddress ifAddr;
if (numOifAddresses == 1)
{
ifAddr = m_ipv4->GetAddress (interfaceId, 0);
}
else
{
NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and Click");
}
rtentry->SetSource (ifAddr.GetLocal ());
rtentry->SetGateway (destination);
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceId));
sockerr = Socket::ERROR_NOTERROR;
NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination ()
<< " via nh " << rtentry->GetGateway ()
<< " with source addr " << rtentry->GetSource ()
<< " and output dev " << rtentry->GetOutputDevice());
}
else
{
NS_LOG_DEBUG ("Click node " << m_nodeName
<< ": RouteOutput for dest=" << header.GetDestination ()
<< " No route to host");
sockerr = Socket::ERROR_NOROUTETOHOST;
}
return rtentry;
}
// This method should never be called since Click handles
// forwarding directly
bool
Ipv4ClickRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
MulticastForwardCallback mcb, LocalDeliverCallback lcb,
ErrorCallback ecb)
{
NS_FATAL_ERROR ("Click router does not have a RouteInput() interface!");
return false;
}
void
Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
{
}
void
Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i)
{}
void
Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i)
{}
void
Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
{}
void
Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
{}
} // namespace ns3
static int simstrlcpy(char *buf, int len, const std::string &s)
{
if (len)
{
len--;
if ((unsigned) len > s.length())
{
len = s.length();
}
s.copy(buf, len);
buf[len] = '\0';
}
return 0;
}
// Sends a Packet from Click to the Simulator: Defined in simclick.h. Click
// calls these methods.
int simclick_sim_send(simclick_node_t *simnode,
int ifid, int type, const unsigned char* data, int len,
simclick_simpacketinfo *pinfo)
{
NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now().GetSeconds()<<": " << ifid << " " << type << " " << data << " "<< len);
if (simnode == NULL)
{
return -1;
}
ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
clickInstance->HandlePacketFromClick (ifid, type, data, len);
return 0;
}
// Click Service Methods: Defined in simclick.h
int simclick_sim_command(simclick_node_t *simnode, int cmd, ...)
{
va_list val;
va_start (val, cmd);
int retval = 0;
ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClickInstanceFromSimNode (simnode);
switch (cmd)
{
case SIMCLICK_VERSION:
{
retval = 0;
break;
}
case SIMCLICK_SUPPORTS:
{
int othercmd = va_arg (val, int);
retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_NODE_ID);
break;
}
case SIMCLICK_IFID_FROM_NAME:
{
const char *ifname = va_arg(val, const char *);
retval = clickInstance->GetInterfaceId (ifname);
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IFID_FROM_NAME: " << ifname << " " << retval);
break;
}
case SIMCLICK_IPADDR_FROM_NAME:
{
const char *ifname = va_arg(val, const char *);
char *buf = va_arg(val, char *);
int len = va_arg(val, int);
int ifid = clickInstance->GetInterfaceId (ifname);
if (ifid >= 0)
{
retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfaceId (ifid));
}
else
{
retval = -1;
}
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NAME: "<< ifname << " "<< buf << " " << len);
break;
}
case SIMCLICK_MACADDR_FROM_NAME:
{
const char *ifname = va_arg(val, const char *);
char *buf = va_arg(val, char *);
int len = va_arg(val, int);
int ifid = clickInstance->GetInterfaceId (ifname);
if (ifid >= 0)
{
retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterfaceId (ifid));
}
else
{
retval = -1;
}
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_NAME: "<< ifname << " "<< buf << " "<< len);
break;
}
case SIMCLICK_SCHEDULE:
{
const struct timeval *when = va_arg(val, const struct timeval *);
clickInstance->HandleScheduleFromClick (when);
retval = 0;
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_SCHEDULE: "<< when->tv_sec << "s and " << when->tv_usec << "usecs later.");
break;
}
case SIMCLICK_GET_NODE_NAME:
{
char *buf = va_arg(val, char *);
int len = va_arg(val, int);
retval = simstrlcpy(buf, len, clickInstance->GetNodeName ());
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME: " << buf << " " << len);
break;
}
case SIMCLICK_IF_READY:
{
int ifid = va_arg(val, int); // Commented out so that optimized build works
// We're not using a ClickQueue, so we're always ready (for the timebeing)
retval = clickInstance->IsInterfaceReady (ifid);
NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " << ifid << " " << ns3::Simulator::Now ());
break;
}
case SIMCLICK_TRACE:
{
// Used only for tracing
NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_TRACE");
break;
}
case SIMCLICK_GET_NODE_ID:
{
// Used only for tracing
NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIMCLICK_GET_NODE_ID");
break;
}
}
return retval;
}
#endif // NS3_CLICK

View File

@@ -0,0 +1,247 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2010 Lalith Suresh
*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
#ifndef __IPV4_CLICK_ROUTING_H__
#define __IPV4_CLICK_ROUTING_H__
#include "ns3/object.h"
#include "ns3/packet.h"
#include "ns3/ipv4.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/test.h"
#include <sys/time.h>
#include <sys/types.h>
#ifdef NS3_CLICK
#include <click/simclick.h>
#endif
#include <map>
#include <string>
namespace ns3 {
/**
* \ingroup click
* \brief Class to allow a node to use Click for external routing
*/
class Ipv4ClickRouting : public Ipv4RoutingProtocol
{
#ifdef NS3_CLICK
public:
// Allow test cases to access private members
friend class ClickTrivialTest;
friend class ClickIfidFromNameTest;
friend class ClickIpMacAddressFromNameTest;
static TypeId GetTypeId (void);
Ipv4ClickRouting ();
virtual ~Ipv4ClickRouting ();
protected:
virtual void DoStart (void);
public:
virtual void DoDispose ();
/**
* \brief Click configuration file to be used by the node's Click Instance.
* \param clickfile name of .click configuration file
*/
void SetClickFile (std::string clickfile);
/**
* \brief Name of the node as to be used by Click. Required for Click Dumps.
* \param name Name to be assigned to the node.
*/
void SetNodeName (std::string name);
/**
* \brief Name of the routing table element being used by Click. Required for RouteOutput ()
* \param name Name of the routing table element.
*/
void SetClickRoutingTableElement (std::string name);
/**
* \brief Read Handler interface for a node's Click Elements.
* Allows a user to read state information of a Click element.
* \param elementName name of the Click element
* \param handlerName name of the handler to be read
*/
std::string ReadHandler (std::string elementName, std::string handlerName);
/**
* \brief Write Handler interface for a node's Click Elements
* Allows a user to modify state information of a Click element.
* \param elementName name of the Click element
* \param handlerName name of the handler to be read
* \param writeString string to be written using the write handler
*/
int WriteHandler (std::string elementName, std::string handlerName, std::string writeString);
/**
*
* \brief Sets an interface to run on promiscuous mode.
*/
void SetPromiscuous (std::string ifName);
private:
simclick_node_t *m_simNode;
/**
* \brief Provide a mapping between the node reference used by Click and the corresponding Ipv4ClickRouting instance.
*/
static std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > m_clickInstanceFromSimNode;
public:
/**
* \brief Allows the Click service methods, which reside outside Ipv4ClickRouting, to get the required Ipv4ClickRouting instances.
* \param simnode The Click simclick_node_t instance for which the Ipv4ClickRouting instance is required
* \return A Ptr to the required Ipv4ClickRouting instance
*/
static Ptr<Ipv4ClickRouting> GetClickInstanceFromSimNode (simclick_node_t *simnode);
public:
/**
* \brief Provides for SIMCLICK_IFID_FROM_NAME
* \param ifname The name of the interface
* \return The interface ID which corresponds to ifname
*/
int GetInterfaceId (const char *ifname);
/**
* \brief Provides for SIMCLICK_IPADDR_FROM_NAME
* \param ifid The interface ID for which the IP Address is required
* \return The IP Address of the interface in string format
*/
std::string GetIpAddressFromInterfaceId (int ifid);
/**
* \brief Provides for SIMCLICK_MACADDR_FROM_NAME
* \param ifid The interface ID for which the MAC Address is required
* \return The MAC Address of the interface in string format
*/
std::string GetMacAddressFromInterfaceId (int ifid);
/**
* \brief Provides for SIMCLICK_GET_NODE_NAME
* \return The Node name
*/
std::string GetNodeName ();
/**
* \brief Provides for SIMCLICK_IF_READY
* \return Returns 1, if the interface is ready, -1 if ifid is invalid
*/
bool IsInterfaceReady (int ifid);
/**
* \brief Set the Ipv4 instance to be used
* \param ipv4 The Ipv4 instance
*/
virtual void SetIpv4 (Ptr<Ipv4> ipv4);
private:
/**
* \brief Used internally in DoStart () to Add a mapping to m_clickInstanceFromSimNode mapping
*/
void AddSimNodeToClickMapping ();
/**
* \brief This method has to be scheduled everytime Click calls SIMCLICK_SCHEDULE
*/
void RunClickEvent ();
public:
/**
* \brief Schedules simclick_click_run to run at the given time
* \param when Time at which the simclick_click_run instance should be run
*/
void HandleScheduleFromClick (const struct timeval *when);
/**
* \brief Receives a packet from Click
* \param ifid The interface ID from which the packet is arriving
* \param type The type of packet as defined in click/simclick.h
* \param data The contents of the packet
* \param len The length of the packet
*/
void HandlePacketFromClick (int ifid, int type, const unsigned char *data, int len);
/**
* \brief Sends a packet to Click
* \param ifid The interface ID from which the packet is arriving
* \param type The type of packet as defined in click/simclick.h
* \param data The contents of the packet
* \param len The length of the packet
*/
void SendPacketToClick (int ifid, int type, const unsigned char *data, int len);
/**
* \brief Allow a higher layer to send data through Click. (From Ipv4ExtRouting)
* \param p The packet to be sent
* \param src The source IP Address
* \param dest The destination IP Address
*/
void Send (Ptr<Packet> p, Ipv4Address src, Ipv4Address dest);
/**
* \brief Allow a lower layer to send data to Click. (From Ipv4ExtRouting)
* \param p The packet to be sent
* \param receiverAddr Receiving interface's address
* \param dest The Destination MAC address
*/
void Receive (Ptr<Packet> p, Mac48Address receiverAddr, Mac48Address dest);
// From Ipv4RoutingProtocol
virtual Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr);
virtual bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb);
virtual void PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const;
virtual void NotifyInterfaceUp (uint32_t interface);
virtual void NotifyInterfaceDown (uint32_t interface);
virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
private:
std::string m_clickFile;
std::string m_nodeName;
std::string m_clickRoutingTableElement;
std::map < std::string, uint32_t > m_ifaceIdFromName;
std::map < std::string, Address > m_ifaceMacFromName;
std::map < std::string, Ipv4Address > m_ifaceAddrFromName;
bool m_clickInitialised;
bool m_nonDefaultName;
Ptr<Ipv4> m_ipv4;
#endif //NS3_CLICK
};
} // namespace ns3
#endif // __IPV4_CLICK_ROUTING_H__

View File

@@ -0,0 +1,818 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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: George F. Riley <riley@ece.gatech.edu>
// Author: Lalith Suresh <suresh.lalith@gmail.com>
//
#ifdef NS3_CLICK
#include "ipv4-l3-click-protocol.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/node.h"
#include "ns3/socket.h"
#include "ns3/ethernet-header.h"
#include "ns3/llc-snap-header.h"
#include "ns3/net-device.h"
#include "ns3/uinteger.h"
#include "ns3/object-vector.h"
#include "ns3/ipv4-raw-socket-impl.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l4-protocol.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/loopback-net-device.h"
NS_LOG_COMPONENT_DEFINE ("Ipv4L3ClickProtocol");
namespace ns3 {
const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
NS_OBJECT_ENSURE_REGISTERED (Ipv4L3ClickProtocol);
TypeId
Ipv4L3ClickProtocol::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Ipv4L3ClickProtocol")
.SetParent<Ipv4> ()
.AddConstructor<Ipv4L3ClickProtocol> ()
.AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
UintegerValue (64),
MakeUintegerAccessor (&Ipv4L3ClickProtocol::m_defaultTtl),
MakeUintegerChecker<uint8_t> ())
.AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Ipv4L3ClickProtocol::m_interfaces),
MakeObjectVectorChecker<Ipv4Interface> ())
;
return tid;
}
Ipv4L3ClickProtocol::Ipv4L3ClickProtocol ()
: m_identification (0)
{
}
Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol ()
{
}
void
Ipv4L3ClickProtocol::DoDispose (void)
{
NS_LOG_FUNCTION (this);
for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
*i = 0;
}
m_protocols.clear ();
for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
{
*i = 0;
}
m_interfaces.clear ();
m_sockets.clear ();
m_node = 0;
m_routingProtocol = 0;
Object::DoDispose ();
}
void
Ipv4L3ClickProtocol::NotifyNewAggregate ()
{
if (m_node == 0)
{
Ptr<Node>node = this->GetObject<Node>();
// verify that it's a valid node and that
// the node has not been set before
if (node != 0)
{
this->SetNode (node);
}
}
Object::NotifyNewAggregate ();
}
void
Ipv4L3ClickProtocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
{
NS_LOG_FUNCTION (this);
m_routingProtocol = routingProtocol;
m_routingProtocol->SetIpv4 (this);
}
Ptr<Ipv4RoutingProtocol>
Ipv4L3ClickProtocol::GetRoutingProtocol (void) const
{
return m_routingProtocol;
}
Ptr<Ipv4Interface>
Ipv4L3ClickProtocol::GetInterface (uint32_t index) const
{
NS_LOG_FUNCTION (this << index);
if (index < m_interfaces.size ())
{
return m_interfaces[index];
}
return 0;
}
uint32_t
Ipv4L3ClickProtocol::GetNInterfaces (void) const
{
NS_LOG_FUNCTION_NOARGS ();
return m_interfaces.size ();
}
int32_t
Ipv4L3ClickProtocol::GetInterfaceForAddress (
Ipv4Address address) const
{
NS_LOG_FUNCTION (this << address);
int32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
{
for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
if ((*i)->GetAddress (j).GetLocal () == address)
{
return interface;
}
}
}
return -1;
}
int32_t
Ipv4L3ClickProtocol::GetInterfaceForPrefix (
Ipv4Address address,
Ipv4Mask mask) const
{
NS_LOG_FUNCTION (this << address << mask);
int32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
{
for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
{
return interface;
}
}
}
return -1;
}
int32_t
Ipv4L3ClickProtocol::GetInterfaceForDevice (
Ptr<const NetDevice> device) const
{
NS_LOG_FUNCTION (this << device->GetIfIndex());
int32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
{
if ((*i)->GetDevice () == device)
{
return interface;
}
}
return -1;
}
bool
Ipv4L3ClickProtocol::IsDestinationAddress (Ipv4Address address, uint32_t iif) const
{
NS_LOG_FUNCTION (this << address << " " << iif);
// First check the incoming interface for a unicast address match
for (uint32_t i = 0; i < GetNAddresses (iif); i++)
{
Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
if (address == iaddr.GetLocal ())
{
NS_LOG_LOGIC ("For me (destination " << address << " match)");
return true;
}
if (address == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("For me (interface broadcast address)");
return true;
}
}
if (address.IsMulticast ())
{
#ifdef NOTYET
if (MulticastCheckGroup (iif, address ))
#endif
if (true)
{
NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
return true;
}
}
if (address.IsBroadcast ())
{
NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
return true;
}
if (GetWeakEsModel ()) // Check other interfaces
{
for (uint32_t j = 0; j < GetNInterfaces (); j++)
{
if (j == uint32_t (iif)) continue;
for (uint32_t i = 0; i < GetNAddresses (j); i++)
{
Ipv4InterfaceAddress iaddr = GetAddress (j, i);
if (address == iaddr.GetLocal ())
{
NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
return true;
}
// This is a small corner case: match another interface's broadcast address
if (address == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
return true;
}
}
}
}
return false;
}
void
Ipv4L3ClickProtocol::SetIpForward (bool forward)
{
NS_LOG_FUNCTION (this << forward);
m_ipForward = forward;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
{
(*i)->SetForwarding (forward);
}
}
bool
Ipv4L3ClickProtocol::GetIpForward (void) const
{
return m_ipForward;
}
void
Ipv4L3ClickProtocol::SetWeakEsModel (bool model)
{
m_weakEsModel = model;
}
bool
Ipv4L3ClickProtocol::GetWeakEsModel (void) const
{
return m_weakEsModel;
}
Ptr<NetDevice>
Ipv4L3ClickProtocol::GetNetDevice (uint32_t i)
{
NS_LOG_FUNCTION (this << i);
return GetInterface (i)->GetDevice ();
}
void
Ipv4L3ClickProtocol::SetDefaultTtl (uint8_t ttl)
{
NS_LOG_FUNCTION_NOARGS ();
m_defaultTtl = ttl;
}
void
Ipv4L3ClickProtocol::SetupLoopback (void)
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
Ptr<LoopbackNetDevice> device = 0;
// First check whether an existing LoopbackNetDevice exists on the node
for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
{
if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
{
break;
}
}
if (device == 0)
{
device = CreateObject<LoopbackNetDevice> ();
m_node->AddDevice (device);
}
interface->SetDevice (device);
interface->SetNode (m_node);
Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
interface->AddAddress (ifaceAddr);
uint32_t index = AddIpv4Interface (interface);
Ptr<Node> node = GetObject<Node> ();
node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
Ipv4L3ClickProtocol::PROT_NUMBER, device);
interface->SetUp ();
if (m_routingProtocol != 0)
{
m_routingProtocol->NotifyInterfaceUp (index);
}
}
Ptr<Socket>
Ipv4L3ClickProtocol::CreateRawSocket (void)
{
NS_LOG_FUNCTION (this);
Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
socket->SetNode (m_node);
m_sockets.push_back (socket);
return socket;
}
void
Ipv4L3ClickProtocol::DeleteRawSocket (Ptr<Socket> socket)
{
NS_LOG_FUNCTION (this << socket);
for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
{
if ((*i) == socket)
{
m_sockets.erase (i);
return;
}
}
return;
}
void
Ipv4L3ClickProtocol::SetNode (Ptr<Node> node)
{
m_node = node;
// Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
SetupLoopback ();
}
bool
Ipv4L3ClickProtocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
{
NS_LOG_FUNCTION (this << i << address);
Ptr<Ipv4Interface> interface = GetInterface (i);
bool retVal = interface->AddAddress (address);
if (m_routingProtocol != 0)
{
m_routingProtocol->NotifyAddAddress (i, address);
}
return retVal;
}
Ipv4InterfaceAddress
Ipv4L3ClickProtocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
{
NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
return interface->GetAddress (addressIndex);
}
uint32_t
Ipv4L3ClickProtocol::GetNAddresses (uint32_t interface) const
{
NS_LOG_FUNCTION (this << interface);
Ptr<Ipv4Interface> iface = GetInterface (interface);
return iface->GetNAddresses ();
}
bool
Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
{
NS_LOG_FUNCTION (this << i << addressIndex);
Ptr<Ipv4Interface> interface = GetInterface (i);
Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
if (address != Ipv4InterfaceAddress ())
{
if (m_routingProtocol != 0)
{
m_routingProtocol->NotifyRemoveAddress (i, address);
}
return true;
}
return false;
}
Ipv4Address
Ipv4L3ClickProtocol::SelectSourceAddress (Ptr<const NetDevice> device,
Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
{
NS_LOG_FUNCTION (device << dst << scope);
Ipv4Address addr ("0.0.0.0");
Ipv4InterfaceAddress iaddr;
bool found = false;
if (device != 0)
{
int32_t i = GetInterfaceForDevice (device);
NS_ASSERT_MSG (i >= 0, "No device found on node");
for (uint32_t j = 0; j < GetNAddresses (i); j++)
{
iaddr = GetAddress (i, j);
if (iaddr.IsSecondary ()) continue;
if (iaddr.GetScope () > scope) continue;
if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
{
return iaddr.GetLocal ();
}
if (!found)
{
addr = iaddr.GetLocal ();
found = true;
}
}
}
if (found)
{
return addr;
}
// Iterate among all interfaces
for (uint32_t i = 0; i < GetNInterfaces (); i++)
{
for (uint32_t j = 0; j < GetNAddresses (i); j++)
{
iaddr = GetAddress (i, j);
if (iaddr.IsSecondary ()) continue;
if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
&& iaddr.GetScope () <= scope)
{
return iaddr.GetLocal ();
}
}
}
NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
<< scope << ", returning 0");
return addr;
}
void
Ipv4L3ClickProtocol::SetMetric (uint32_t i, uint16_t metric)
{
NS_LOG_FUNCTION (i << metric);
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetMetric (metric);
}
uint16_t
Ipv4L3ClickProtocol::GetMetric (uint32_t i) const
{
NS_LOG_FUNCTION (i);
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetMetric ();
}
uint16_t
Ipv4L3ClickProtocol::GetMtu (uint32_t i) const
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->GetDevice ()->GetMtu ();
}
bool
Ipv4L3ClickProtocol::IsUp (uint32_t i) const
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv4Interface> interface = GetInterface (i);
return interface->IsUp ();
}
void
Ipv4L3ClickProtocol::SetUp (uint32_t i)
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetUp ();
if (m_routingProtocol != 0)
{
m_routingProtocol->NotifyInterfaceUp (i);
}
}
void
Ipv4L3ClickProtocol::SetDown (uint32_t ifaceIndex)
{
NS_LOG_FUNCTION (this << ifaceIndex);
Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
interface->SetDown ();
if (m_routingProtocol != 0)
{
m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
}
}
bool
Ipv4L3ClickProtocol::IsForwarding (uint32_t i) const
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv4Interface> interface = GetInterface (i);
NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
return interface->IsForwarding ();
}
void
Ipv4L3ClickProtocol::SetForwarding (uint32_t i, bool val)
{
NS_LOG_FUNCTION (this << i);
Ptr<Ipv4Interface> interface = GetInterface (i);
interface->SetForwarding (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);
}
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),
ArpL3Protocol::PROT_NUMBER, device);
Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
interface->SetNode (m_node);
interface->SetDevice (device);
interface->SetForwarding (m_ipForward);
return AddIpv4Interface (interface);
}
uint32_t
Ipv4L3ClickProtocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
{
NS_LOG_FUNCTION (this << interface);
uint32_t index = m_interfaces.size ();
m_interfaces.push_back (interface);
return index;
}
// XXX when should we set ip_id? check whether we are incrementing
// m_identification on packets that may later be dropped in this stack
// and whether that deviates from Linux
Ipv4Header
Ipv4L3ClickProtocol::BuildHeader (
Ipv4Address source,
Ipv4Address destination,
uint8_t protocol,
uint16_t payloadSize,
uint8_t ttl,
bool mayFragment)
{
NS_LOG_FUNCTION_NOARGS ();
Ipv4Header ipHeader;
ipHeader.SetSource (source);
ipHeader.SetDestination (destination);
ipHeader.SetProtocol (protocol);
ipHeader.SetPayloadSize (payloadSize);
ipHeader.SetTtl (ttl);
if (mayFragment == true)
{
ipHeader.SetMayFragment ();
ipHeader.SetIdentification (m_identification);
m_identification++;
}
else
{
ipHeader.SetDontFragment ();
// TBD: set to zero here; will cause traces to change
ipHeader.SetIdentification (m_identification);
m_identification++;
}
if (Node::ChecksumEnabled ())
{
ipHeader.EnableChecksum ();
}
return ipHeader;
}
void
Ipv4L3ClickProtocol::Send (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
uint8_t protocol,
Ptr<Ipv4Route> route)
{
NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
Ipv4Header ipHeader;
bool mayFragment = true;
uint8_t ttl = m_defaultTtl;
SocketIpTtlTag tag;
bool found = packet->RemovePacketTag (tag);
if (found)
{
ttl = tag.GetTtl ();
}
ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (m_routingProtocol);
if (Node::ChecksumEnabled ())
{
ipHeader.EnableChecksum ();
}
packet->AddHeader (ipHeader);
click->Send (packet->Copy (), source, destination);
return;
}
void
Ipv4L3ClickProtocol::SendDown (Ptr<Packet> p, int ifid)
{
// Called by Ipv4ClickRouting.
// NetDevice::Send () attaches ethernet headers,
// so the one that Click attaches isn't required
// but we need the destination address and
// protocol values from the header.
Ptr<NetDevice> netdev = GetNetDevice (ifid);
EthernetHeader header;
p->RemoveHeader (header);
uint16_t protocol;
if (header.GetLengthType () <= 1500)
{
LlcSnapHeader llc;
p->RemoveHeader (llc);
protocol = llc.GetType ();
}
else
{
protocol = header.GetLengthType ();
}
// Use the destination address and protocol obtained
// from above to send the packet.
netdev->Send (p, header.GetDestination (), protocol);
}
void
Ipv4L3ClickProtocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION (this << device << p << from << to);
Ptr<Packet> packet = p->Copy ();
// Add an ethernet frame. This allows
// Click to work with csma and wifi
EthernetHeader hdr;
hdr.SetSource (Mac48Address::ConvertFrom (from));
hdr.SetDestination (Mac48Address::ConvertFrom (to));
hdr.SetLengthType (protocol);
packet->AddHeader (hdr);
Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (GetRoutingProtocol ());
click->Receive (packet->Copy (), Mac48Address::ConvertFrom (device->GetAddress ()), Mac48Address::ConvertFrom (to));
}
void
Ipv4L3ClickProtocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
{
NS_LOG_FUNCTION (this << packet << &ip);
Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
m_localDeliverTrace (ip, packet, iif);
Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
if (protocol != 0)
{
// we need to make a copy in the unlikely event we hit the
// RX_ENDPOINT_UNREACH codepath
Ptr<Packet> copy = p->Copy ();
enum Ipv4L4Protocol::RxStatus status =
protocol->Receive (p, ip, GetInterface (iif));
switch (status) {
case Ipv4L4Protocol::RX_OK:
// fall through
case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
// fall through
case Ipv4L4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
if (ip.GetDestination ().IsBroadcast () == true ||
ip.GetDestination ().IsMulticast () == true)
{
break; // Do not reply to broadcast or multicast
}
// Another case to suppress ICMP is a subnet-directed broadcast
bool subnetDirected = false;
for (uint32_t i = 0; i < GetNAddresses (iif); i++)
{
Ipv4InterfaceAddress addr = GetAddress (iif, i);
if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination().CombineMask (addr.GetMask ()) &&
ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
{
subnetDirected = true;
}
}
if (subnetDirected == false)
{
GetIcmp ()->SendDestUnreachPort (ip, copy);
}
}
}
}
Ptr<Icmpv4L4Protocol>
Ipv4L3ClickProtocol::GetIcmp (void) const
{
Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
if (prot != 0)
{
return prot->GetObject<Icmpv4L4Protocol> ();
}
else
{
return 0;
}
}
void
Ipv4L3ClickProtocol::Insert(Ptr<Ipv4L4Protocol> protocol)
{
m_protocols.push_back (protocol);
}
Ptr<Ipv4L4Protocol>
Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
{
for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
if ((*i)->GetProtocolNumber () == protocolNumber)
{
return *i;
}
}
return 0;
}
} // namespace ns3
#endif // NS3_CLICK

View File

@@ -0,0 +1,270 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//
// Copyright (c) 2006 Georgia Tech Research Corporation
//
// 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: George F. Riley <riley@ece.gatech.edu>
// Author: Lalith Suresh <suresh.lalith@gmail.com>
//
#ifndef IPV4_L3_CLICK_PROTOCOL_H
#define IPV4_L3_CLICK_PROTOCOL_H
#include "ns3/ipv4.h"
#include "ns3/net-device.h"
#include "ns3/packet.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/traced-callback.h"
#include "ns3/ipv4-interface.h"
#include "ns3/log.h"
namespace ns3 {
class Packet;
class NetDevice;
class Ipv4Interface;
class Ipv4Address;
class Ipv4Header;
class Ipv4RoutingTableEntry;
class Ipv4Route;
class Node;
class Socket;
class Ipv4RawSocketImpl;
class Ipv4L4Protocol;
class Icmpv4L4Protocol;
/**
* \brief Implement the Ipv4 layer specifically for Click nodes
* to allow a clean integration of Click.
*
* This is code is mostly repeated from the Ipv4L3Protocol implementation.
* Changes include:
* - A stripped down version of Send().
* - A stripped down version of Receive().
* - A public version of LocalDeliver().
* - Modifications to AddInterface().
*/
class Ipv4L3ClickProtocol : public Ipv4
{
#ifdef NS3_CLICK
public:
static TypeId GetTypeId (void);
/**
* Protocol number for Ipv4 L3 (0x0800).
*/
static const uint16_t PROT_NUMBER;
Ipv4L3ClickProtocol();
virtual ~Ipv4L3ClickProtocol();
/**
* \param protocol a template for the protocol to add to this L4 Demux.
* \returns the L4Protocol effectively added.
*
* Invoke Copy on the input template to get a copy of the input
* protocol which can be used on the Node on which this L4 Demux
* is running. The new L4Protocol is registered internally as
* a working L4 Protocol and returned from this method.
* The caller does not get ownership of the returned pointer.
*/
void Insert(Ptr<Ipv4L4Protocol> protocol);
/**
* \param protocolNumber number of protocol to lookup
* in this L4 Demux
* \returns a matching L4 Protocol
*
* This method is typically called by lower layers
* to forward packets up the stack to the right protocol.
* It is also called from NodeImpl::GetUdp for example.
*/
Ptr<Ipv4L4Protocol> GetProtocol(int protocolNumber) const;
/**
* \param ttl default ttl to use
*
* When we need to send an ipv4 packet, we use this default
* ttl value.
*/
void SetDefaultTtl (uint8_t ttl);
/**
* \param packet packet to send
* \param source source address of packet
* \param destination address of packet
* \param protocol number of packet
* \param route route entry
*
* Higher-level layers call this method to send a packet
* to Click
*/
void Send (Ptr<Packet> packet, Ipv4Address source,
Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route);
/**
* \param packet packet to send down the stack
* \param ifid interface to be used for sending down packet
*
* Ipv4ClickRouting calls this method to send a packet further
* down the stack
*/
void SendDown (Ptr<Packet> packet, int ifid);
/**
* Lower layer calls this method to send a packet to Click
* \param device network device
* \param p the packet
* \param protocol protocol value
* \param from address of the correspondant
* \param to address of the destination
* \param packetType type of the packet
*/
void Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType);
/**
* Ipv4ClickRouting calls this to locally deliver a packet
* \param p the packet
* \param ip The Ipv4Header of the packet
* \param iif The interface on which the packet was received
*/
void LocalDeliver (Ptr<const Packet> p, Ipv4Header const&ip, uint32_t iif);
/**
* Get a pointer to the i'th Ipv4Interface
* \param i index of interface, pointer to which is to be returned
* \returns Pointer to the i'th Ipv4Interface if any.
*/
Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
/**
* Adds an Ipv4Interface to the interfaces list
* \param interface Pointer to the Ipv4Interface to be added
* \returns Index of the device which was added
*/
uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
/**
* Calls m_node = node and sets up Loopback if needed
* \param node Pointer to the node
*/
void SetNode (Ptr<Node> node);
/**
* Returns the Icmpv4L4Protocol for the node
* \returns Icmpv4L4Protocol instance of the node
*/
Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
/**
* Sets up a Loopback device
*/
void SetupLoopback (void);
/**
* Creates a raw-socket
* \returns Pointer to the created socket
*/
Ptr<Socket> CreateRawSocket (void);
/**
* Deletes a particular raw socket
* \param socket Pointer of socket to be deleted
*/
void DeleteRawSocket (Ptr<Socket> socket);
// functions defined in base class Ipv4
void SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol);
Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (void) const;
Ptr<NetDevice> GetNetDevice (uint32_t i);
uint32_t AddInterface (Ptr<NetDevice> device);
uint32_t GetNInterfaces (void) const;
int32_t GetInterfaceForAddress (Ipv4Address addr) const;
int32_t GetInterfaceForPrefix (Ipv4Address addr, Ipv4Mask mask) const;
int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
bool IsDestinationAddress (Ipv4Address address, uint32_t iif) const;
bool AddAddress (uint32_t i, Ipv4InterfaceAddress address);
Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
uint32_t GetNAddresses (uint32_t interface) const;
bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex);
Ipv4Address SelectSourceAddress (Ptr<const NetDevice> device,
Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope);
void SetMetric (uint32_t i, uint16_t metric);
uint16_t GetMetric (uint32_t i) const;
uint16_t GetMtu (uint32_t i) const;
bool IsUp (uint32_t i) const;
void SetUp (uint32_t i);
void SetDown (uint32_t i);
bool IsForwarding (uint32_t i) const;
void SetForwarding (uint32_t i, bool val);
void SetPromisc(uint32_t i);
protected:
virtual void DoDispose (void);
/**
* This function will notify other components connected to the node that a new stack member is now connected
* This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
*/
virtual void NotifyNewAggregate ();
private:
Ipv4Header BuildHeader (
Ipv4Address source,
Ipv4Address destination,
uint8_t protocol,
uint16_t payloadSize,
uint8_t ttl,
bool mayFragment);
virtual void SetIpForward (bool forward);
virtual bool GetIpForward (void) const;
virtual void SetWeakEsModel (bool model);
virtual bool GetWeakEsModel (void) const;
typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
Ptr<Ipv4RoutingProtocol> m_routingProtocol;
bool m_ipForward;
bool m_weakEsModel;
L4List_t m_protocols;
Ipv4InterfaceList m_interfaces;
uint8_t m_defaultTtl;
uint16_t m_identification;
Ptr<Node> m_node;
TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_sendOutgoingTrace;
TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_unicastForwardTrace;
TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_localDeliverTrace;
SocketList m_sockets;
std::vector<bool> m_promiscDeviceList;
#endif //NS3_CLICK
};
} //namespace ns3
#endif // IPV4_L3_CLICK_ROUTING_H

View File

@@ -0,0 +1,222 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2010 Lalith Suresh
*
* 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
*
* Authors: Lalith Suresh <suresh.lalith@gmail.com>
*/
#ifdef NS3_CLICK
#include "ns3/test.h"
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/simple-net-device.h"
#include "ns3/ipv4-click-routing.h"
#include "ns3/icmpv4-l4-protocol.h"
#include "ns3/arp-l3-protocol.h"
#include <click/simclick.h>
namespace ns3 {
static void
AddClickInternetStack (Ptr<Node> node)
{
// Setup ArpL3Protocol
Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
node->AggregateObject (arp);
// Setup Ipv4L3Protocol
Ptr<Ipv4L3Protocol> ipv4l3 = CreateObject<Ipv4L3Protocol> ();
node->AggregateObject (ipv4l3);
// Setup Click instance
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> click = CreateObject<Ipv4ClickRouting> ();
click->SetClickFile ("examples/click/nsclick-lan-single-interface.click");
ipv4->SetRoutingProtocol (click);
}
static void
AddNetworkDevice (Ptr<Node> node, Mac48Address macaddr, Ipv4Address ipv4addr, Ipv4Mask ipv4mask)
{
Ptr<SimpleNetDevice> rxDev1;
rxDev1 = CreateObject<SimpleNetDevice> ();
rxDev1->SetAddress (Mac48Address(macaddr));
node->AddDevice (rxDev1);
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (ipv4addr, ipv4mask);
ipv4->AddAddress (netdev_idx, ipv4Addr);
ipv4->SetUp (netdev_idx);
}
class ClickIfidFromNameTest : public TestCase
{
public:
ClickIfidFromNameTest ();
virtual void DoRun ();
};
ClickIfidFromNameTest::ClickIfidFromNameTest ()
: TestCase ("Test SIMCLICK_IFID_FROM_NAME")
{
}
void
ClickIfidFromNameTest::DoRun ()
{
Ptr<Node> node = CreateObject<Node> ();
AddClickInternetStack (node);
AddNetworkDevice (node, Mac48Address("00:00:00:00:00:01"), Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0"));
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (ipv4->GetRoutingProtocol ());
click->DoStart ();
int ret;
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "tap0");
NS_TEST_EXPECT_MSG_EQ (ret, 0, "tap0 is interface 0");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "tun0");
NS_TEST_EXPECT_MSG_EQ (ret, 0, "tun0 is interface 0");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "eth0");
NS_TEST_EXPECT_MSG_EQ (ret, 1, "Eth0 is interface 1");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "tap1");
NS_TEST_EXPECT_MSG_EQ (ret, 0, "tap1 is interface 0");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "tun1");
NS_TEST_EXPECT_MSG_EQ (ret, 0, "tun1 is interface 0");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IFID_FROM_NAME, "eth1");
NS_TEST_EXPECT_MSG_EQ (ret, -1, "No eth1 on node");
}
class ClickIpMacAddressFromNameTest : public TestCase
{
public:
ClickIpMacAddressFromNameTest ();
virtual void DoRun ();
};
ClickIpMacAddressFromNameTest::ClickIpMacAddressFromNameTest ()
: TestCase ("Test SIMCLICK_IPADDR_FROM_NAME")
{
}
void
ClickIpMacAddressFromNameTest::DoRun ()
{
Ptr<Node> node = CreateObject<Node> ();
AddClickInternetStack (node);
AddNetworkDevice (node, Mac48Address("00:00:00:00:00:01"), Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0"));
AddNetworkDevice (node, Mac48Address("00:00:00:00:00:02"), Ipv4Address ("10.1.1.2"), Ipv4Mask ("255.255.255.0"));
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (ipv4->GetRoutingProtocol ());
click->DoStart ();
int ret = 0;
char *buf = NULL;
buf = new char [255];
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IPADDR_FROM_NAME, "eth0", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp (buf, "10.1.1.1"), 0, "eth0 has IP 10.1.1.1");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_MACADDR_FROM_NAME, "eth0", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp (buf, "00:00:00:00:00:01"), 0, "eth0 has Mac Address 00:00:00:00:00:01");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IPADDR_FROM_NAME, "eth1", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp(buf, "10.1.1.2"), 0, "eth1 has IP 10.1.1.2");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_MACADDR_FROM_NAME, "eth1", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp (buf, "00:00:00:00:00:02"), 0, "eth0 has Mac Address 00:00:00:00:00:02");
// Not sure how to test the below case, because the Ipv4ClickRouting code is to ASSERT for such inputs
// ret = simclick_sim_command (click->m_simNode, SIMCLICK_IPADDR_FROM_NAME, "eth2", buf, 255);
// NS_TEST_EXPECT_MSG_EQ (buf, NULL, "No eth2");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IPADDR_FROM_NAME, "tap0", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp(buf, "127.0.0.1"), 0, "tun0 has IP 127.0.0.1");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_MACADDR_FROM_NAME, "tap0", buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp(buf, "00:00:00:00:00:00"), 0, "tun0 has IP 127.0.0.1");
delete [] buf;
}
class ClickTrivialTest : public TestCase
{
public:
ClickTrivialTest ();
virtual void DoRun ();
};
ClickTrivialTest::ClickTrivialTest ()
: TestCase ("Test SIMCLICK_GET_NODE_NAME and SIMCLICK_IF_READY")
{
}
void
ClickTrivialTest::DoRun ()
{
Ptr<Node> node = CreateObject<Node> ();
AddClickInternetStack (node);
AddNetworkDevice (node, Mac48Address("00:00:00:00:00:01"), Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0"));
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (ipv4->GetRoutingProtocol ());
click->SetNodeName ("myNode");
click->DoStart ();
int ret = 0;
char *buf = NULL;
buf = new char [255];
ret = simclick_sim_command (click->m_simNode, SIMCLICK_GET_NODE_NAME, buf, 255);
NS_TEST_EXPECT_MSG_EQ (strcmp (buf, "myNode"), 0, "Node name is Node");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IF_READY, 0);
NS_TEST_EXPECT_MSG_EQ (ret, 1, "tap0 is ready");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IF_READY, 1);
NS_TEST_EXPECT_MSG_EQ (ret, 1, "eth0 is ready");
ret = simclick_sim_command (click->m_simNode, SIMCLICK_IF_READY, 2);
NS_TEST_EXPECT_MSG_EQ (ret, -1, "eth1 does not exist, so return -1");
delete [] buf;
ret = 1;
}
class ClickIfidFromNameTestSuite : public TestSuite
{
public:
ClickIfidFromNameTestSuite () : TestSuite ("routing-click", UNIT)
{
AddTestCase (new ClickTrivialTest);
AddTestCase (new ClickIfidFromNameTest);
AddTestCase (new ClickIpMacAddressFromNameTest);
}
} g_ipv4ClickRoutingTestSuite;
} // namespace ns3
#endif // NS3_CLICK

1
src/routing/click/waf vendored Normal file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../waf "$@"

93
src/routing/click/wscript Normal file
View File

@@ -0,0 +1,93 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
import os
import Options
def set_options(opt):
opt.add_option('--with-nsclick',
help=('Path to Click source for NS-3 Click Integration support'),
dest='with_nsclick', default=None)
def configure(conf):
if Options.options.with_nsclick:
if os.path.isdir(Options.options.with_nsclick):
conf.check_message("libnsclick.so location", '', True, ("%s (given)" % Options.options.with_nsclick))
conf.env['WITH_NSCLICK'] = os.path.abspath(Options.options.with_nsclick)
else:
nsclick_dir = os.path.join('..','click')
if os.path.isdir(nsclick_dir):
conf.check_message("click location", '', True, ("%s (guessed)" % nsclick_dir))
conf.env['WITH_NSCLICK'] = os.path.abspath(nsclick_dir)
del nsclick_dir
if not conf.env['WITH_NSCLICK']:
conf.check_message("click location", '', False)
conf.report_optional_feature("nsclick", "NS-3 Click Integration", False,
"nsclick not enabled (see option --with-nsclick)")
return
test_code = '''
#include<sys/types.h>
#include<sys/time.h>
#include<click/simclick.h>
#ifdef __cplusplus
extern "C" {
#endif
int simclick_sim_send(simclick_node_t *sim,int ifid,int type, const unsigned char* data,int len,simclick_simpacketinfo *pinfo)
{
return 0;
}
int simclick_sim_command(simclick_node_t *sim, int cmd, ...)
{
return 0;
}
#ifdef __cplusplus
}
#endif
int main()
{
return 0;
}
'''
conf.env['DL'] = conf.check(mandatory=True, lib='dl', define_name='DL', uselib='DL')
conf.env.append_value('NS3_MODULE_PATH',os.path.abspath(os.path.join(conf.env['WITH_NSCLICK'],'ns')))
conf.env['CPPPATH_NSCLICK'] = [os.path.abspath(os.path.join(conf.env['WITH_NSCLICK'],'include'))]
conf.env['LIBPATH_NSCLICK'] = [os.path.abspath(os.path.join(conf.env['WITH_NSCLICK'],'ns'))]
conf.env['NSCLICK'] = conf.check(fragment=test_code, lib='nsclick', uselib='NSCLICK DL')
conf.report_optional_feature("nsclick", "NS-3 Click Integration",
conf.env['NSCLICK'], "nsclick library not found")
if conf.env['NSCLICK']:
conf.env.append_value('CXXDEFINES', 'NS3_CLICK')
conf.env.append_value('CPPPATH', conf.env['CPPPATH_NSCLICK'])
def build(bld):
module = bld.create_ns3_module('click', ['internet-stack', 'contrib'])
module.includes = '. CPPPATH_NSCLICK'
module.source = [
'model/ipv4-click-routing.cc',
'model/ipv4-l3-click-protocol.cc',
'test/ipv4-click-routing-test.cc',
'helper/click-internet-stack-helper.cc',
]
if bld.env['NSCLICK'] and bld.env['DL']:
module.uselib = 'NSCLICK DL'
headers = bld.new_task_gen('ns3header')
headers.module = 'click'
headers.source = [
'model/ipv4-click-routing.h',
'model/ipv4-l3-click-protocol.h',
'helper/click-internet-stack-helper.h',
]
if bld.env['ENABLE_EXAMPLES']:
bld.add_subdirs('examples')