--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/doc/click.h Wed Feb 23 17:50:31 2011 +0000
@@ -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.
+*
+*
+*/
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-ip-router.click Wed Feb 23 17:50:31 2011 +0000
@@ -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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-lan-single-interface.click Wed Feb 23 17:50:31 2011 +0000
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-raw-wlan.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-routing-node0.click Wed Feb 23 17:50:31 2011 +0000
@@ -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;
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-routing-node2.click Wed Feb 23 17:50:31 2011 +0000
@@ -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;
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-routing.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-simple-lan.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-udp-client-server-csma.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-udp-client-server-wifi.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/nsclick-wifi-single-interface.click Wed Feb 23 17:50:31 2011 +0000
@@ -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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/examples/wscript Wed Feb 23 17:50:31 2011 +0000
@@ -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'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/helper/click-internet-stack-helper.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/helper/click-internet-stack-helper.h Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/model/ipv4-click-routing.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/model/ipv4-click-routing.h Wed Feb 23 17:50:31 2011 +0000
@@ -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__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/model/ipv4-l3-click-protocol.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/model/ipv4-l3-click-protocol.h Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/test/ipv4-click-routing-test.cc Wed Feb 23 17:50:31 2011 +0000
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/waf Wed Feb 23 17:50:31 2011 +0000
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/click/wscript Wed Feb 23 17:50:31 2011 +0000
@@ -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')