ns-3-simu_zebra_ipv6-2nd
changeset 4775:fc2c29a13125
After support for TD/NINA on zebra-0.95
line diff
1.1 --- a/.hgignore Mon Sep 07 15:45:12 2009 +0200
1.2 +++ b/.hgignore Thu Oct 01 23:37:18 2009 +0900
1.3 @@ -33,4 +33,7 @@
1.4 \.patch$
1.5 \.diff$
1.6 \.tr$
1.7 -\#[^\#/]+\#$
1.8 \ No newline at end of file
1.9 +\#[^\#/]+\#$
1.10 +files-*
1.11 +elf-loader-cache
1.12 +G.*
2.1 --- a/bindings/python/ns3_module_contrib.py Mon Sep 07 15:45:12 2009 +0200
2.2 +++ b/bindings/python/ns3_module_contrib.py Thu Oct 01 23:37:18 2009 +0900
2.3 @@ -39,6 +39,21 @@
2.4 module.add_class('Gnuplot3dDataset', parent=root_module['ns3::GnuplotDataset'])
2.5 ## gnuplot.h: ns3::Gnuplot3dFunction [class]
2.6 module.add_class('Gnuplot3dFunction', parent=root_module['ns3::GnuplotDataset'])
2.7 + ## pyviz.h: ns3::PyViz [class]
2.8 + module.add_class('PyViz')
2.9 + ## pyviz.h: ns3::PyViz::LastPacketsSample [struct]
2.10 + module.add_class('LastPacketsSample', outer_class=root_module['ns3::PyViz'])
2.11 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics [struct]
2.12 + module.add_class('NetDeviceStatistics', outer_class=root_module['ns3::PyViz'])
2.13 + ## pyviz.h: ns3::PyViz::NodeStatistics [struct]
2.14 + module.add_class('NodeStatistics', outer_class=root_module['ns3::PyViz'])
2.15 + ## pyviz.h: ns3::PyViz::PacketDropSample [struct]
2.16 + module.add_class('PacketDropSample', outer_class=root_module['ns3::PyViz'])
2.17 + ## pyviz.h: ns3::PyViz::PacketSample [struct]
2.18 + module.add_class('PacketSample', outer_class=root_module['ns3::PyViz'])
2.19 + ## pyviz.h: ns3::PyViz::TransmissionSample [struct]
2.20 + module.add_class('TransmissionSample', outer_class=root_module['ns3::PyViz'])
2.21 +
2.22
2.23 ## Register a nested module for the namespace Config
2.24
2.25 @@ -105,6 +120,13 @@
2.26 register_Ns3Gnuplot2dFunction_methods(root_module, root_module['ns3::Gnuplot2dFunction'])
2.27 register_Ns3Gnuplot3dDataset_methods(root_module, root_module['ns3::Gnuplot3dDataset'])
2.28 register_Ns3Gnuplot3dFunction_methods(root_module, root_module['ns3::Gnuplot3dFunction'])
2.29 + register_Ns3PyViz_methods(root_module, root_module['ns3::PyViz'])
2.30 + register_Ns3PyVizLastPacketsSample_methods(root_module, root_module['ns3::PyViz::LastPacketsSample'])
2.31 + register_Ns3PyVizNetDeviceStatistics_methods(root_module, root_module['ns3::PyViz::NetDeviceStatistics'])
2.32 + register_Ns3PyVizNodeStatistics_methods(root_module, root_module['ns3::PyViz::NodeStatistics'])
2.33 + register_Ns3PyVizPacketDropSample_methods(root_module, root_module['ns3::PyViz::PacketDropSample'])
2.34 + register_Ns3PyVizPacketSample_methods(root_module, root_module['ns3::PyViz::PacketSample'])
2.35 + register_Ns3PyVizTransmissionSample_methods(root_module, root_module['ns3::PyViz::TransmissionSample'])
2.36 return
2.37
2.38 def register_Ns3DelayJitterEstimation_methods(root_module, cls):
2.39 @@ -500,3 +522,131 @@
2.40 def register_functions_ns3_olsr(module, root_module):
2.41 return
2.42
2.43 +def register_Ns3PyViz_methods(root_module, cls):
2.44 + ## pyviz.h: ns3::PyViz::PyViz(ns3::PyViz const & arg0) [copy constructor]
2.45 + cls.add_constructor([param('ns3::PyViz const &', 'arg0')])
2.46 + ## pyviz.h: ns3::PyViz::PyViz() [constructor]
2.47 + cls.add_constructor([])
2.48 + ## pyviz.h: ns3::PyViz::LastPacketsSample ns3::PyViz::GetLastPackets(uint32_t nodeId) const [member function]
2.49 + cls.add_method('GetLastPackets',
2.50 + 'ns3::PyViz::LastPacketsSample',
2.51 + [param('uint32_t', 'nodeId')],
2.52 + is_const=True)
2.53 + ## pyviz.h: std::vector<ns3::PyViz::NodeStatistics,std::allocator<ns3::PyViz::NodeStatistics> > ns3::PyViz::GetNodesStatistics() const [member function]
2.54 + cls.add_method('GetNodesStatistics',
2.55 + 'std::vector< ns3::PyViz::NodeStatistics >',
2.56 + [],
2.57 + is_const=True)
2.58 + ## pyviz.h: std::vector<ns3::PyViz::PacketDropSample,std::allocator<ns3::PyViz::PacketDropSample> > ns3::PyViz::GetPacketDropSamples() const [member function]
2.59 + cls.add_method('GetPacketDropSamples',
2.60 + 'std::vector< ns3::PyViz::PacketDropSample >',
2.61 + [],
2.62 + is_const=True)
2.63 + ## pyviz.h: std::vector<std::string, std::allocator<std::string> > ns3::PyViz::GetPauseMessages() const [member function]
2.64 + cls.add_method('GetPauseMessages',
2.65 + 'std::vector< std::string >',
2.66 + [],
2.67 + is_const=True)
2.68 + ## pyviz.h: std::vector<ns3::PyViz::TransmissionSample,std::allocator<ns3::PyViz::TransmissionSample> > ns3::PyViz::GetTransmissionSamples() const [member function]
2.69 + cls.add_method('GetTransmissionSamples',
2.70 + 'std::vector< ns3::PyViz::TransmissionSample >',
2.71 + [],
2.72 + is_const=True)
2.73 + ## pyviz.h: static void ns3::PyViz::Pause(std::string const & message) [member function]
2.74 + cls.add_method('Pause',
2.75 + 'void',
2.76 + [param('std::string const &', 'message')],
2.77 + is_static=True)
2.78 + ## pyviz.h: void ns3::PyViz::RegisterDropTracePath(std::string const & tracePath) [member function]
2.79 + cls.add_method('RegisterDropTracePath',
2.80 + 'void',
2.81 + [param('std::string const &', 'tracePath')])
2.82 + ## pyviz.h: void ns3::PyViz::SetNodesOfInterest(std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > nodes) [member function]
2.83 + cls.add_method('SetNodesOfInterest',
2.84 + 'void',
2.85 + [param('std::set< unsigned int >', 'nodes')])
2.86 + ## pyviz.h: void ns3::PyViz::SimulatorRunUntil(ns3::Time time) [member function]
2.87 + cls.add_method('SimulatorRunUntil',
2.88 + 'void',
2.89 + [param('ns3::Time', 'time')])
2.90 + return
2.91 +
2.92 +def register_Ns3PyVizLastPacketsSample_methods(root_module, cls):
2.93 + ## pyviz.h: ns3::PyViz::LastPacketsSample::LastPacketsSample() [constructor]
2.94 + cls.add_constructor([])
2.95 + ## pyviz.h: ns3::PyViz::LastPacketsSample::LastPacketsSample(ns3::PyViz::LastPacketsSample const & arg0) [copy constructor]
2.96 + cls.add_constructor([param('ns3::PyViz::LastPacketsSample const &', 'arg0')])
2.97 + ## pyviz.h: ns3::PyViz::LastPacketsSample::lastDroppedPackets [variable]
2.98 + cls.add_instance_attribute('lastDroppedPackets', 'std::vector< ns3::PyViz::PacketSample >', is_const=False)
2.99 + ## pyviz.h: ns3::PyViz::LastPacketsSample::lastReceivedPackets [variable]
2.100 + cls.add_instance_attribute('lastReceivedPackets', 'std::vector< ns3::PyViz::PacketSample >', is_const=False)
2.101 + ## pyviz.h: ns3::PyViz::LastPacketsSample::lastTransmittedPackets [variable]
2.102 + cls.add_instance_attribute('lastTransmittedPackets', 'std::vector< ns3::PyViz::PacketSample >', is_const=False)
2.103 + return
2.104 +
2.105 +def register_Ns3PyVizNetDeviceStatistics_methods(root_module, cls):
2.106 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::NetDeviceStatistics(ns3::PyViz::NetDeviceStatistics const & arg0) [copy constructor]
2.107 + cls.add_constructor([param('ns3::PyViz::NetDeviceStatistics const &', 'arg0')])
2.108 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::NetDeviceStatistics() [constructor]
2.109 + cls.add_constructor([])
2.110 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::receivedBytes [variable]
2.111 + cls.add_instance_attribute('receivedBytes', 'uint64_t', is_const=False)
2.112 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::receivedPackets [variable]
2.113 + cls.add_instance_attribute('receivedPackets', 'uint32_t', is_const=False)
2.114 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::transmittedBytes [variable]
2.115 + cls.add_instance_attribute('transmittedBytes', 'uint64_t', is_const=False)
2.116 + ## pyviz.h: ns3::PyViz::NetDeviceStatistics::transmittedPackets [variable]
2.117 + cls.add_instance_attribute('transmittedPackets', 'uint32_t', is_const=False)
2.118 + return
2.119 +
2.120 +def register_Ns3PyVizNodeStatistics_methods(root_module, cls):
2.121 + ## pyviz.h: ns3::PyViz::NodeStatistics::NodeStatistics() [constructor]
2.122 + cls.add_constructor([])
2.123 + ## pyviz.h: ns3::PyViz::NodeStatistics::NodeStatistics(ns3::PyViz::NodeStatistics const & arg0) [copy constructor]
2.124 + cls.add_constructor([param('ns3::PyViz::NodeStatistics const &', 'arg0')])
2.125 + ## pyviz.h: ns3::PyViz::NodeStatistics::nodeId [variable]
2.126 + cls.add_instance_attribute('nodeId', 'uint32_t', is_const=False)
2.127 + ## pyviz.h: ns3::PyViz::NodeStatistics::statistics [variable]
2.128 + cls.add_instance_attribute('statistics', 'std::vector< ns3::PyViz::NetDeviceStatistics >', is_const=False)
2.129 + return
2.130 +
2.131 +def register_Ns3PyVizPacketDropSample_methods(root_module, cls):
2.132 + ## pyviz.h: ns3::PyViz::PacketDropSample::PacketDropSample() [constructor]
2.133 + cls.add_constructor([])
2.134 + ## pyviz.h: ns3::PyViz::PacketDropSample::PacketDropSample(ns3::PyViz::PacketDropSample const & arg0) [copy constructor]
2.135 + cls.add_constructor([param('ns3::PyViz::PacketDropSample const &', 'arg0')])
2.136 + ## pyviz.h: ns3::PyViz::PacketDropSample::bytes [variable]
2.137 + cls.add_instance_attribute('bytes', 'uint32_t', is_const=False)
2.138 + ## pyviz.h: ns3::PyViz::PacketDropSample::transmitter [variable]
2.139 + cls.add_instance_attribute('transmitter', 'ns3::Ptr< ns3::Node >', is_const=False)
2.140 + return
2.141 +
2.142 +def register_Ns3PyVizPacketSample_methods(root_module, cls):
2.143 + ## pyviz.h: ns3::PyViz::PacketSample::PacketSample() [constructor]
2.144 + cls.add_constructor([])
2.145 + ## pyviz.h: ns3::PyViz::PacketSample::PacketSample(ns3::PyViz::PacketSample const & arg0) [copy constructor]
2.146 + cls.add_constructor([param('ns3::PyViz::PacketSample const &', 'arg0')])
2.147 + ## pyviz.h: ns3::PyViz::PacketSample::device [variable]
2.148 + cls.add_instance_attribute('device', 'ns3::Ptr< ns3::NetDevice >', is_const=False)
2.149 + ## pyviz.h: ns3::PyViz::PacketSample::packet [variable]
2.150 + cls.add_instance_attribute('packet', 'ns3::Ptr< ns3::Packet >', is_const=False)
2.151 + ## pyviz.h: ns3::PyViz::PacketSample::time [variable]
2.152 + cls.add_instance_attribute('time', 'ns3::Time', is_const=False)
2.153 + return
2.154 +
2.155 +def register_Ns3PyVizTransmissionSample_methods(root_module, cls):
2.156 + ## pyviz.h: ns3::PyViz::TransmissionSample::TransmissionSample() [constructor]
2.157 + cls.add_constructor([])
2.158 + ## pyviz.h: ns3::PyViz::TransmissionSample::TransmissionSample(ns3::PyViz::TransmissionSample const & arg0) [copy constructor]
2.159 + cls.add_constructor([param('ns3::PyViz::TransmissionSample const &', 'arg0')])
2.160 + ## pyviz.h: ns3::PyViz::TransmissionSample::bytes [variable]
2.161 + cls.add_instance_attribute('bytes', 'uint32_t', is_const=False)
2.162 + ## pyviz.h: ns3::PyViz::TransmissionSample::channel [variable]
2.163 + cls.add_instance_attribute('channel', 'ns3::Ptr< ns3::Channel >', is_const=False)
2.164 + ## pyviz.h: ns3::PyViz::TransmissionSample::receiver [variable]
2.165 + cls.add_instance_attribute('receiver', 'ns3::Ptr< ns3::Node >', is_const=False)
2.166 + ## pyviz.h: ns3::PyViz::TransmissionSample::transmitter [variable]
2.167 + cls.add_instance_attribute('transmitter', 'ns3::Ptr< ns3::Node >', is_const=False)
2.168 + return
2.169 +
2.170 +
3.1 --- a/bindings/python/wscript Mon Sep 07 15:45:12 2009 +0200
3.2 +++ b/bindings/python/wscript Thu Oct 01 23:37:18 2009 +0900
3.3 @@ -15,6 +15,7 @@
3.4 import Utils
3.5
3.6 ## https://launchpad.net/pybindgen/
3.7 +#REQUIRED_PYBINDGEN_VERSION = (0, 12, 0, 700)
3.8 REQUIRED_PYBINDGEN_VERSION = (0, 11, 0, 697)
3.9 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
3.10
4.1 --- a/src/contrib/wscript Mon Sep 07 15:45:12 2009 +0200
4.2 +++ b/src/contrib/wscript Thu Oct 01 23:37:18 2009 +0900
4.3 @@ -30,6 +30,7 @@
4.4 'attribute-default-iterator.cc',
4.5 'file-config.cc',
4.6 'raw-text-config.cc',
4.7 + 'pyviz.cc',
4.8 ]
4.9
4.10 headers = bld.new_task_gen('ns3header')
4.11 @@ -41,6 +42,7 @@
4.12 'file-config.h',
4.13 'config-store.h',
4.14 'flow-id-tag.h',
4.15 + 'pyviz.h',
4.16 ]
4.17
4.18 if bld.env['ENABLE_GTK_CONFIG_STORE']:
4.19 @@ -54,3 +56,5 @@
4.20 module.uselib = module.uselib + ' LIBXML2'
4.21 else:
4.22 module.uselib = 'LIBXML2'
4.23 +
4.24 + bld.add_subdirs('visualizer')
5.1 --- a/src/helper/internet-stack-helper.cc Mon Sep 07 15:45:12 2009 +0200
5.2 +++ b/src/helper/internet-stack-helper.cc Thu Oct 01 23:37:18 2009 +0900
5.3 @@ -315,6 +315,9 @@
5.4
5.5 CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv6L3Protocol");
5.6 CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv6L4Protocol");
5.7 + ObjectFactory m_tcp6Factory;
5.8 + m_tcp6Factory.SetTypeId ("ns3::Tcp6L4Protocol");
5.9 + node->AggregateObject (m_tcp6Factory.Create<Object> ());
5.10 /* TODO add UdpL4Protocol / TcpL4Protocol for IPv6 */
5.11 Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
5.12 Ptr<Ipv6RoutingProtocol> ipv6Routing = m_routingv6->Create (node);
6.1 --- a/src/helper/ipv6-interface-container.cc Mon Sep 07 15:45:12 2009 +0200
6.2 +++ b/src/helper/ipv6-interface-container.cc Thu Oct 01 23:37:18 2009 +0900
6.3 @@ -87,7 +87,7 @@
6.4
6.5 ipv6 = m_interfaces[other].first;
6.6 routing = routingHelper.GetStaticRouting (ipv6);
6.7 - routing->SetDefaultRoute (routerAddress, m_interfaces[other].second);
6.8 + // routing->SetDefaultRoute (routerAddress, m_interfaces[other].second);
6.9 }
6.10 }
6.11 }
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/src/helper/netlink-socket-helper.cc Thu Oct 01 23:37:18 2009 +0900
7.3 @@ -0,0 +1,30 @@
7.4 +#include "netlink-socket-helper.h"
7.5 +#include "ns3/netlink-socket-factory.h"
7.6 +#include "ns3/netlink-ipv6-routing-table.h"
7.7 +#include "ns3/ipv6-list-routing.h"
7.8 +
7.9 +namespace ns3 {
7.10 +
7.11 +void
7.12 +NetlinkSocketHelper::Install (NodeContainer c)
7.13 +{
7.14 + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
7.15 + {
7.16 + Ptr<Node> node = *i;
7.17 + Ptr<NetlinkSocketFactory> factory = CreateObject<NetlinkSocketFactory> ();
7.18 + node->AggregateObject (factory);
7.19 +
7.20 + Ptr<Ipv6RoutingProtocol> ipv6rp = node->GetObject<Ipv6>()->GetRoutingProtocol ();
7.21 + NS_ASSERT_MSG (ipv6rp, "No routing protocol associated with Ipv6");
7.22 + if (DynamicCast<Ipv6ListRouting> (ipv6rp))
7.23 + {
7.24 + Ptr<Ipv6ListRouting> lrp = DynamicCast<Ipv6ListRouting> (ipv6rp);
7.25 +
7.26 + Ptr<NetlinkIpv6RoutingTable> table = CreateObject<NetlinkIpv6RoutingTable> ();
7.27 + lrp->AddRoutingProtocol (table, -20); // FIXME
7.28 + node->AggregateObject (table);
7.29 + }
7.30 + }
7.31 +}
7.32 +
7.33 +} // namespace ns3
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/src/helper/netlink-socket-helper.h Thu Oct 01 23:37:18 2009 +0900
8.3 @@ -0,0 +1,25 @@
8.4 +#ifndef NETLINK_SOCKET_HELPER_H
8.5 +#define NETLINK_SOCKET_HELPER_H
8.6 +
8.7 +#include "ns3/node-container.h"
8.8 +
8.9 +namespace ns3 {
8.10 +
8.11 +/**
8.12 + * \brief Give ns3::NetlinkSocket powers to ns3::Node.
8.13 + */
8.14 +class NetlinkSocketHelper
8.15 +{
8.16 +public:
8.17 + /**
8.18 + * \param c container of node pointers
8.19 + *
8.20 + * For each node in the input container, aggregate a ns3::NetlinkSocketFactory
8.21 + * object instance.
8.22 + */
8.23 + void Install (NodeContainer c);
8.24 +};
8.25 +
8.26 +} // namespace ns3
8.27 +
8.28 +#endif /* NETLINK_SOCKET_HELPER_H */
9.1 --- a/src/helper/node-container.cc Mon Sep 07 15:45:12 2009 +0200
9.2 +++ b/src/helper/node-container.cc Thu Oct 01 23:37:18 2009 +0900
9.3 @@ -88,6 +88,16 @@
9.4 {
9.5 return m_nodes[i];
9.6 }
9.7 +NodeContainer
9.8 +NodeContainer::Get (uint32_t start, uint32_t end) const
9.9 +{
9.10 + NodeContainer nodes;
9.11 + for (uint32_t i = start; i < end; i++)
9.12 + {
9.13 + nodes.Add (m_nodes[i]);
9.14 + }
9.15 + return nodes;
9.16 +}
9.17 void
9.18 NodeContainer::Create (uint32_t n)
9.19 {
10.1 --- a/src/helper/node-container.h Mon Sep 07 15:45:12 2009 +0200
10.2 +++ b/src/helper/node-container.h Thu Oct 01 23:37:18 2009 +0900
10.3 @@ -91,6 +91,7 @@
10.4 * \returns the requested node pointer.
10.5 */
10.6 Ptr<Node> Get (uint32_t i) const;
10.7 + NodeContainer Get (uint32_t start, uint32_t end) const;
10.8
10.9 /**
10.10 * \param n the number of nodes to create
11.1 --- a/src/helper/wscript Mon Sep 07 15:45:12 2009 +0200
11.2 +++ b/src/helper/wscript Thu Oct 01 23:37:18 2009 +0900
11.3 @@ -37,6 +37,7 @@
11.4 'ping6-helper.cc',
11.5 'process-manager-helper.cc',
11.6 'process-helper.cc',
11.7 + 'netlink-socket-helper.cc',
11.8 ]
11.9
11.10 headers = bld.new_task_gen('ns3header')
11.11 @@ -76,6 +77,7 @@
11.12 'ping6-helper.h',
11.13 'process-manager-helper.h',
11.14 'process-helper.h',
11.15 + 'netlink-socket-helper.h',
11.16 ]
11.17
11.18 env = bld.env_of_name('default')
12.1 --- a/src/internet-stack/ipv6-l3-protocol.cc Mon Sep 07 15:45:12 2009 +0200
12.2 +++ b/src/internet-stack/ipv6-l3-protocol.cc Thu Oct 01 23:37:18 2009 +0900
12.3 @@ -69,7 +69,8 @@
12.4 }
12.5
12.6 Ipv6L3Protocol::Ipv6L3Protocol ()
12.7 - : m_nInterfaces (0)
12.8 + : m_nInterfaces (0),
12.9 + m_acceptRtadvDefrtr(true)
12.10 {
12.11 NS_LOG_FUNCTION_NOARGS ();
12.12 }
12.13 @@ -593,6 +594,13 @@
12.14 m_defaultTtl = ttl;
12.15 }
12.16
12.17 +void Ipv6L3Protocol::SetAcceptRtadvDefrtr(bool flag)
12.18 +{
12.19 + NS_LOG_FUNCTION(this << flag);
12.20 + m_acceptRtadvDefrtr=flag;
12.21 +}
12.22 +
12.23 +
12.24 void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route)
12.25 {
12.26 NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
13.1 --- a/src/internet-stack/ipv6-l3-protocol.h Mon Sep 07 15:45:12 2009 +0200
13.2 +++ b/src/internet-stack/ipv6-l3-protocol.h Thu Oct 01 23:37:18 2009 +0900
13.3 @@ -307,6 +307,8 @@
13.4 */
13.5 void RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter);
13.6
13.7 + void SetAcceptRtadvDefrtr(bool flag);
13.8 +
13.9 protected:
13.10 /**
13.11 * \brief Dispose object.
13.12 @@ -478,6 +480,8 @@
13.13 * \brief List of IPv6 prefix received from RA.
13.14 */
13.15 Ipv6AutoconfiguredPrefixList m_prefixes;
13.16 +
13.17 + bool m_acceptRtadvDefrtr;
13.18 };
13.19
13.20 } /* namespace ns3 */
14.1 --- a/src/internet-stack/ipv6-raw-socket-impl.cc Mon Sep 07 15:45:12 2009 +0200
14.2 +++ b/src/internet-stack/ipv6-raw-socket-impl.cc Thu Oct 01 23:37:18 2009 +0900
14.3 @@ -48,10 +48,12 @@
14.4 UintegerValue (0),
14.5 MakeUintegerAccessor (&Ipv6RawSocketImpl::m_protocol),
14.6 MakeUintegerChecker<uint16_t> ())
14.7 +#ifdef FIXME
14.8 .AddAttribute ("IcmpFilter", "Any ICMPv6 header whose type field matches a bit in this filter is dropped.",
14.9 UintegerValue (0),
14.10 MakeUintegerAccessor (&Ipv6RawSocketImpl::m_icmpFilter),
14.11 MakeUintegerChecker<uint32_t> ())
14.12 +#endif
14.13 ;
14.14 return tid;
14.15 }
14.16 @@ -66,6 +68,7 @@
14.17 m_protocol = 0;
14.18 m_shutdownSend = false;
14.19 m_shutdownRecv = false;
14.20 + m_ifIndex = 0;
14.21 }
14.22
14.23 Ipv6RawSocketImpl::~Ipv6RawSocketImpl ()
14.24 @@ -212,6 +215,10 @@
14.25 NS_ASSERT (index >= 0);
14.26 oif = index;
14.27 }
14.28 + else
14.29 + {
14.30 + oif = m_ifIndex;
14.31 + }
14.32
14.33 route = ipv6->GetRoutingProtocol ()->RouteOutput (p, hdr, oif, err);
14.34
14.35 @@ -239,7 +246,7 @@
14.36 NS_LOG_DEBUG ("No route, dropped!");
14.37 }
14.38 }
14.39 - return 0;
14.40 + return p->GetSize();
14.41 }
14.42
14.43 Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
14.44 @@ -315,11 +322,13 @@
14.45 copy->PeekHeader (icmpHeader);
14.46 uint8_t type = icmpHeader.GetType ();
14.47
14.48 - if ((1 << type) & m_icmpFilter)
14.49 - {
14.50 - /* packet filtered */
14.51 - return false;
14.52 - }
14.53 + if (ICMP6_FILTER_WILLBLOCK(type, &m_icmpFilter))
14.54 + {
14.55 + NS_LOG_DEBUG("Dropped by ICMP6 filter type=" << (uint32_t)type << " on " << this);
14.56 + /* packet filtered */
14.57 + return false;
14.58 + }
14.59 +
14.60 }
14.61
14.62 copy->AddHeader (hdr);
14.63 @@ -334,5 +343,24 @@
14.64 return false;
14.65 }
14.66
14.67 +void Ipv6RawSocketImpl::SetIfIndex(uint32_t ifIndex)
14.68 +{
14.69 + m_ifIndex=ifIndex;
14.70 +}
14.71 +
14.72 +uint32_t Ipv6RawSocketImpl::GetIfIndex()
14.73 +{
14.74 + NS_LOG_FUNCTION_NOARGS();
14.75 + return m_ifIndex;
14.76 +}
14.77 +
14.78 +void
14.79 +Ipv6RawSocketImpl::SetIcmp6Filter (struct icmp6_filter* filter)
14.80 +{
14.81 + NS_LOG_DEBUG("Set filter for " << this);
14.82 + memcpy(&m_icmpFilter, filter, sizeof(struct icmp6_filter));
14.83 + return;
14.84 +}
14.85 +
14.86 } /* namespace ns3 */
14.87
15.1 --- a/src/internet-stack/ipv6-raw-socket-impl.h Mon Sep 07 15:45:12 2009 +0200
15.2 +++ b/src/internet-stack/ipv6-raw-socket-impl.h Thu Oct 01 23:37:18 2009 +0900
15.3 @@ -26,6 +26,7 @@
15.4 #include "ns3/socket.h"
15.5 #include "ns3/ipv6-address.h"
15.6 #include "ns3/ipv6-header.h"
15.7 +#include <netinet/icmp6.h> // need ICMP6_FILTER
15.8
15.9 namespace ns3
15.10 {
15.11 @@ -186,6 +187,10 @@
15.12 */
15.13 bool ForwardUp (Ptr<const Packet> p, Ipv6Header hdr, Ptr<NetDevice> device);
15.14
15.15 + void SetIfIndex(uint32_t ifIndex);
15.16 + uint32_t GetIfIndex();
15.17 + void SetIcmp6Filter (struct icmp6_filter* filter);
15.18 +
15.19 private:
15.20 /**
15.21 * \struct Data
15.22 @@ -246,7 +251,8 @@
15.23 /**
15.24 * \brief ICMPv6 filter.
15.25 */
15.26 - uint32_t m_icmpFilter;
15.27 + struct icmp6_filter m_icmpFilter;
15.28 + u_int32_t m_ifIndex;
15.29 };
15.30
15.31 } /* namespace ns3 */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/src/internet-stack/tcp6-l4-protocol.cc Thu Oct 01 23:37:18 2009 +0900
16.3 @@ -0,0 +1,321 @@
16.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
16.5 +/*
16.6 + * Copyright (c) 2007 Georgia Tech Research Corporation
16.7 + *
16.8 + * This program is free software; you can redistribute it and/or modify
16.9 + * it under the terms of the GNU General Public License version 2 as
16.10 + * published by the Free Software Foundation;
16.11 + *
16.12 + * This program is distributed in the hope that it will be useful,
16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.15 + * GNU General Public License for more details.
16.16 + *
16.17 + * You should have received a copy of the GNU General Public License
16.18 + * along with this program; if not, write to the Free Software
16.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16.20 + *
16.21 + * Author: Raj Bhattacharjea <raj.b@gatech.edu>
16.22 + * Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
16.23 + */
16.24 +
16.25 +#include "ns3/assert.h"
16.26 +#include "ns3/log.h"
16.27 +#include "ns3/nstime.h"
16.28 +
16.29 +#include "ns3/packet.h"
16.30 +#include "ns3/node.h"
16.31 +
16.32 +#include "tcp6-l4-protocol.h"
16.33 +#include "tcp-header.h"
16.34 +#include "ipv6-end-point-demux.h"
16.35 +#include "ipv6-end-point.h"
16.36 +#include "ipv6-l3-protocol.h"
16.37 +#include "tcp6-socket-impl.h"
16.38 +#include "tcp6-socket-factory-impl.h"
16.39 +#include "ns3/ipv6-routing-protocol.h"
16.40 +#include "ns3/ipv6-route.h"
16.41 +
16.42 +#include "tcp-typedefs.h"
16.43 +
16.44 +#include <vector>
16.45 +#include <sstream>
16.46 +#include <iomanip>
16.47 +
16.48 +NS_LOG_COMPONENT_DEFINE ("Tcp6L4Protocol");
16.49 +
16.50 +namespace ns3 {
16.51 +
16.52 +NS_OBJECT_ENSURE_REGISTERED (Tcp6L4Protocol);
16.53 +
16.54 +static TcpStateMachine tcpStateMachine; //only instance of a Tcp6StateMachine
16.55 +
16.56 +//Tcp6L4Protocol stuff----------------------------------------------------------
16.57 +
16.58 +
16.59 +/* see http://www.iana.org/assignments/protocol-numbers */
16.60 +const uint8_t Tcp6L4Protocol::PROT_NUMBER = 6;
16.61 +
16.62 +ObjectFactory
16.63 +Tcp6L4Protocol::GetDefaultRttEstimatorFactory (void)
16.64 +{
16.65 + ObjectFactory factory;
16.66 + factory.SetTypeId (RttMeanDeviation::GetTypeId ());
16.67 + return factory;
16.68 +}
16.69 +
16.70 +TypeId
16.71 +Tcp6L4Protocol::GetTypeId (void)
16.72 +{
16.73 + static TypeId tid = TypeId ("ns3::Tcp6L4Protocol")
16.74 + .SetParent<Ipv6L4Protocol> ()
16.75 + .AddConstructor<Tcp6L4Protocol> ()
16.76 + .AddAttribute ("RttEstimatorFactory",
16.77 + "How RttEstimator objects are created.",
16.78 + ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
16.79 + MakeObjectFactoryAccessor (&Tcp6L4Protocol::m_rttFactory),
16.80 + MakeObjectFactoryChecker ())
16.81 + ;
16.82 + return tid;
16.83 +}
16.84 +
16.85 +Tcp6L4Protocol::Tcp6L4Protocol ()
16.86 + : m_endPoints (new Ipv6EndPointDemux ())
16.87 +{
16.88 + NS_LOG_FUNCTION_NOARGS ();
16.89 + NS_LOG_LOGIC("Made a Tcp6L4Protocol "<<this);
16.90 +}
16.91 +
16.92 +Tcp6L4Protocol::~Tcp6L4Protocol ()
16.93 +{
16.94 + NS_LOG_FUNCTION_NOARGS ();
16.95 +}
16.96 +
16.97 +void
16.98 +Tcp6L4Protocol::SetNode (Ptr<Node> node)
16.99 +{
16.100 + m_node = node;
16.101 +}
16.102 +
16.103 +void
16.104 +Tcp6L4Protocol::NotifyNewAggregate ()
16.105 +{
16.106 + if (m_node == 0)
16.107 + {
16.108 + Ptr<Node> node = this->GetObject<Node> ();
16.109 + if (node != 0)
16.110 + {
16.111 + Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
16.112 + if (ipv6 != 0)
16.113 + {
16.114 + this->SetNode (node);
16.115 + ipv6->Insert (this);
16.116 + Ptr<Tcp6SocketFactoryImpl> tcpFactory = CreateObject<Tcp6SocketFactoryImpl> ();
16.117 + tcpFactory->SetTcp6 (this);
16.118 + node->AggregateObject (tcpFactory);
16.119 + }
16.120 + }
16.121 + }
16.122 + Object::NotifyNewAggregate ();
16.123 +}
16.124 +
16.125 +int
16.126 +Tcp6L4Protocol::GetProtocolNumber (void) const
16.127 +{
16.128 + return PROT_NUMBER;
16.129 +}
16.130 +int
16.131 +Tcp6L4Protocol::GetVersion (void) const
16.132 +{
16.133 + return 2;
16.134 +}
16.135 +
16.136 +void
16.137 +Tcp6L4Protocol::DoDispose (void)
16.138 +{
16.139 + NS_LOG_FUNCTION_NOARGS ();
16.140 + if (m_endPoints != 0)
16.141 + {
16.142 + delete m_endPoints;
16.143 + m_endPoints = 0;
16.144 + }
16.145 + m_node = 0;
16.146 + Ipv6L4Protocol::DoDispose ();
16.147 +}
16.148 +
16.149 +Ptr<Socket>
16.150 +Tcp6L4Protocol::CreateSocket (void)
16.151 +{
16.152 + NS_LOG_FUNCTION_NOARGS ();
16.153 + Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
16.154 + Ptr<Tcp6SocketImpl> socket = CreateObject<Tcp6SocketImpl> ();
16.155 + socket->SetNode (m_node);
16.156 + socket->SetTcp (this);
16.157 + socket->SetRtt (rtt);
16.158 + return socket;
16.159 +}
16.160 +
16.161 +Ipv6EndPoint *
16.162 +Tcp6L4Protocol::Allocate (void)
16.163 +{
16.164 + NS_LOG_FUNCTION_NOARGS ();
16.165 + return m_endPoints->Allocate ();
16.166 +}
16.167 +
16.168 +Ipv6EndPoint *
16.169 +Tcp6L4Protocol::Allocate (Ipv6Address address)
16.170 +{
16.171 + NS_LOG_FUNCTION (this << address);
16.172 + return m_endPoints->Allocate (address);
16.173 +}
16.174 +
16.175 +Ipv6EndPoint *
16.176 +Tcp6L4Protocol::Allocate (uint16_t port)
16.177 +{
16.178 + NS_LOG_FUNCTION (this << port);
16.179 + return m_endPoints->Allocate (port);
16.180 +}
16.181 +
16.182 +Ipv6EndPoint *
16.183 +Tcp6L4Protocol::Allocate (Ipv6Address address, uint16_t port)
16.184 +{
16.185 + NS_LOG_FUNCTION (this << address << port);
16.186 + return m_endPoints->Allocate (address, port);
16.187 +}
16.188 +
16.189 +Ipv6EndPoint *
16.190 +Tcp6L4Protocol::Allocate (Ipv6Address localAddress, uint16_t localPort,
16.191 + Ipv6Address peerAddress, uint16_t peerPort)
16.192 +{
16.193 + NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
16.194 + return m_endPoints->Allocate (localAddress, localPort,
16.195 + peerAddress, peerPort);
16.196 +}
16.197 +
16.198 +void
16.199 +Tcp6L4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
16.200 +{
16.201 + NS_LOG_FUNCTION (this << endPoint);
16.202 + m_endPoints->DeAllocate (endPoint);
16.203 +}
16.204 +
16.205 +enum Ipv6L4Protocol::RxStatus_e
16.206 +Tcp6L4Protocol::Receive (Ptr<Packet> packet,
16.207 + Ipv6Address const &source,
16.208 + Ipv6Address const &destination,
16.209 + Ptr<Ipv6Interface> incomingInterface)
16.210 +{
16.211 + NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
16.212 +
16.213 + TcpHeader tcpHeader;
16.214 +
16.215 + tcpHeader.EnableChecksums();
16.216 + // tcpHeader.InitializeChecksum(source, destination, 6);
16.217 + packet->PeekHeader (tcpHeader);
16.218 +
16.219 + NS_LOG_LOGIC("Tcp6L4Protocol " << this
16.220 + << " receiving seq " << tcpHeader.GetSequenceNumber()
16.221 + << " ack " << tcpHeader.GetAckNumber()
16.222 + << " flags "<< std::hex << (int)tcpHeader.GetFlags() << std::dec
16.223 + << " data size " << packet->GetSize());
16.224 +
16.225 +
16.226 + if(!tcpHeader.IsChecksumOk ())
16.227 + {
16.228 + NS_LOG_INFO("Bad checksum, dropping packet!");
16.229 + return Ipv6L4Protocol::RX_CSUM_FAILED;
16.230 + }
16.231 +
16.232 + NS_LOG_LOGIC ("Tcp6L4Protocol "<<this<<" received a packet");
16.233 + Ipv6EndPointDemux::EndPoints endPoints =
16.234 + m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
16.235 + source, tcpHeader.GetSourcePort (),incomingInterface);
16.236 + if (endPoints.empty ())
16.237 + {
16.238 + NS_LOG_LOGIC (" No endpoints matched on Tcp6L4Protocol "<<this);
16.239 + std::ostringstream oss;
16.240 + oss<<" destination IP: ";
16.241 + destination.Print (oss);
16.242 + oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
16.243 + source.Print (oss);
16.244 + oss<<" source port: "<<tcpHeader.GetSourcePort ();
16.245 + NS_LOG_LOGIC (oss.str ());
16.246 + return Ipv6L4Protocol::RX_ENDPOINT_UNREACH;
16.247 + }
16.248 + NS_ASSERT_MSG (endPoints.size() == 1 , "Demux returned more than one endpoint");
16.249 + NS_LOG_LOGIC ("Tcp6L4Protocol "<<this<<" forwarding up to endpoint/socket");
16.250 + (*endPoints.begin ())->ForwardUp (packet, source, tcpHeader.GetSourcePort ());
16.251 + return Ipv6L4Protocol::RX_OK;
16.252 +}
16.253 +
16.254 +void
16.255 +Tcp6L4Protocol::Send (Ptr<Packet> packet,
16.256 + Ipv6Address saddr, Ipv6Address daddr,
16.257 + uint16_t sport, uint16_t dport)
16.258 +{
16.259 + NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
16.260 +
16.261 + TcpHeader tcpHeader;
16.262 + tcpHeader.SetDestinationPort (dport);
16.263 + tcpHeader.SetSourcePort (sport);
16.264 + tcpHeader.SetLength(5);
16.265 + tcpHeader.EnableChecksums();
16.266 +// tcpHeader.InitializeChecksum (saddr,
16.267 +// daddr,
16.268 +// PROT_NUMBER);
16.269 + tcpHeader.SetFlags (TcpHeader::ACK);
16.270 + tcpHeader.SetAckNumber (0);
16.271 +
16.272 + packet->AddHeader (tcpHeader);
16.273 +
16.274 + Ptr<Ipv6L3Protocol> ipv6 =
16.275 + m_node->GetObject<Ipv6L3Protocol> ();
16.276 + if (ipv6 != 0)
16.277 + {
16.278 + Ipv6Header header;
16.279 + header.SetDestinationAddress (daddr);
16.280 + Socket::SocketErrno errno_;
16.281 + Ptr<Ipv6Route> route;
16.282 + uint32_t oif = 0; //specify non-zero if bound to a source address
16.283 + route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
16.284 + ipv6->Send (packet, saddr, daddr, PROT_NUMBER, route);
16.285 + }
16.286 +}
16.287 +
16.288 +void
16.289 +Tcp6L4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
16.290 + Ipv6Address saddr, Ipv6Address daddr)
16.291 +{
16.292 + NS_LOG_LOGIC("TcpL4Protocol " << this
16.293 + << " sending seq " << outgoingHeader.GetSequenceNumber()
16.294 + << " ack " << outgoingHeader.GetAckNumber()
16.295 + << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec
16.296 + << " data size " << packet->GetSize());
16.297 + NS_LOG_FUNCTION (this << packet << saddr << daddr);
16.298 + // XXX outgoingHeader cannot be logged
16.299 +
16.300 + outgoingHeader.SetLength (5); //header length in units of 32bit words
16.301 + /* outgoingHeader.SetUrgentPointer (0); //XXX */
16.302 + outgoingHeader.EnableChecksums();
16.303 + // outgoingHeader.InitializeChecksum(saddr, daddr, PROT_NUMBER);
16.304 +
16.305 + packet->AddHeader (outgoingHeader);
16.306 +
16.307 + Ptr<Ipv6L3Protocol> ipv6 =
16.308 + m_node->GetObject<Ipv6L3Protocol> ();
16.309 + if (ipv6 != 0)
16.310 + {
16.311 + Ipv6Header header;
16.312 + header.SetDestinationAddress (daddr);
16.313 + Socket::SocketErrno errno_;
16.314 + Ptr<Ipv6Route> route;
16.315 + uint32_t oif = 0; //specify non-zero if bound to a source address
16.316 + route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
16.317 + ipv6->Send (packet, saddr, daddr, PROT_NUMBER, route);
16.318 + }
16.319 + else
16.320 + NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv6 interface");
16.321 +}
16.322 +
16.323 +}; // namespace ns3
16.324 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/src/internet-stack/tcp6-l4-protocol.h Thu Oct 01 23:37:18 2009 +0900
17.3 @@ -0,0 +1,121 @@
17.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
17.5 +/*
17.6 + * Copyright (c) 2007 Georgia Tech Research Corporation
17.7 + *
17.8 + * This program is free software; you can redistribute it and/or modify
17.9 + * it under the terms of the GNU General Public License version 2 as
17.10 + * published by the Free Software Foundation;
17.11 + *
17.12 + * This program is distributed in the hope that it will be useful,
17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17.15 + * GNU General Public License for more details.
17.16 + *
17.17 + * You should have received a copy of the GNU General Public License
17.18 + * along with this program; if not, write to the Free Software
17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17.20 + *
17.21 + * Author: Raj Bhattacharjea <raj.b@gatech.edu>
17.22 + * Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
17.23 + */
17.24 +
17.25 +#ifndef TCP6_L4_PROTOCOL_H
17.26 +#define TCP6_L4_PROTOCOL_H
17.27 +
17.28 +#include <stdint.h>
17.29 +
17.30 +#include "ns3/packet.h"
17.31 +#include "ns3/ipv6-address.h"
17.32 +#include "ns3/ptr.h"
17.33 +#include "ns3/object-factory.h"
17.34 +#include "ipv6-end-point-demux.h"
17.35 +#include "ipv6-l4-protocol.h"
17.36 +#include "ipv6-interface.h"
17.37 +
17.38 +#include "tcp-header.h"
17.39 +#include "tcp-typedefs.h"
17.40 +
17.41 +namespace ns3 {
17.42 +
17.43 +class Node;
17.44 +class Socket;
17.45 +class TcpHeader;
17.46 +/**
17.47 + * \class Tcp6L4Protocol
17.48 + * \brief Implementation of the TCP protocol
17.49 + */
17.50 +class Tcp6L4Protocol : public Ipv6L4Protocol {
17.51 +public:
17.52 + static TypeId GetTypeId (void);
17.53 + static const uint8_t PROT_NUMBER;
17.54 + /**
17.55 + * \brief Constructor
17.56 + */
17.57 + Tcp6L4Protocol ();
17.58 + virtual ~Tcp6L4Protocol ();
17.59 +
17.60 + void SetNode (Ptr<Node> node);
17.61 +
17.62 + virtual int GetProtocolNumber (void) const;
17.63 + virtual int GetVersion (void) const;
17.64 +
17.65 + /**
17.66 + * \return A smart Socket pointer to a Tcp6SocketImpl, allocated by this instance
17.67 + * of the TCP protocol
17.68 + */
17.69 + Ptr<Socket> CreateSocket (void);
17.70 +
17.71 + Ipv6EndPoint *Allocate (void);
17.72 + Ipv6EndPoint *Allocate (Ipv6Address address);
17.73 + Ipv6EndPoint *Allocate (uint16_t port);
17.74 + Ipv6EndPoint *Allocate (Ipv6Address address, uint16_t port);
17.75 + Ipv6EndPoint *Allocate (Ipv6Address localAddress, uint16_t localPort,
17.76 + Ipv6Address peerAddress, uint16_t peerPort);
17.77 +
17.78 + void DeAllocate (Ipv6EndPoint *endPoint);
17.79 +
17.80 +// // called by Tcp6SocketImpl.
17.81 +// bool Connect (const Ipv6Address& saddr, const Ipv6Address& daddr,
17.82 +// uint16_t sport, uint16_t dport);
17.83 +
17.84 + /**
17.85 + * \brief Send a packet via TCP
17.86 + * \param packet The packet to send
17.87 + * \param saddr The source Ipv6Address
17.88 + * \param daddr The destination Ipv6Address
17.89 + * \param sport The source port number
17.90 + * \param dport The destination port number
17.91 + */
17.92 + void Send (Ptr<Packet> packet,
17.93 + Ipv6Address saddr, Ipv6Address daddr,
17.94 + uint16_t sport, uint16_t dport);
17.95 + /**
17.96 + * \brief Recieve a packet up the protocol stack
17.97 + * \param p The Packet to dump the contents into
17.98 + * \param source The source's Ipv6Address
17.99 + * \param destination The destinations Ipv6Address
17.100 + * \param incomingInterface The Ipv6Interface it was received on
17.101 + */
17.102 + virtual enum Ipv6L4Protocol::RxStatus_e Receive (Ptr<Packet> p,
17.103 + Ipv6Address const &source,
17.104 + Ipv6Address const &destination,
17.105 + Ptr<Ipv6Interface> incomingInterface);
17.106 +
17.107 +protected:
17.108 + virtual void DoDispose (void);
17.109 + virtual void NotifyNewAggregate ();
17.110 +private:
17.111 + Ptr<Node> m_node;
17.112 + Ipv6EndPointDemux *m_endPoints;
17.113 + ObjectFactory m_rttFactory;
17.114 +private:
17.115 + friend class Tcp6SocketImpl;
17.116 + void SendPacket (Ptr<Packet>, TcpHeader,
17.117 + Ipv6Address, Ipv6Address);
17.118 + static ObjectFactory GetDefaultRttEstimatorFactory (void);
17.119 +};
17.120 +
17.121 +}; // namespace ns3
17.122 +
17.123 +#endif /* TCP6_L4_PROTOCOL_H */
17.124 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/src/internet-stack/tcp6-socket-factory-impl.cc Thu Oct 01 23:37:18 2009 +0900
18.3 @@ -0,0 +1,56 @@
18.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
18.5 +/*
18.6 + * Copyright (c) 2007-2008 Louis Pasteur University
18.7 + *
18.8 + * This program is free software; you can redistribute it and/or modify
18.9 + * it under the terms of the GNU General Public License version 2 as
18.10 + * published by the Free Software Foundation;
18.11 + *
18.12 + * This program is distributed in the hope that it will be useful,
18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18.15 + * GNU General Public License for more details.
18.16 + *
18.17 + * You should have received a copy of the GNU General Public License
18.18 + * along with this program; if not, write to the Free Software
18.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18.20 + *
18.21 + * Author: David Gross <gdavid.devel@gmail.com>
18.22 + */
18.23 +
18.24 +#include "tcp6-socket-factory-impl.h"
18.25 +#include "tcp6-l4-protocol.h"
18.26 +#include "ns3/socket.h"
18.27 +#include "ns3/assert.h"
18.28 +
18.29 +namespace ns3
18.30 +{
18.31 +
18.32 + Tcp6SocketFactoryImpl::Tcp6SocketFactoryImpl ()
18.33 + : m_tcp6 (0)
18.34 + {
18.35 + }
18.36 +
18.37 + Tcp6SocketFactoryImpl::~Tcp6SocketFactoryImpl ()
18.38 + {
18.39 + NS_ASSERT (m_tcp6 == 0);
18.40 + }
18.41 +
18.42 + void Tcp6SocketFactoryImpl::SetTcp6 (Ptr<Tcp6L4Protocol> tcp6)
18.43 + {
18.44 + m_tcp6 = tcp6;
18.45 + }
18.46 +
18.47 + Ptr<Socket> Tcp6SocketFactoryImpl::CreateSocket ()
18.48 + {
18.49 + return m_tcp6->CreateSocket ();
18.50 + }
18.51 +
18.52 + void Tcp6SocketFactoryImpl::DoDispose (void)
18.53 + {
18.54 + m_tcp6 = 0;
18.55 + Tcp6SocketFactory::DoDispose ();
18.56 + }
18.57 +
18.58 +} /* namespace ns3 */
18.59 +
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/src/internet-stack/tcp6-socket-factory-impl.h Thu Oct 01 23:37:18 2009 +0900
19.3 @@ -0,0 +1,81 @@
19.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
19.5 +/*
19.6 + * Copyright (c) 2007-2008 Louis Pasteur University
19.7 + *
19.8 + * This program is free software; you can redistribute it and/or modify
19.9 + * it under the terms of the GNU General Public License version 2 as
19.10 + * published by the Free Software Foundation;
19.11 + *
19.12 + * This program is distributed in the hope that it will be useful,
19.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.15 + * GNU General Public License for more details.
19.16 + *
19.17 + * You should have received a copy of the GNU General Public License
19.18 + * along with this program; if not, write to the Free Software
19.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19.20 + *
19.21 + * Author : David Gross <gdavid.devel@gmail.com>
19.22 + */
19.23 +
19.24 +#ifndef TCP6_SOCKET_FACTORY_IMPL_H
19.25 +#define TCP6_SOCKET_FACTORY_IMPL_H
19.26 +
19.27 +#include "ns3/tcp6-socket-factory.h"
19.28 +#include "ns3/ptr.h"
19.29 +
19.30 +namespace ns3
19.31 +{
19.32 +
19.33 + class Socket;
19.34 + class Tcp6L4Protocol;
19.35 +
19.36 + /**
19.37 + * \class Tcp6SocketFactoryImpl
19.38 + * \brief TCPv6 socket factory implementation.
19.39 + * \section Tcp overview
19.40 + * This TCP over IPv6 version is ported from IPv4 code.
19.41 + */
19.42 +
19.43 + class Tcp6SocketFactoryImpl : public Tcp6SocketFactory
19.44 + {
19.45 + public:
19.46 + /**
19.47 + * \brief Constructor.
19.48 + */
19.49 + Tcp6SocketFactoryImpl ();
19.50 +
19.51 + /**
19.52 + * \brief Destructor.
19.53 + */
19.54 + virtual ~Tcp6SocketFactoryImpl ();
19.55 +
19.56 + /**
19.57 + * \brief Set the TCPv6 Protocol.
19.58 + * \param tcp6 the TCPv6 protocol
19.59 + */
19.60 + void SetTcp6 (Ptr<Tcp6L4Protocol> tcp6);
19.61 +
19.62 + /**
19.63 + * \brief Create a socket.
19.64 + * \return pointer on a socket.
19.65 + */
19.66 + virtual Ptr<Socket> CreateSocket ();
19.67 +
19.68 + protected:
19.69 + /**
19.70 + * \brief Dispose this object.
19.71 + */
19.72 + virtual void DoDispose (void);
19.73 +
19.74 + private:
19.75 + /**
19.76 + * \brief The Tcp6L4Protocol instance.
19.77 + */
19.78 + Ptr<Tcp6L4Protocol> m_tcp6;
19.79 + };
19.80 +
19.81 +} /* namespace ns3 */
19.82 +
19.83 +#endif /* TCP6_SOCKET_FACTORY_IMPL_H */
19.84 +
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/src/internet-stack/tcp6-socket-impl.cc Thu Oct 01 23:37:18 2009 +0900
20.3 @@ -0,0 +1,1482 @@
20.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
20.5 +/*
20.6 + * Copyright (c) 2007 Georgia Tech Research Corporation
20.7 + *
20.8 + * This program is free software; you can redistribute it and/or modify
20.9 + * it under the terms of the GNU General Public License version 2 as
20.10 + * published by the Free Software Foundation;
20.11 + *
20.12 + * This program is distributed in the hope that it will be useful,
20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.15 + * GNU General Public License for more details.
20.16 + *
20.17 + * You should have received a copy of the GNU General Public License
20.18 + * along with this program; if not, write to the Free Software
20.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20.20 + *
20.21 + * Author: Raj Bhattacharjea <raj.b@gatech.edu>
20.22 + * Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
20.23 + */
20.24 +
20.25 +#include "ns3/node.h"
20.26 +#include "ns3/inet6-socket-address.h"
20.27 +#include "ns3/log.h"
20.28 +#include "ns3/ipv6.h"
20.29 +#include "tcp6-socket-impl.h"
20.30 +#include "tcp6-l4-protocol.h"
20.31 +#include "ipv6-end-point.h"
20.32 +#include "ns3/simulation-singleton.h"
20.33 +#include "tcp-typedefs.h"
20.34 +#include "ns3/simulator.h"
20.35 +#include "ns3/packet.h"
20.36 +#include "ns3/uinteger.h"
20.37 +#include "ns3/trace-source-accessor.h"
20.38 +#include "ns3/ipv6-header.h"
20.39 +#include "ns3/ipv6-route.h"
20.40 +#include "ns3/ipv6-routing-protocol.h"
20.41 +
20.42 +#include <algorithm>
20.43 +
20.44 +NS_LOG_COMPONENT_DEFINE ("Tcp6SocketImpl");
20.45 +
20.46 +using namespace std;
20.47 +
20.48 +namespace ns3 {
20.49 +
20.50 +NS_OBJECT_ENSURE_REGISTERED (Tcp6SocketImpl);
20.51 +
20.52 +TypeId
20.53 +Tcp6SocketImpl::GetTypeId ()
20.54 +{
20.55 + static TypeId tid = TypeId("ns3::Tcp6SocketImpl")
20.56 + .SetParent<TcpSocket> ()
20.57 + .AddTraceSource ("CongestionWindow",
20.58 + "The TCP connection's congestion window",
20.59 + MakeTraceSourceAccessor (&Tcp6SocketImpl::m_cWnd))
20.60 + ;
20.61 + return tid;
20.62 +}
20.63 +
20.64 + Tcp6SocketImpl::Tcp6SocketImpl ()
20.65 + : m_skipRetxResched (false),
20.66 + m_dupAckCount (0),
20.67 + m_delAckCount (0),
20.68 + m_endPoint (0),
20.69 + m_node (0),
20.70 + m_tcp (0),
20.71 + m_errno (ERROR_NOTERROR),
20.72 + m_shutdownSend (false),
20.73 + m_shutdownRecv (false),
20.74 + m_connected (false),
20.75 + m_state (CLOSED),
20.76 + m_closeNotified (false),
20.77 + m_closeRequestNotified (false),
20.78 + m_closeOnEmpty (false),
20.79 + m_pendingClose (false),
20.80 + m_nextTxSequence (0),
20.81 + m_highTxMark (0),
20.82 + m_highestRxAck (0),
20.83 + m_lastRxAck (0),
20.84 + m_nextRxSequence (0),
20.85 + m_pendingData (0),
20.86 + m_rtt (0),
20.87 + m_lastMeasuredRtt (Seconds(0.0)),
20.88 + m_rxAvailable (0),
20.89 + m_wouldBlock (false)
20.90 +{
20.91 + NS_LOG_FUNCTION (this);
20.92 +}
20.93 +
20.94 +Tcp6SocketImpl::Tcp6SocketImpl(const Tcp6SocketImpl& sock)
20.95 + : TcpSocket(sock), //copy the base class callbacks
20.96 + m_skipRetxResched (sock.m_skipRetxResched),
20.97 + m_dupAckCount (sock.m_dupAckCount),
20.98 + m_delAckCount (0),
20.99 + m_delAckMaxCount (sock.m_delAckMaxCount),
20.100 + m_delAckTimeout (sock.m_delAckTimeout),
20.101 + m_endPoint (0),
20.102 + m_node (sock.m_node),
20.103 + m_tcp (sock.m_tcp),
20.104 + m_remoteAddress (sock.m_remoteAddress),
20.105 + m_remotePort (sock.m_remotePort),
20.106 + m_localAddress (sock.m_localAddress),
20.107 + m_localPort (sock.m_localPort),
20.108 + m_errno (sock.m_errno),
20.109 + m_shutdownSend (sock.m_shutdownSend),
20.110 + m_shutdownRecv (sock.m_shutdownRecv),
20.111 + m_connected (sock.m_connected),
20.112 + m_state (sock.m_state),
20.113 + m_closeNotified (sock.m_closeNotified),
20.114 + m_closeRequestNotified (sock.m_closeRequestNotified),
20.115 + m_closeOnEmpty (sock.m_closeOnEmpty),
20.116 + m_pendingClose (sock.m_pendingClose),
20.117 + m_nextTxSequence (sock.m_nextTxSequence),
20.118 + m_highTxMark (sock.m_highTxMark),
20.119 + m_highestRxAck (sock.m_highestRxAck),
20.120 + m_lastRxAck (sock.m_lastRxAck),
20.121 + m_nextRxSequence (sock.m_nextRxSequence),
20.122 + m_pendingData (0),
20.123 + m_segmentSize (sock.m_segmentSize),
20.124 + m_rxWindowSize (sock.m_rxWindowSize),
20.125 + m_advertisedWindowSize (sock.m_advertisedWindowSize),
20.126 + m_cWnd (sock.m_cWnd),
20.127 + m_ssThresh (sock.m_ssThresh),
20.128 + m_initialCWnd (sock.m_initialCWnd),
20.129 + m_rtt (0),
20.130 + m_lastMeasuredRtt (Seconds(0.0)),
20.131 + m_cnTimeout (sock.m_cnTimeout),
20.132 + m_cnCount (sock.m_cnCount),
20.133 + m_rxAvailable (0),
20.134 + m_wouldBlock (false),
20.135 + m_sndBufSize (sock.m_sndBufSize),
20.136 + m_rcvBufSize(sock.m_rcvBufSize)
20.137 +{
20.138 + NS_LOG_FUNCTION_NOARGS ();
20.139 + NS_LOG_LOGIC("Invoked the copy constructor");
20.140 + //copy the pending data if necessary
20.141 + if(sock.m_pendingData)
20.142 + {
20.143 + m_pendingData = sock.m_pendingData->Copy();
20.144 + }
20.145 + //copy the rtt if necessary
20.146 + if (sock.m_rtt)
20.147 + {
20.148 + m_rtt = sock.m_rtt->Copy();
20.149 + }
20.150 + //can't "copy" the endpoint just yes, must do this when we know the peer info
20.151 + //too; this is in SYN_ACK_TX
20.152 +}
20.153 +
20.154 +Tcp6SocketImpl::~Tcp6SocketImpl ()
20.155 +{
20.156 + NS_LOG_FUNCTION(this);
20.157 + m_node = 0;
20.158 + if (m_endPoint != 0)
20.159 + {
20.160 + NS_ASSERT (m_tcp != 0);
20.161 + /**
20.162 + * Note that this piece of code is a bit tricky:
20.163 + * when DeAllocate is called, it will call into
20.164 + * Ipv6EndPointDemux::Deallocate which triggers
20.165 + * a delete of the associated endPoint which triggers
20.166 + * in turn a call to the method ::Destroy below
20.167 + * will will zero the m_endPoint field.
20.168 + */
20.169 + NS_ASSERT (m_endPoint != 0);
20.170 + m_tcp->DeAllocate (m_endPoint);
20.171 + NS_ASSERT (m_endPoint == 0);
20.172 + }
20.173 + m_tcp = 0;
20.174 + delete m_pendingData; //prevents leak
20.175 + m_pendingData = 0;
20.176 +}
20.177 +
20.178 +void
20.179 +Tcp6SocketImpl::SetNode (Ptr<Node> node)
20.180 +{
20.181 + m_node = node;
20.182 + // Initialize some variables
20.183 + m_cWnd = m_initialCWnd * m_segmentSize;
20.184 + m_rxWindowSize = m_advertisedWindowSize;
20.185 +}
20.186 +
20.187 +void
20.188 +Tcp6SocketImpl::SetTcp (Ptr<Tcp6L4Protocol> tcp)
20.189 +{
20.190 + m_tcp = tcp;
20.191 +}
20.192 +void
20.193 +Tcp6SocketImpl::SetRtt (Ptr<RttEstimator> rtt)
20.194 +{
20.195 + m_rtt = rtt;
20.196 +}
20.197 +
20.198 +
20.199 +enum Socket::SocketErrno
20.200 +Tcp6SocketImpl::GetErrno (void) const
20.201 +{
20.202 + NS_LOG_FUNCTION_NOARGS ();
20.203 + return m_errno;
20.204 +}
20.205 +
20.206 +Ptr<Node>
20.207 +Tcp6SocketImpl::GetNode (void) const
20.208 +{
20.209 + NS_LOG_FUNCTION_NOARGS ();
20.210 + return m_node;
20.211 +}
20.212 +
20.213 +void
20.214 +Tcp6SocketImpl::Destroy (void)
20.215 +{
20.216 + NS_LOG_FUNCTION_NOARGS ();
20.217 + m_node = 0;
20.218 + m_endPoint = 0;
20.219 + m_tcp = 0;
20.220 + m_retxEvent.Cancel ();
20.221 +}
20.222 +int
20.223 +Tcp6SocketImpl::FinishBind (void)
20.224 +{
20.225 + NS_LOG_FUNCTION_NOARGS ();
20.226 + if (m_endPoint == 0)
20.227 + {
20.228 + return -1;
20.229 + }
20.230 + m_endPoint->SetRxCallback (MakeCallback (&Tcp6SocketImpl::ForwardUp, Ptr<Tcp6SocketImpl>(this)));
20.231 + m_endPoint->SetDestroyCallback (MakeCallback (&Tcp6SocketImpl::Destroy, Ptr<Tcp6SocketImpl>(this)));
20.232 + m_localAddress = m_endPoint->GetLocalAddress ();
20.233 + m_localPort = m_endPoint->GetLocalPort ();
20.234 + return 0;
20.235 +}
20.236 +
20.237 +int
20.238 +Tcp6SocketImpl::Bind (void)
20.239 +{
20.240 + NS_LOG_FUNCTION_NOARGS ();
20.241 + m_endPoint = m_tcp->Allocate ();
20.242 + return FinishBind ();
20.243 +}
20.244 +int
20.245 +Tcp6SocketImpl::Bind (const Address &address)
20.246 +{
20.247 + NS_LOG_FUNCTION (this<<address);
20.248 + if (!Inet6SocketAddress::IsMatchingType (address))
20.249 + {
20.250 + return ERROR_INVAL;
20.251 + }
20.252 + Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
20.253 + Ipv6Address ipv6 = transport.GetIpv6 ();
20.254 + uint16_t port = transport.GetPort ();
20.255 + if (ipv6 == Ipv6Address::GetAny () && port == 0)
20.256 + {
20.257 + m_endPoint = m_tcp->Allocate ();
20.258 + NS_LOG_LOGIC ("Tcp6SocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
20.259 + }
20.260 + else if (ipv6 == Ipv6Address::GetAny () && port != 0)
20.261 + {
20.262 + m_endPoint = m_tcp->Allocate (port);
20.263 + NS_LOG_LOGIC ("Tcp6SocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
20.264 + }
20.265 + else if (ipv6 != Ipv6Address::GetAny () && port == 0)
20.266 + {
20.267 + m_endPoint = m_tcp->Allocate (ipv6);
20.268 + NS_LOG_LOGIC ("Tcp6SocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
20.269 + }
20.270 + else if (ipv6 != Ipv6Address::GetAny () && port != 0)
20.271 + {
20.272 + m_endPoint = m_tcp->Allocate (ipv6, port);
20.273 + NS_LOG_LOGIC ("Tcp6SocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
20.274 + }
20.275 +
20.276 + return FinishBind ();
20.277 +}
20.278 +
20.279 +int
20.280 +Tcp6SocketImpl::ShutdownSend (void)
20.281 +{
20.282 + NS_LOG_FUNCTION_NOARGS ();
20.283 + m_shutdownSend = true;
20.284 + return 0;
20.285 +}
20.286 +int
20.287 +Tcp6SocketImpl::ShutdownRecv (void)
20.288 +{
20.289 + NS_LOG_FUNCTION_NOARGS ();
20.290 + m_shutdownRecv = false;
20.291 + return 0;
20.292 +}
20.293 +
20.294 +int
20.295 +Tcp6SocketImpl::Close (void)
20.296 +{
20.297 + NS_LOG_FUNCTION_NOARGS ();
20.298 + if (m_state == CLOSED)
20.299 + {
20.300 + return -1;
20.301 + }
20.302 + if (m_pendingData && m_pendingData->Size() != 0)
20.303 + { // App close with pending data must wait until all data transmitted
20.304 + m_closeOnEmpty = true;
20.305 + NS_LOG_LOGIC("Socket " << this <<
20.306 + " deferring close, state " << m_state);
20.307 + return 0;
20.308 + }
20.309 +
20.310 + Actions_t action = ProcessEvent (APP_CLOSE);
20.311 + ProcessAction (action);
20.312 + ShutdownSend ();
20.313 + return 0;
20.314 +}
20.315 +
20.316 +int
20.317 +Tcp6SocketImpl::Connect (const Address & address)
20.318 +{
20.319 + NS_LOG_FUNCTION (this << address);
20.320 + if (m_endPoint == 0)
20.321 + {
20.322 + if (Bind () == -1)
20.323 + {
20.324 + NS_ASSERT (m_endPoint == 0);
20.325 + return -1;
20.326 + }
20.327 + NS_ASSERT (m_endPoint != 0);
20.328 + }
20.329 + Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
20.330 + m_remoteAddress = transport.GetIpv6 ();
20.331 + m_remotePort = transport.GetPort ();
20.332 +
20.333 + Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
20.334 +
20.335 + Ipv6Header header;
20.336 + header.SetDestinationAddress (m_remoteAddress);
20.337 + Socket::SocketErrno errno_;
20.338 + Ptr<Ipv6Route> route;
20.339 + uint32_t oif = 0; //specify non-zero if bound to a source address
20.340 + // XXX here, cache the route in the endpoint?
20.341 + route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
20.342 +
20.343 + if (route != 0)
20.344 + {
20.345 + m_endPoint->SetLocalAddress (route->GetSource ());
20.346 + }
20.347 + else
20.348 + {
20.349 + m_errno = ERROR_NOROUTETOHOST;
20.350 + return -1;
20.351 + }
20.352 +
20.353 + Actions_t action = ProcessEvent (APP_CONNECT);
20.354 + bool success = ProcessAction (action);
20.355 + if (success)
20.356 + {
20.357 + return 0;
20.358 + }
20.359 + return -1;
20.360 +}
20.361 +int
20.362 +Tcp6SocketImpl::Send (Ptr<Packet> p, uint32_t flags)
20.363 +{
20.364 + NS_LOG_FUNCTION (this << p);
20.365 + if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
20.366 + {
20.367 + if (p->GetSize() > GetTxAvailable ())
20.368 + {
20.369 + m_wouldBlock = true;
20.370 + m_errno = ERROR_MSGSIZE;
20.371 + return -1;
20.372 + }
20.373 + if (!m_pendingData)
20.374 + {
20.375 + m_pendingData = new PendingData (); // Create if non-existent
20.376 + m_firstPendingSequence = m_nextTxSequence; // Note seq of first
20.377 + }
20.378 + //PendingData::Add stores a copy of the Ptr p
20.379 + m_pendingData->Add (p);
20.380 + NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() <<
20.381 + " state " << m_state);
20.382 + Actions_t action = ProcessEvent (APP_SEND);
20.383 + NS_LOG_DEBUG(" action " << action);
20.384 + if (!ProcessAction (action))
20.385 + {
20.386 + return -1; // Failed, return zero
20.387 + }
20.388 + return p->GetSize();
20.389 + }
20.390 + else
20.391 + {
20.392 + m_errno = ERROR_NOTCONN;
20.393 + return -1;
20.394 + }
20.395 +}
20.396 +
20.397 +int Tcp6SocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
20.398 +{
20.399 + NS_LOG_FUNCTION (this << p << address);
20.400 + Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
20.401 + Ipv6Address ipv6 = transport.GetIpv6 ();
20.402 + uint16_t port = transport.GetPort ();
20.403 + return DoSendTo (p, ipv6, port);
20.404 +}
20.405 +
20.406 +int Tcp6SocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address ipv6, uint16_t port)
20.407 +{
20.408 + NS_LOG_FUNCTION (this << p << ipv6 << port);
20.409 + if (m_endPoint == 0)
20.410 + {
20.411 + if (Bind () == -1)
20.412 + {
20.413 + NS_ASSERT (m_endPoint == 0);
20.414 + return -1;
20.415 + }
20.416 + NS_ASSERT (m_endPoint != 0);
20.417 + }
20.418 + if (m_shutdownSend)
20.419 + {
20.420 + m_errno = ERROR_SHUTDOWN;
20.421 + return -1;
20.422 + }
20.423 + m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv6,
20.424 + m_endPoint->GetLocalPort (), port);
20.425 + NotifyDataSent (p->GetSize ());
20.426 + return 0;
20.427 +}
20.428 +
20.429 +int
20.430 +Tcp6SocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
20.431 +{
20.432 + NS_LOG_FUNCTION (this << address << p);
20.433 + if (!m_connected)
20.434 + {
20.435 + m_errno = ERROR_NOTCONN;
20.436 + return -1;
20.437 + }
20.438 + else
20.439 + {
20.440 + return Send (p, flags); //drop the address according to BSD manpages
20.441 + }
20.442 +}
20.443 +
20.444 +uint32_t
20.445 +Tcp6SocketImpl::GetTxAvailable (void) const
20.446 +{
20.447 + NS_LOG_FUNCTION_NOARGS ();
20.448 + if (m_pendingData != 0)
20.449 + {
20.450 + uint32_t unAckedDataSize =
20.451 + m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck);
20.452 + NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error
20.453 + return m_sndBufSize-unAckedDataSize;
20.454 + }
20.455 + else
20.456 + {
20.457 + return m_sndBufSize;
20.458 + }
20.459 +}
20.460 +
20.461 +int
20.462 +Tcp6SocketImpl::Listen ()
20.463 +{
20.464 + NS_LOG_FUNCTION (this);
20.465 + Actions_t action = ProcessEvent (APP_LISTEN);
20.466 + ProcessAction (action);
20.467 + return 0;
20.468 +}
20.469 +
20.470 +Ptr<Packet>
20.471 +Tcp6SocketImpl::Recv (uint32_t maxSize, uint32_t flags)
20.472 +{
20.473 + NS_LOG_FUNCTION_NOARGS ();
20.474 + if(m_bufferedData.empty())
20.475 + {
20.476 + return 0;
20.477 + }
20.478 + UnAckData_t out; //serves as buffer to return up to the user
20.479 + UnAckData_t::iterator i;
20.480 + while (!m_bufferedData.empty ())
20.481 + { // Check the buffered data for delivery
20.482 + NS_LOG_LOGIC("TCP " << this << " bufferedData.size() "
20.483 + << m_bufferedData.size ()
20.484 + << " time " << Simulator::Now ());
20.485 + i = m_bufferedData.begin ();
20.486 + SequenceNumber s1 = 0;
20.487 + if (i->first > m_nextRxSequence)
20.488 + {
20.489 + break; // we're done, no more in-sequence data exits
20.490 + }
20.491 + else // (i->first <= m_nextRxSequence)
20.492 + { // Two cases here.
20.493 + // 1) seq + length > nextRxSeq, can deliver partial
20.494 + // 2) seq + length <= nextRxSeq, deliver whole
20.495 + s1 = i->second->GetSize ();
20.496 + if (i->first + s1 > m_nextRxSequence)
20.497 + { // Remove partial data to prepare for delivery
20.498 + uint32_t avail = s1 + i->first - m_nextRxSequence;
20.499 + i->second = i->second->CreateFragment (0, avail);
20.500 + }
20.501 + // else this packet is okay to deliver whole
20.502 + // so don't do anything else and output it
20.503 + out[i->first] = i->second;
20.504 + }
20.505 + m_rxAvailable -= i->second->GetSize ();
20.506 + m_bufferedData.erase (i); // Remove from list
20.507 + }
20.508 + if (out.size() == 0)
20.509 + {
20.510 + return 0;
20.511 + }
20.512 + Ptr<Packet> outPacket = Create<Packet>();
20.513 + for(i = out.begin(); i!=out.end(); ++i)
20.514 + {
20.515 + if (outPacket->GetSize() + i->second->GetSize() <= maxSize )
20.516 + {
20.517 + outPacket->AddAtEnd(i->second);
20.518 + }
20.519 + else
20.520 + {
20.521 + //only append as much as will fit
20.522 + uint32_t avail = maxSize - outPacket->GetSize();
20.523 + outPacket->AddAtEnd(i->second->CreateFragment(0,avail));
20.524 + //put the rest back into the buffer
20.525 + m_bufferedData[i->first+SequenceNumber(avail)]
20.526 + = i->second->CreateFragment(avail,i->second->GetSize()-avail);
20.527 + m_rxAvailable += i->second->GetSize()-avail;
20.528 + }
20.529 + }
20.530 + return outPacket;
20.531 +}
20.532 +
20.533 +uint32_t
20.534 +Tcp6SocketImpl::GetRxAvailable (void) const
20.535 +{
20.536 + NS_LOG_FUNCTION_NOARGS ();
20.537 + // We separately maintain this state to avoid walking the queue
20.538 + // every time this might be called
20.539 + return m_rxAvailable;
20.540 +}
20.541 +
20.542 +Ptr<Packet> Tcp6SocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
20.543 + Address &fromAddress)
20.544 +{
20.545 + NS_LOG_FUNCTION (this << maxSize << flags);
20.546 + Ptr<Packet> packet = Recv (maxSize, flags);
20.547 + if (packet != 0)
20.548 + {
20.549 + SocketAddressTag tag;
20.550 + bool found;
20.551 + found = packet->FindFirstMatchingByteTag (tag);
20.552 + NS_ASSERT (found);
20.553 + fromAddress = tag.GetAddress ();
20.554 + }
20.555 + return packet;
20.556 +}
20.557 +
20.558 +void
20.559 +Tcp6SocketImpl::ForwardUp (Ptr<Packet> packet, Ipv6Address ipv6, uint16_t port)
20.560 +{
20.561 + NS_LOG_DEBUG("Socket " << this << " got forward up" <<
20.562 + " dport " << m_endPoint->GetLocalPort() <<
20.563 + " daddr " << m_endPoint->GetLocalAddress() <<
20.564 + " sport " << m_endPoint->GetPeerPort() <<
20.565 + " saddr " << m_endPoint->GetPeerAddress());
20.566 +
20.567 + NS_LOG_FUNCTION (this << packet << ipv6 << port);
20.568 + if (m_shutdownRecv)
20.569 + {
20.570 + return;
20.571 + }
20.572 + TcpHeader tcpHeader;
20.573 + packet->RemoveHeader (tcpHeader);
20.574 +
20.575 + if (tcpHeader.GetFlags () & TcpHeader::ACK)
20.576 + {
20.577 + Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
20.578 + if (m != Seconds (0.0))
20.579 + {
20.580 + m_lastMeasuredRtt = m;
20.581 + }
20.582 + }
20.583 +
20.584 + Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
20.585 + Actions_t action = ProcessEvent (event); //updates the state
20.586 + Address address = Inet6SocketAddress (ipv6, port);
20.587 + NS_LOG_DEBUG("Socket " << this <<
20.588 + " processing pkt action, " << action <<
20.589 + " current state " << m_state);
20.590 + ProcessPacketAction (action, packet, tcpHeader, address);
20.591 +}
20.592 +
20.593 +Actions_t Tcp6SocketImpl::ProcessEvent (Events_t e)
20.594 +{
20.595 + NS_LOG_FUNCTION (this << e);
20.596 + States_t saveState = m_state;
20.597 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " processing event " << e);
20.598 + // simulation singleton is a way to get a single global static instance of a
20.599 + // class intended to be a singleton; see simulation-singleton.h
20.600 + SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
20.601 + // debug
20.602 + if (stateAction.action == RST_TX)
20.603 + {
20.604 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " sending RST from state "
20.605 + << saveState << " event " << e);
20.606 + }
20.607 + bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED
20.608 + && e != TIMEOUT);
20.609 + m_state = stateAction.state;
20.610 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " moved from state " << saveState
20.611 + << " to state " <<m_state);
20.612 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " pendingData " << m_pendingData);
20.613 +
20.614 + //extra event logic is here for RX events
20.615 + //e = SYN_ACK_RX
20.616 + if (saveState == SYN_SENT && m_state == ESTABLISHED)
20.617 + // this means the application side has completed its portion of
20.618 + // the handshaking
20.619 + {
20.620 + Simulator::ScheduleNow(&Tcp6SocketImpl::ConnectionSucceeded, this);
20.621 + //NotifyConnectionSucceeded ();
20.622 + m_connected = true;
20.623 + m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
20.624 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " Connected!");
20.625 + }
20.626 +
20.627 + if (needCloseNotify && !m_closeNotified)
20.628 + {
20.629 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " transition to CLOSED from "
20.630 + << m_state << " event " << e << " closeNot " << m_closeNotified
20.631 + << " action " << stateAction.action);
20.632 + m_closeNotified = true;
20.633 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " calling Closed from PE"
20.634 + << " origState " << saveState
20.635 + << " event " << e);
20.636 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " transition to CLOSED from "
20.637 + << m_state << " event " << e
20.638 + << " set CloseNotif ");
20.639 + }
20.640 + return stateAction.action;
20.641 +}
20.642 +
20.643 +void Tcp6SocketImpl::SendEmptyPacket (uint8_t flags)
20.644 +{
20.645 + NS_LOG_FUNCTION (this << flags);
20.646 + Ptr<Packet> p = Create<Packet> ();
20.647 + TcpHeader header;
20.648 +
20.649 + header.SetFlags (flags);
20.650 + header.SetSequenceNumber (m_nextTxSequence);
20.651 + header.SetAckNumber (m_nextRxSequence);
20.652 + header.SetSourcePort (m_endPoint->GetLocalPort ());
20.653 + header.SetDestinationPort (m_remotePort);
20.654 + header.SetWindowSize (m_advertisedWindowSize);
20.655 + m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
20.656 + m_remoteAddress);
20.657 + Time rto = m_rtt->RetransmitTimeout ();
20.658 + if (flags & TcpHeader::SYN)
20.659 + {
20.660 + rto = m_cnTimeout;
20.661 + m_cnTimeout = m_cnTimeout + m_cnTimeout;
20.662 + m_cnCount--;
20.663 + }
20.664 + if (m_retxEvent.IsExpired () ) //no outstanding timer
20.665 + {
20.666 + NS_LOG_LOGIC ("Schedule retransmission timeout at time "
20.667 + << Simulator::Now ().GetSeconds () << " to expire at time "
20.668 + << (Simulator::Now () + rto).GetSeconds ());
20.669 + m_retxEvent = Simulator::Schedule (rto, &Tcp6SocketImpl::ReTxTimeout, this);
20.670 + }
20.671 +}
20.672 +
20.673 +bool Tcp6SocketImpl::ProcessAction (Actions_t a)
20.674 +{ // These actions do not require a packet or any TCP Headers
20.675 + NS_LOG_FUNCTION (this << a);
20.676 + switch (a)
20.677 + {
20.678 + case NO_ACT:
20.679 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action: NO_ACT");
20.680 + break;
20.681 + case ACK_TX:
20.682 + SendEmptyPacket (TcpHeader::ACK);
20.683 + break;
20.684 + case ACK_TX_1:
20.685 + NS_ASSERT (false); // This should be processed in ProcessPacketAction
20.686 + break;
20.687 + case RST_TX:
20.688 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action RST_TX");
20.689 + SendEmptyPacket (TcpHeader::RST);
20.690 + break;
20.691 + case SYN_TX:
20.692 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action SYN_TX");
20.693 + // TCP SYN Flag consumes one byte
20.694 + // is the above correct? we're SENDING a syn, not acking back -- Raj
20.695 + // commented out for now
20.696 + // m_nextTxSequence+= 1;
20.697 + SendEmptyPacket (TcpHeader::SYN);
20.698 + break;
20.699 + case SYN_ACK_TX:
20.700 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action SYN_ACK_TX");
20.701 + // TCP SYN Flag consumes one byte
20.702 + ++m_nextRxSequence;
20.703 + SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
20.704 + break;
20.705 + case FIN_TX:
20.706 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action FIN_TX");
20.707 + SendEmptyPacket (TcpHeader::FIN);
20.708 + break;
20.709 + case FIN_ACK_TX:
20.710 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action FIN_ACK_TX");
20.711 + SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
20.712 + break;
20.713 + case NEW_ACK:
20.714 + NS_ASSERT (false); // This should be processed in ProcessPacketAction
20.715 + break;
20.716 + case NEW_SEQ_RX:
20.717 + NS_ASSERT (false); // This should be processed in ProcessPacketAction
20.718 + break;
20.719 + case RETX:
20.720 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action RETX");
20.721 + break;
20.722 + case TX_DATA:
20.723 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action TX_DATA");
20.724 + SendPendingData ();
20.725 + break;
20.726 + case PEER_CLOSE:
20.727 + NS_ASSERT (false); // This should be processed in ProcessPacketAction
20.728 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action PEER_CLOSE");
20.729 + break;
20.730 + case APP_CLOSED:
20.731 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action APP_CLOSED");
20.732 + break;
20.733 + case CANCEL_TM:
20.734 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action CANCEL_TM");
20.735 + break;
20.736 + case APP_NOTIFY:
20.737 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action APP_NOTIFY");
20.738 + break;
20.739 + case SERV_NOTIFY:
20.740 + NS_ASSERT (false); // This should be processed in ProcessPacketAction
20.741 + break;
20.742 + case LAST_ACTION:
20.743 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action LAST_ACTION");
20.744 + break;
20.745 + }
20.746 + return true;
20.747 +}
20.748 +
20.749 +bool Tcp6SocketImpl::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
20.750 + const TcpHeader& tcpHeader,
20.751 + const Address& fromAddress)
20.752 +{
20.753 + NS_LOG_FUNCTION (this << a << p << fromAddress);
20.754 + Ipv6Header header;
20.755 + Socket::SocketErrno errno_;
20.756 + Ptr<Ipv6Route> route;
20.757 + uint32_t oif = 0;
20.758 +
20.759 + Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
20.760 + switch (a)
20.761 + {
20.762 + case SYN_ACK_TX:
20.763 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action SYN_ACK_TX");
20.764 +// m_remotePort = Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ();
20.765 +// m_remoteAddress = Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 ();
20.766 +// if (ipv6->GetIfIndexForDestination (m_remoteAddress, localIfIndex))
20.767 +// {
20.768 +// m_localAddress = ipv6->GetAddress (localIfIndex);
20.769 +// }
20.770 + if (m_state == LISTEN) //this means we should fork a new Tcp6SocketImpl
20.771 + {
20.772 + NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
20.773 + //notify the server that we got a SYN
20.774 + // If server refuses connection do nothing
20.775 + if (!NotifyConnectionRequest(fromAddress)) return true;
20.776 + // Clone the socket
20.777 + Ptr<Tcp6SocketImpl> newSock = Copy ();
20.778 + NS_LOG_LOGIC ("Cloned a Tcp6SocketImpl " << newSock);
20.779 + //this listening socket should do nothing more
20.780 + Simulator::ScheduleNow (&Tcp6SocketImpl::CompleteFork, newSock,
20.781 + p, tcpHeader,fromAddress);
20.782 + return true;
20.783 + }
20.784 + // This is the cloned endpoint
20.785 + m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
20.786 +
20.787 + header.SetDestinationAddress (m_remoteAddress);
20.788 + oif = 0; //specify non-zero if bound to a source address
20.789 + route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
20.790 +
20.791 + if (route != 0)
20.792 + {
20.793 + m_endPoint->SetLocalAddress (route->GetSource());
20.794 + // Leave local addr in the portmap to any, as the path from
20.795 + // remote can change and packets can arrive on different interfaces
20.796 + //m_endPoint->SetLocalAddress (Ipv6Address::GetAny());
20.797 + }
20.798 + // TCP SYN consumes one byte
20.799 + m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
20.800 + SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
20.801 + break;
20.802 + case ACK_TX_1:
20.803 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action ACK_TX_1");
20.804 + // TCP SYN consumes one byte
20.805 + m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
20.806 + m_nextTxSequence = tcpHeader.GetAckNumber ();
20.807 + m_firstPendingSequence = m_nextTxSequence; //bug 166
20.808 + NS_LOG_DEBUG ("Tcp6SocketImpl " << this << " ACK_TX_1" <<
20.809 + " nextRxSeq " << m_nextRxSequence);
20.810 + SendEmptyPacket (TcpHeader::ACK);
20.811 + m_rxWindowSize = tcpHeader.GetWindowSize ();
20.812 + if (tcpHeader.GetAckNumber () > m_highestRxAck)
20.813 + {
20.814 + m_highestRxAck = tcpHeader.GetAckNumber ();
20.815 + // Data freed from the send buffer; notify any blocked sender
20.816 + if (m_wouldBlock)
20.817 + {
20.818 + m_wouldBlock = false;
20.819 + NotifySend (GetTxAvailable ());
20.820 + }
20.821 + }
20.822 + SendPendingData ();
20.823 + break;
20.824 + case NEW_ACK:
20.825 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action NEW_ACK_TX");
20.826 + if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
20.827 + {
20.828 + break;
20.829 + }
20.830 + if (tcpHeader.GetAckNumber () == m_highestRxAck &&
20.831 + tcpHeader.GetAckNumber () < m_nextTxSequence)
20.832 + {
20.833 + DupAck (tcpHeader, ++m_dupAckCount);
20.834 + break;
20.835 + }
20.836 + if (tcpHeader.GetAckNumber () > m_highestRxAck)
20.837 + {
20.838 + m_dupAckCount = 0;
20.839 + }
20.840 + NewAck (tcpHeader.GetAckNumber ());
20.841 + break;
20.842 + case NEW_SEQ_RX:
20.843 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action NEW_SEQ_RX");
20.844 + NewRx (p, tcpHeader, fromAddress); // Process new data received
20.845 + break;
20.846 + case PEER_CLOSE:
20.847 + {
20.848 + // First we have to be sure the FIN packet was not received
20.849 + // out of sequence. If so, note pending close and process
20.850 + // new sequence rx
20.851 + if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
20.852 + { // process close later
20.853 + m_pendingClose = true;
20.854 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " setting pendingClose"
20.855 + << " rxseq " << tcpHeader.GetSequenceNumber ()
20.856 + << " nextRxSeq " << m_nextRxSequence);
20.857 + NewRx (p, tcpHeader, fromAddress);
20.858 + return true;
20.859 + }
20.860 + // Now we need to see if any data came with the FIN
20.861 + // if so, call NewRx
20.862 + if (p->GetSize () != 0)
20.863 + {
20.864 + NewRx (p, tcpHeader, fromAddress);
20.865 + }
20.866 + States_t saveState = m_state; // Used to see if app responds
20.867 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this
20.868 + << " peer close, state " << m_state);
20.869 + if (!m_closeRequestNotified)
20.870 + {
20.871 + NS_LOG_LOGIC ("TCP " << this
20.872 + << " calling AppCloseRequest");
20.873 + m_closeRequestNotified = true;
20.874 + }
20.875 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this
20.876 + << " peer close, state after " << m_state);
20.877 + if (m_state == saveState)
20.878 + { // Need to ack, the application will close later
20.879 + SendEmptyPacket (TcpHeader::ACK);
20.880 +// // Also need to re-tx the ack if we
20.881 + }
20.882 + if (m_state == LAST_ACK)
20.883 + {
20.884 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " scheduling LATO1");
20.885 + m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
20.886 + &Tcp6SocketImpl::LastAckTimeout,this);
20.887 + }
20.888 + break;
20.889 + }
20.890 + case SERV_NOTIFY:
20.891 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this <<" Action SERV_NOTIFY");
20.892 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " Connected!");
20.893 + NotifyNewConnectionCreated (this, fromAddress);
20.894 + m_connected = true; // ! This is bogus; fix when we clone the tcp
20.895 + m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
20.896 + //treat the connection orientation final ack as a newack
20.897 + CommonNewAck (tcpHeader.GetAckNumber (), true);
20.898 + break;
20.899 + default:
20.900 + break;
20.901 + }
20.902 + return true;
20.903 +}
20.904 +
20.905 +void Tcp6SocketImpl::CompleteFork(Ptr<Packet> p, const TcpHeader& h, const Address& fromAddress)
20.906 +{
20.907 + // Get port and address from peer (connecting host)
20.908 + m_remotePort = Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ();
20.909 + m_remoteAddress = Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 ();
20.910 + m_endPoint = m_tcp->Allocate (m_localAddress,
20.911 + m_localPort,
20.912 + m_remoteAddress,
20.913 + m_remotePort);
20.914 + //the cloned socket with be in listen state, so manually change state
20.915 + m_state = SYN_RCVD;
20.916 + //equivalent to FinishBind
20.917 + m_endPoint->SetRxCallback (MakeCallback (&Tcp6SocketImpl::ForwardUp, Ptr<Tcp6SocketImpl>(this)));
20.918 + m_endPoint->SetDestroyCallback (MakeCallback (&Tcp6SocketImpl::Destroy, Ptr<Tcp6SocketImpl>(this)));
20.919 + ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress);
20.920 + }
20.921 +
20.922 +void Tcp6SocketImpl::ConnectionSucceeded()
20.923 +{ // We would preferred to have scheduled an event directly to
20.924 + // NotifyConnectionSucceeded, but (sigh) these are protected
20.925 + // and we can get the address of it :(
20.926 + NotifyConnectionSucceeded();
20.927 +}
20.928 +
20.929 +bool Tcp6SocketImpl::SendPendingData (bool withAck)
20.930 +{
20.931 + NS_LOG_FUNCTION (this << withAck);
20.932 + NS_LOG_LOGIC ("ENTERING SendPendingData");
20.933 + if (!m_pendingData)
20.934 + {
20.935 + return false; // No data exists
20.936 + }
20.937 + uint32_t nPacketsSent = 0;
20.938 + while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
20.939 + {
20.940 + uint32_t w = AvailableWindow ();// Get available window size
20.941 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " SendPendingData"
20.942 + << " w " << w
20.943 + << " rxwin " << m_rxWindowSize
20.944 + << " cWnd " << m_cWnd
20.945 + << " segsize " << m_segmentSize
20.946 + << " nextTxSeq " << m_nextTxSequence
20.947 + << " highestRxAck " << m_highestRxAck
20.948 + << " pd->Size " << m_pendingData->Size ()
20.949 + << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
20.950 +
20.951 + if (w < m_segmentSize && m_pendingData->Size () > w)
20.952 + {
20.953 + break; // No more
20.954 + }
20.955 + uint32_t s = std::min (w, m_segmentSize); // Send no more than window
20.956 + Ptr<Packet> p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence,
20.957 + m_nextTxSequence);
20.958 + NS_LOG_LOGIC("Tcp6SocketImpl " << this << " SendPendingData"
20.959 + << " txseq " << m_nextTxSequence
20.960 + << " s " << s
20.961 + << " datasize " << p->GetSize() );
20.962 + uint8_t flags = 0;
20.963 + if (withAck)
20.964 + {
20.965 + flags |= TcpHeader::ACK;
20.966 + }
20.967 + uint32_t sz = p->GetSize (); // Size of packet
20.968 + uint32_t remainingData = m_pendingData->SizeFromSeq(
20.969 + m_firstPendingSequence,
20.970 + m_nextTxSequence + SequenceNumber (sz));
20.971 + if (m_closeOnEmpty && (remainingData == 0))
20.972 + {
20.973 + flags = TcpHeader::FIN;
20.974 + m_state = FIN_WAIT_1;
20.975 + }
20.976 +
20.977 + TcpHeader header;
20.978 + header.SetFlags (flags);
20.979 + header.SetSequenceNumber (m_nextTxSequence);
20.980 + header.SetAckNumber (m_nextRxSequence);
20.981 + header.SetSourcePort (m_endPoint->GetLocalPort());
20.982 + header.SetDestinationPort (m_remotePort);
20.983 + if (m_shutdownSend)
20.984 + {
20.985 + m_errno = ERROR_SHUTDOWN;
20.986 + return -1;
20.987 + }
20.988 +
20.989 +
20.990 + if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
20.991 + {
20.992 + Time rto = m_rtt->RetransmitTimeout ();
20.993 + NS_LOG_LOGIC ("SendPendingData Schedule retransmission timeout at time " <<
20.994 + Simulator::Now ().GetSeconds () << " to expire at time " <<
20.995 + (Simulator::Now () + rto).GetSeconds () );
20.996 + m_retxEvent = Simulator::Schedule (rto,&Tcp6SocketImpl::ReTxTimeout,this);
20.997 + }
20.998 + NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
20.999 + m_tcp->SendPacket (p, header,
20.1000 + m_endPoint->GetLocalAddress (),
20.1001 + m_remoteAddress);
20.1002 + m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT
20.1003 + // Notify the application
20.1004 + Simulator::ScheduleNow(&Tcp6SocketImpl::NotifyDataSent, this, p->GetSize ());
20.1005 + nPacketsSent++; // Count sent this loop
20.1006 + m_nextTxSequence += sz; // Advance next tx sequence
20.1007 + // Note the high water mark
20.1008 + m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);
20.1009 + }
20.1010 + NS_LOG_LOGIC ("SendPendingData Sent "<<nPacketsSent<<" packets");
20.1011 + NS_LOG_LOGIC("RETURN SendPendingData");
20.1012 + return (nPacketsSent>0);
20.1013 +}
20.1014 +
20.1015 +uint32_t Tcp6SocketImpl::UnAckDataCount ()
20.1016 +{
20.1017 + NS_LOG_FUNCTION_NOARGS ();
20.1018 + return m_nextTxSequence - m_highestRxAck;
20.1019 +}
20.1020 +
20.1021 +uint32_t Tcp6SocketImpl::BytesInFlight ()
20.1022 +{
20.1023 + NS_LOG_FUNCTION_NOARGS ();
20.1024 + return m_highTxMark - m_highestRxAck;
20.1025 +}
20.1026 +
20.1027 +uint32_t Tcp6SocketImpl::Window ()
20.1028 +{
20.1029 + NS_LOG_FUNCTION_NOARGS ();
20.1030 + NS_LOG_LOGIC ("Tcp6SocketImpl::Window() "<<this);
20.1031 + return std::min (m_rxWindowSize, m_cWnd.Get());
20.1032 +}
20.1033 +
20.1034 +uint32_t Tcp6SocketImpl::AvailableWindow ()
20.1035 +{
20.1036 + NS_LOG_FUNCTION_NOARGS ();
20.1037 + uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
20.1038 + uint32_t win = Window ();
20.1039 + if (win < unack)
20.1040 + {
20.1041 + return 0; // No space available
20.1042 + }
20.1043 + return (win - unack); // Amount of window space available
20.1044 +}
20.1045 +
20.1046 +void Tcp6SocketImpl::NewRx (Ptr<Packet> p,
20.1047 + const TcpHeader& tcpHeader,
20.1048 + const Address& fromAddress)
20.1049 +{
20.1050 + NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress);
20.1051 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " NewRx,"
20.1052 + << " seq " << tcpHeader.GetSequenceNumber()
20.1053 + << " ack " << tcpHeader.GetAckNumber()
20.1054 + << " p.size is " << p->GetSize () );
20.1055 + NS_LOG_DEBUG ("Tcp6SocketImpl " << this <<
20.1056 + " NewRx," <<
20.1057 + " seq " << tcpHeader.GetSequenceNumber() <<
20.1058 + " ack " << tcpHeader.GetAckNumber() <<
20.1059 + " p.size is " << p->GetSize());
20.1060 + States_t origState = m_state;
20.1061 + uint32_t s = p->GetSize (); // Size of associated data
20.1062 + if (s == 0)
20.1063 + {// Nothing to do if no associated data
20.1064 + return;
20.1065 + }
20.1066 + // Log sequence received if enabled
20.1067 + // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
20.1068 + // Three possibilities
20.1069 + // 1) Received seq is expected, buffer this, update rxAvailable, and ack
20.1070 + // 2) Received seq is < expected, just re-ack previous
20.1071 + // 3) Received seq is > expected, just re-ack previous and buffer data
20.1072 + if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
20.1073 + { // If seq is expected seq
20.1074 + // 1) Update nextRxSeq
20.1075 + // 2) Buffer this packet so Recv can read it
20.1076 + // 3) Send the ack
20.1077 + m_nextRxSequence += s; // Advance next expected sequence
20.1078 + //bytesReceived += s; // Statistics
20.1079 + NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
20.1080 + SocketAddressTag tag;
20.1081 + tag.SetAddress (fromAddress);
20.1082 + p->AddByteTag (tag);
20.1083 + //buffer this, it'll be read by call to Recv
20.1084 + UnAckData_t::iterator i =
20.1085 + m_bufferedData.find (tcpHeader.GetSequenceNumber () );
20.1086 + if (i != m_bufferedData.end () ) //we found it already in the buffer
20.1087 + {
20.1088 + i->second = 0; // relase reference to already buffered
20.1089 + }
20.1090 + // Save for later delivery
20.1091 + m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
20.1092 + m_rxAvailable += p->GetSize ();
20.1093 + //putting this into the buffer might have filled in a sequence gap
20.1094 + //so we have to iterate through the list to find the largest contiguous
20.1095 + //sequenced chunk, and update m_rxAvailable appropriately
20.1096 + i = m_bufferedData.find (tcpHeader.GetSequenceNumber () );
20.1097 + UnAckData_t::iterator next = i;
20.1098 + next++;
20.1099 + while(next != m_bufferedData.end())
20.1100 + {
20.1101 + if(i->first + SequenceNumber(i->second->GetSize ()) == next->first)
20.1102 + {
20.1103 + //next packet is in sequence, count it
20.1104 + m_rxAvailable += next->second->GetSize();
20.1105 + m_nextRxSequence += next->second->GetSize();
20.1106 + }
20.1107 + else
20.1108 + {
20.1109 + break; //no more in this contiguous chunk
20.1110 + }
20.1111 + ++i;
20.1112 + ++next;
20.1113 + }
20.1114 + NotifyDataRecv ();
20.1115 + if (m_closeNotified)
20.1116 + {
20.1117 + NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
20.1118 + }
20.1119 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " adv rxseq by " << s);
20.1120 + if (m_pendingClose || (origState > ESTABLISHED))
20.1121 + { // See if we can close now
20.1122 + if (m_bufferedData.empty())
20.1123 + {
20.1124 + ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
20.1125 + }
20.1126 + }
20.1127 + }
20.1128 + else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
20.1129 + { // Need to buffer this one
20.1130 + NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
20.1131 + UnAckData_t::iterator i =
20.1132 + m_bufferedData.find (tcpHeader.GetSequenceNumber () );
20.1133 + if (i != m_bufferedData.end () )
20.1134 + {
20.1135 + i->second = 0; // relase reference to already buffered
20.1136 + }
20.1137 + // Save for later delivery
20.1138 + SocketAddressTag tag;
20.1139 + tag.SetAddress (fromAddress);
20.1140 + p->AddByteTag (tag);
20.1141 + m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
20.1142 + }
20.1143 + else
20.1144 + { // debug
20.1145 + NS_LOG_LOGIC("TCP " << this
20.1146 + << " got seq " << tcpHeader.GetSequenceNumber ()
20.1147 + << " expected " << m_nextRxSequence
20.1148 + << " flags " << tcpHeader.GetFlags ());
20.1149 + }
20.1150 + // Now send a new ack packet acknowledging all received and delivered data
20.1151 + if(++m_delAckCount >= m_delAckMaxCount)
20.1152 + {
20.1153 + m_delAckEvent.Cancel();
20.1154 + m_delAckCount = 0;
20.1155 + SendEmptyPacket (TcpHeader::ACK);
20.1156 + }
20.1157 + else
20.1158 + {
20.1159 + m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &Tcp6SocketImpl::DelAckTimeout, this);
20.1160 + }
20.1161 +}
20.1162 +
20.1163 +void Tcp6SocketImpl::DelAckTimeout ()
20.1164 +{
20.1165 + m_delAckCount = 0;
20.1166 + SendEmptyPacket (TcpHeader::ACK);
20.1167 +}
20.1168 +
20.1169 +void Tcp6SocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer)
20.1170 +{ // CommonNewAck is called only for "New" (non-duplicate) acks
20.1171 + // and MUST be called by any subclass, from the NewAck function
20.1172 + // Always cancel any pending re-tx timer on new acknowledgement
20.1173 + NS_LOG_FUNCTION (this << ack << skipTimer);
20.1174 + //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
20.1175 + if (!skipTimer)
20.1176 + {
20.1177 + m_retxEvent.Cancel ();
20.1178 + //On recieving a "New" ack we restart retransmission timer .. RFC 2988
20.1179 + Time rto = m_rtt->RetransmitTimeout ();
20.1180 + NS_LOG_LOGIC ("Schedule retransmission timeout at time "
20.1181 + << Simulator::Now ().GetSeconds () << " to expire at time "
20.1182 + << (Simulator::Now () + rto).GetSeconds ());
20.1183 + m_retxEvent = Simulator::Schedule (rto, &Tcp6SocketImpl::ReTxTimeout, this);
20.1184 + }
20.1185 + NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack
20.1186 + << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed
20.1187 + m_highestRxAck = ack; // Note the highest recieved Ack
20.1188 + if (m_wouldBlock)
20.1189 + {
20.1190 + // m_highestRxAck advancing means some data was acked, and the size
20.1191 + // of free space in the buffer has increased
20.1192 + m_wouldBlock = false;
20.1193 + NotifySend (GetTxAvailable ());
20.1194 + }
20.1195 + if (ack > m_nextTxSequence)
20.1196 + {
20.1197 + m_nextTxSequence = ack; // If advanced
20.1198 + }
20.1199 + // See if all pending ack'ed; if so we can delete the data
20.1200 + if (m_pendingData)
20.1201 + { // Data exists, see if can be deleted
20.1202 + if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
20.1203 + { // All pending acked, can be deleted
20.1204 + m_pendingData->Clear ();
20.1205 + delete m_pendingData;
20.1206 + m_pendingData = 0;
20.1207 + // Insure no re-tx timer
20.1208 + m_retxEvent.Cancel ();
20.1209 + }
20.1210 + }
20.1211 + // Try to send more data
20.1212 + SendPendingData();
20.1213 +}
20.1214 +
20.1215 +Ptr<Tcp6SocketImpl> Tcp6SocketImpl::Copy ()
20.1216 +{
20.1217 + return CopyObject<Tcp6SocketImpl> (this);
20.1218 +}
20.1219 +
20.1220 +void Tcp6SocketImpl::NewAck (SequenceNumber seq)
20.1221 +{ // New acknowledgement up to sequence number "seq"
20.1222 + // Adjust congestion window in response to new ack's received
20.1223 + NS_LOG_FUNCTION (this << seq);
20.1224 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " NewAck "
20.1225 + << " seq " << seq
20.1226 + << " cWnd " << m_cWnd
20.1227 + << " ssThresh " << m_ssThresh);
20.1228 + if (m_cWnd < m_ssThresh)
20.1229 + { // Slow start mode, add one segSize to cWnd
20.1230 + m_cWnd += m_segmentSize;
20.1231 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " NewCWnd SlowStart, cWnd " << m_cWnd
20.1232 + << " sst " << m_ssThresh);
20.1233 + }
20.1234 + else
20.1235 + { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
20.1236 + double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd.Get();
20.1237 + if (adder < 1.0)
20.1238 + {
20.1239 + adder = 1.0;
20.1240 + }
20.1241 + m_cWnd += (uint32_t) adder;
20.1242 + NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd
20.1243 + << " sst " << m_ssThresh);
20.1244 + }
20.1245 + CommonNewAck (seq, false); // Complete newAck processing
20.1246 +}
20.1247 +
20.1248 +void Tcp6SocketImpl::DupAck (const TcpHeader& t, uint32_t count)
20.1249 +{
20.1250 + NS_LOG_FUNCTION (this << "t " << count);
20.1251 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " DupAck " << t.GetAckNumber ()
20.1252 + << ", count " << count
20.1253 + << ", time " << Simulator::Now ());
20.1254 + if (count == 3)
20.1255 + { // Count of three indicates triple duplicate ack
20.1256 + m_ssThresh = Window () / 2; // Per RFC2581
20.1257 + m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
20.1258 + NS_LOG_LOGIC("Tcp6SocketImpl " << this << "Tahoe TDA, time " << Simulator::Now ()
20.1259 + << " seq " << t.GetAckNumber ()
20.1260 + << " in flight " << BytesInFlight ()
20.1261 + << " new ssthresh " << m_ssThresh);
20.1262 +
20.1263 + m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
20.1264 + // For Tahoe, we also reset nextTxSeq
20.1265 + m_nextTxSequence = m_highestRxAck;
20.1266 + SendPendingData ();
20.1267 + }
20.1268 +}
20.1269 +
20.1270 +void Tcp6SocketImpl::ReTxTimeout ()
20.1271 +{ // Retransmit timeout
20.1272 + NS_LOG_FUNCTION (this);
20.1273 + m_ssThresh = Window () / 2; // Per RFC2581
20.1274 + m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
20.1275 + // Set cWnd to segSize on timeout, per rfc2581
20.1276 + // Collapse congestion window (re-enter slowstart)
20.1277 + m_cWnd = m_segmentSize;
20.1278 + m_nextTxSequence = m_highestRxAck; // Start from highest Ack
20.1279 + m_rtt->IncreaseMultiplier (); // DoubleValue timeout value for next retx timer
20.1280 + Retransmit (); // Retransmit the packet
20.1281 +}
20.1282 +
20.1283 +void Tcp6SocketImpl::LastAckTimeout ()
20.1284 +{
20.1285 + m_lastAckEvent.Cancel ();
20.1286 + if (m_state == LAST_ACK)
20.1287 + {
20.1288 + Actions_t action = ProcessEvent (TIMEOUT);
20.1289 + ProcessAction (action);
20.1290 + }
20.1291 + if (!m_closeNotified)
20.1292 + {
20.1293 + m_closeNotified = true;
20.1294 + }
20.1295 +}
20.1296 +
20.1297 +void Tcp6SocketImpl::Retransmit ()
20.1298 +{
20.1299 + NS_LOG_FUNCTION (this);
20.1300 + uint8_t flags = TcpHeader::NONE;
20.1301 + if (m_state == SYN_SENT)
20.1302 + {
20.1303 + if (m_cnCount > 0)
20.1304 + {
20.1305 + SendEmptyPacket (TcpHeader::SYN);
20.1306 + return;
20.1307 + }
20.1308 + else
20.1309 + {
20.1310 + NotifyConnectionFailed ();
20.1311 + return;
20.1312 + }
20.1313 + }
20.1314 + if (!m_pendingData)
20.1315 + {
20.1316 + if (m_state == FIN_WAIT_1)
20.1317 + { // Must have lost FIN, re-send
20.1318 + SendEmptyPacket (TcpHeader::FIN);
20.1319 + }
20.1320 + return;
20.1321 + }
20.1322 + Ptr<Packet> p = m_pendingData->CopyFromSeq (m_segmentSize,
20.1323 + m_firstPendingSequence,
20.1324 + m_highestRxAck);
20.1325 + // Calculate remaining data for COE check
20.1326 + uint32_t remainingData = m_pendingData->SizeFromSeq (
20.1327 + m_firstPendingSequence,
20.1328 + m_nextTxSequence + SequenceNumber(p->GetSize ()));
20.1329 + if (m_closeOnEmpty && remainingData == 0)
20.1330 + { // Add the FIN flag
20.1331 + flags = flags | TcpHeader::FIN;
20.1332 + }
20.1333 +
20.1334 + NS_LOG_LOGIC ("Tcp6SocketImpl " << this << " retxing seq " << m_highestRxAck);
20.1335 + if (m_retxEvent.IsExpired () )
20.1336 + {
20.1337 + Time rto = m_rtt->RetransmitTimeout ();
20.1338 + NS_LOG_LOGIC ("Schedule retransmission timeout at time "
20.1339 + << Simulator::Now ().GetSeconds () << " to expire at time "
20.1340 + << (Simulator::Now () + rto).GetSeconds ());
20.1341 + m_retxEvent = Simulator::Schedule (rto,&Tcp6SocketImpl::ReTxTimeout,this);
20.1342 + }
20.1343 + m_rtt->SentSeq (m_highestRxAck,p->GetSize ());
20.1344 + // And send the packet
20.1345 + TcpHeader tcpHeader;
20.1346 + tcpHeader.SetSequenceNumber (m_nextTxSequence);
20.1347 + tcpHeader.SetAckNumber (m_nextRxSequence);
20.1348 + tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
20.1349 + tcpHeader.SetDestinationPort (m_remotePort);
20.1350 + tcpHeader.SetFlags (flags);
20.1351 + tcpHeader.SetWindowSize (m_advertisedWindowSize);
20.1352 +
20.1353 + m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
20.1354 + m_remoteAddress);
20.1355 +}
20.1356 +
20.1357 +void
20.1358 +Tcp6SocketImpl::SetSndBufSize (uint32_t size)
20.1359 +{
20.1360 + m_sndBufSize = size;
20.1361 +}
20.1362 +
20.1363 +uint32_t
20.1364 +Tcp6SocketImpl::GetSndBufSize (void) const
20.1365 +{
20.1366 + return m_sndBufSize;
20.1367 +}
20.1368 +
20.1369 +void
20.1370 +Tcp6SocketImpl::SetRcvBufSize (uint32_t size)
20.1371 +{
20.1372 + m_rcvBufSize = size;
20.1373 +}
20.1374 +
20.1375 +uint32_t
20.1376 +Tcp6SocketImpl::GetRcvBufSize (void) const
20.1377 +{
20.1378 + return m_rcvBufSize;
20.1379 +}
20.1380 +
20.1381 +void
20.1382 +Tcp6SocketImpl::SetSegSize (uint32_t size)
20.1383 +{
20.1384 + m_segmentSize = size;
20.1385 +}
20.1386 +
20.1387 +uint32_t
20.1388 +Tcp6SocketImpl::GetSegSize (void) const
20.1389 +{
20.1390 + return m_segmentSize;
20.1391 +}
20.1392 +
20.1393 +void
20.1394 +Tcp6SocketImpl::SetAdvWin (uint32_t window)
20.1395 +{
20.1396 + m_advertisedWindowSize = window;
20.1397 +}
20.1398 +
20.1399 +uint32_t
20.1400 +Tcp6SocketImpl::GetAdvWin (void) const
20.1401 +{
20.1402 + return m_advertisedWindowSize;
20.1403 +}
20.1404 +
20.1405 +void
20.1406 +Tcp6SocketImpl::SetSSThresh (uint32_t threshold)
20.1407 +{
20.1408 + m_ssThresh = threshold;
20.1409 +}
20.1410 +
20.1411 +uint32_t
20.1412 +Tcp6SocketImpl::GetSSThresh (void) const
20.1413 +{
20.1414 + return m_ssThresh;
20.1415 +}
20.1416 +
20.1417 +void
20.1418 +Tcp6SocketImpl::SetInitialCwnd (uint32_t cwnd)
20.1419 +{
20.1420 + m_initialCWnd = cwnd;
20.1421 +}
20.1422 +
20.1423 +uint32_t
20.1424 +Tcp6SocketImpl::GetInitialCwnd (void) const
20.1425 +{
20.1426 + return m_initialCWnd;
20.1427 +}
20.1428 +
20.1429 +void
20.1430 +Tcp6SocketImpl::SetConnTimeout (Time timeout)
20.1431 +{
20.1432 + m_cnTimeout = timeout;
20.1433 +}
20.1434 +
20.1435 +Time
20.1436 +Tcp6SocketImpl::GetConnTimeout (void) const
20.1437 +{
20.1438 + return m_cnTimeout;
20.1439 +}
20.1440 +
20.1441 +void
20.1442 +Tcp6SocketImpl::SetConnCount (uint32_t count)
20.1443 +{
20.1444 + m_cnCount = count;
20.1445 +}
20.1446 +
20.1447 +uint32_t
20.1448 +Tcp6SocketImpl::GetConnCount (void) const
20.1449 +{
20.1450 + return m_cnCount;
20.1451 +}
20.1452 +
20.1453 +void
20.1454 +Tcp6SocketImpl::SetDelAckTimeout (Time timeout)
20.1455 +{
20.1456 + m_delAckTimeout = timeout;
20.1457 +}
20.1458 +
20.1459 +Time
20.1460 +Tcp6SocketImpl::GetDelAckTimeout (void) const
20.1461 +{
20.1462 + return m_delAckTimeout;
20.1463 +}
20.1464 +
20.1465 +void
20.1466 +Tcp6SocketImpl::SetDelAckMaxCount (uint32_t count)
20.1467 +{
20.1468 + m_delAckMaxCount = count;
20.1469 +}
20.1470 +
20.1471 +uint32_t
20.1472 +Tcp6SocketImpl::GetDelAckMaxCount (void) const
20.1473 +{
20.1474 + return m_delAckMaxCount;
20.1475 +}
20.1476 +
20.1477 +int
20.1478 +Tcp6SocketImpl::GetSockName (Address &address) const
20.1479 +{
20.1480 + NS_ASSERT (0);
20.1481 + return 0;
20.1482 +}
20.1483 +
20.1484 +}//namespace ns3
20.1485 +
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/src/internet-stack/tcp6-socket-impl.h Thu Oct 01 23:37:18 2009 +0900
21.3 @@ -0,0 +1,218 @@
21.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
21.5 +/*
21.6 + * Copyright (c) 2007 Georgia Tech Research Corporation
21.7 + *
21.8 + * This program is free software; you can redistribute it and/or modify
21.9 + * it under the terms of the GNU General Public License version 2 as
21.10 + * published by the Free Software Foundation;
21.11 + *
21.12 + * This program is distributed in the hope that it will be useful,
21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.15 + * GNU General Public License for more details.
21.16 + *
21.17 + * You should have received a copy of the GNU General Public License
21.18 + * along with this program; if not, write to the Free Software
21.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21.20 + *
21.21 + * Author: Raj Bhattacharjea <raj.b@gatech.edu>
21.22 + * Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
21.23 + */
21.24 +
21.25 +#ifndef TCP6_SOCKET_IMPL_H
21.26 +#define TCP6_SOCKET_IMPL_H
21.27 +
21.28 +#include <stdint.h>
21.29 +#include <queue>
21.30 +#include "ns3/callback.h"
21.31 +#include "ns3/traced-value.h"
21.32 +#include "ns3/tcp-socket.h"
21.33 +#include "ns3/ptr.h"
21.34 +#include "ns3/ipv6-address.h"
21.35 +#include "ns3/event-id.h"
21.36 +#include "tcp-typedefs.h"
21.37 +#include "pending-data.h"
21.38 +#include "sequence-number.h"
21.39 +#include "rtt-estimator.h"
21.40 +
21.41 +
21.42 +namespace ns3 {
21.43 +
21.44 +class Ipv6EndPoint;
21.45 +class Node;
21.46 +class Packet;
21.47 +class Tcp6L4Protocol;
21.48 +class TcpHeader;
21.49 +
21.50 +class Tcp6SocketImpl : public TcpSocket
21.51 +{
21.52 +public:
21.53 + static TypeId GetTypeId (void);
21.54 + /**
21.55 + * Create an unbound tcp socket.
21.56 + */
21.57 + Tcp6SocketImpl ();
21.58 + Tcp6SocketImpl (const Tcp6SocketImpl& sock);
21.59 + virtual ~Tcp6SocketImpl ();
21.60 +
21.61 + void SetNode (Ptr<Node> node);
21.62 + void SetTcp (Ptr<Tcp6L4Protocol> tcp);
21.63 + void SetRtt (Ptr<RttEstimator> rtt);
21.64 +
21.65 + virtual enum SocketErrno GetErrno (void) const;
21.66 + virtual Ptr<Node> GetNode (void) const;
21.67 + virtual int Bind (void);
21.68 + virtual int Bind (const Address &address);
21.69 + virtual int Close (void);
21.70 + virtual int ShutdownSend (void);
21.71 + virtual int ShutdownRecv (void);
21.72 + virtual int Connect(const Address &address);
21.73 + virtual uint32_t GetTxAvailable (void) const;
21.74 + virtual int Listen(void);
21.75 + virtual int Send (Ptr<Packet> p, uint32_t flags);
21.76 + virtual int SendTo(Ptr<Packet> p, uint32_t flags, const Address &toAddress);
21.77 + virtual uint32_t GetRxAvailable (void) const;
21.78 + virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
21.79 + virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress);
21.80 + virtual int GetSockName (Address &address) const;
21.81 +
21.82 +
21.83 +private:
21.84 + friend class Tcp;
21.85 + // invoked by Tcp class
21.86 + int FinishBind (void);
21.87 + void ForwardUp (Ptr<Packet> p, Ipv6Address ipv6, uint16_t port);
21.88 + void Destroy (void);
21.89 + int DoSendTo (Ptr<Packet> p, const Address &daddr);
21.90 + int DoSendTo (Ptr<Packet> p, Ipv6Address daddr, uint16_t dport);
21.91 + void SendEmptyPacket(uint8_t flags);
21.92 + //methods for state
21.93 + bool ProcessAction (Actions_t a);
21.94 + bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader,
21.95 + Ipv6Address saddr, Ipv6Address daddr);
21.96 + bool ProcessPacketAction (Actions_t a, Ptr<Packet> p,
21.97 + const TcpHeader& tcpHeader,
21.98 + const Address& fromAddress);
21.99 + Actions_t ProcessEvent (Events_t e);
21.100 + bool SendPendingData(bool withAck = false);
21.101 + void CompleteFork(Ptr<Packet>, const TcpHeader&, const Address& fromAddress);
21.102 + void ConnectionSucceeded();
21.103 +
21.104 + //methods for window management
21.105 + virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes
21.106 + virtual uint32_t BytesInFlight(); // Return total bytes in flight
21.107 + virtual uint32_t Window(); // Return window size (integer)
21.108 + virtual uint32_t AvailableWindow();// Return unfilled portion of window
21.109 +
21.110 + // Manage data tx/rx
21.111 + void NewRx (Ptr<Packet>, const TcpHeader&, const Address&);
21.112 + // XXX This should be virtual and overridden
21.113 + Ptr<Tcp6SocketImpl> Copy ();
21.114 + void NewAck (SequenceNumber seq);
21.115 + // XXX This should be virtual and overridden
21.116 + void DupAck (const TcpHeader& t, uint32_t count);
21.117 + void ReTxTimeout ();
21.118 + void DelAckTimeout ();
21.119 + void LastAckTimeout ();
21.120 + void Retransmit ();
21.121 + void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
21.122 +
21.123 + // attribute related
21.124 + virtual void SetSndBufSize (uint32_t size);
21.125 + virtual uint32_t GetSndBufSize (void) const;
21.126 + virtual void SetRcvBufSize (uint32_t size);
21.127 + virtual uint32_t GetRcvBufSize (void) const;
21.128 + virtual void SetSegSize (uint32_t size);
21.129 + virtual uint32_t GetSegSize (void) const;
21.130 + virtual void SetAdvWin (uint32_t window);
21.131 + virtual uint32_t GetAdvWin (void) const;
21.132 + virtual void SetSSThresh (uint32_t threshold);
21.133 + virtual uint32_t GetSSThresh (void) const;
21.134 + virtual void SetInitialCwnd (uint32_t cwnd);
21.135 + virtual uint32_t GetInitialCwnd (void) const;
21.136 + virtual void SetConnTimeout (Time timeout);
21.137 + virtual Time GetConnTimeout (void) const;
21.138 + virtual void SetConnCount (uint32_t count);
21.139 + virtual uint32_t GetConnCount (void) const;
21.140 + virtual void SetDelAckTimeout (Time timeout);
21.141 + virtual Time GetDelAckTimeout (void) const;
21.142 + virtual void SetDelAckMaxCount (uint32_t count);
21.143 + virtual uint32_t GetDelAckMaxCount (void) const;
21.144 +
21.145 + bool m_skipRetxResched;
21.146 + uint32_t m_dupAckCount;
21.147 + EventId m_retxEvent;
21.148 + EventId m_lastAckEvent;
21.149 +
21.150 + EventId m_delAckEvent;
21.151 + uint32_t m_delAckCount;
21.152 + uint32_t m_delAckMaxCount;
21.153 + Time m_delAckTimeout;
21.154 +
21.155 + Ipv6EndPoint *m_endPoint;
21.156 + Ptr<Node> m_node;
21.157 + Ptr<Tcp6L4Protocol> m_tcp;
21.158 + Ipv6Address m_remoteAddress;
21.159 + uint16_t m_remotePort;
21.160 + //these two are so that the socket/endpoint cloning works
21.161 + Ipv6Address m_localAddress;
21.162 + uint16_t m_localPort;
21.163 + enum SocketErrno m_errno;
21.164 + bool m_shutdownSend;
21.165 + bool m_shutdownRecv;
21.166 + bool m_connected;
21.167 +
21.168 + //manage the state infomation
21.169 + States_t m_state;
21.170 + bool m_closeNotified;
21.171 + bool m_closeRequestNotified;
21.172 + bool m_closeOnEmpty;
21.173 + bool m_pendingClose;
21.174 +
21.175 +
21.176 + //sequence info, sender side
21.177 + SequenceNumber m_nextTxSequence;
21.178 + SequenceNumber m_highTxMark;
21.179 + SequenceNumber m_highestRxAck;
21.180 + SequenceNumber m_lastRxAck;
21.181 +
21.182 + //sequence info, reciever side
21.183 + SequenceNumber m_nextRxSequence;
21.184 +
21.185 + //history data
21.186 + //this is the incoming data buffer which sorts out of sequence data
21.187 + UnAckData_t m_bufferedData;
21.188 + //this is kind of the tx buffer
21.189 + PendingData* m_pendingData;
21.190 + SequenceNumber m_firstPendingSequence;
21.191 +
21.192 + // Window management
21.193 + uint32_t m_segmentSize; //SegmentSize
21.194 + uint32_t m_rxWindowSize;
21.195 + uint32_t m_advertisedWindowSize; //Window to advertise
21.196 + TracedValue<uint32_t> m_cWnd; //Congestion window
21.197 + uint32_t m_ssThresh; //Slow Start Threshold
21.198 + uint32_t m_initialCWnd; //Initial cWnd value
21.199 +
21.200 + // Round trip time estimation
21.201 + Ptr<RttEstimator> m_rtt;
21.202 + Time m_lastMeasuredRtt;
21.203 +
21.204 + // Timer-related members
21.205 + Time m_cnTimeout;
21.206 + uint32_t m_cnCount;
21.207 +
21.208 + // Temporary queue for delivering data to application
21.209 + uint32_t m_rxAvailable;
21.210 +
21.211 + bool m_wouldBlock; // set to true whenever socket would block on send()
21.212 +
21.213 + // Attributes
21.214 + uint32_t m_sndBufSize; // buffer limit for the outgoing queue
21.215 + uint32_t m_rcvBufSize; // maximum receive socket buffer size
21.216 +};
21.217 +
21.218 +}//namespace ns3
21.219 +
21.220 +#endif /* TCP6_SOCKET_IMPL_H */
21.221 +
22.1 --- a/src/internet-stack/wscript Mon Sep 07 15:45:12 2009 +0200
22.2 +++ b/src/internet-stack/wscript Thu Oct 01 23:37:18 2009 +0900
22.3 @@ -110,7 +110,10 @@
22.4 'ipv6-raw-socket-impl.cc',
22.5 'ipv6-autoconfigured-prefix.cc',
22.6 'icmpv6-l4-protocol.cc',
22.7 - 'ipv6-test.cc'
22.8 + 'ipv6-test.cc',
22.9 + 'tcp6-socket-factory-impl.cc',
22.10 + 'tcp6-l4-protocol.cc',
22.11 + 'tcp6-socket-impl.cc',
22.12 ]
22.13
22.14 headers = bld.new_task_gen('ns3header')
22.15 @@ -128,6 +131,10 @@
22.16 'icmpv4-l4-protocol.h',
22.17 'ipv4-l4-protocol.h',
22.18 'arp-cache.h',
22.19 + 'ipv6-raw-socket-impl.h',
22.20 + 'ipv6-interface.h',
22.21 + 'ipv6-l3-protocol.h',
22.22 + 'ndisc-cache.h',
22.23 ]
22.24
22.25 if bld.env['NSC_ENABLED']:
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/src/mobility/oneway-mobility-model.cc Thu Oct 01 23:37:18 2009 +0900
23.3 @@ -0,0 +1,120 @@
23.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
23.5 +/*
23.6 + * Copyright (c) 2009 WIDE Project
23.7 + *
23.8 + * This program is free software; you can redistribute it and/or modify
23.9 + * it under the terms of the GNU General Public License version 2 as
23.10 + * published by the Free Software Foundation;
23.11 + *
23.12 + * This program is distributed in the hope that it will be useful,
23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.15 + * GNU General Public License for more details.
23.16 + *
23.17 + * You should have received a copy of the GNU General Public License
23.18 + * along with this program; if not, write to the Free Software
23.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23.20 + *
23.21 + * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
23.22 + */
23.23 +#include "ns3/simulator.h"
23.24 +#include "ns3/random-variable.h"
23.25 +#include "ns3/pointer.h"
23.26 +#include "oneway-mobility-model.h"
23.27 +#include "position-allocator.h"
23.28 +
23.29 +namespace ns3 {
23.30 +
23.31 +NS_OBJECT_ENSURE_REGISTERED (OnewayMobilityModel);
23.32 +
23.33 +TypeId
23.34 +OnewayMobilityModel::GetTypeId (void)
23.35 +{
23.36 + static TypeId tid = TypeId ("ns3::OnewayMobilityModel")
23.37 + .SetParent<MobilityModel> ()
23.38 + .SetGroupName ("Mobility")
23.39 + .AddConstructor<OnewayMobilityModel> ()
23.40 + .AddAttribute ("Speed",
23.41 + "A random variable used to pick the speed of a random waypoint model.",
23.42 + RandomVariableValue (UniformVariable (0.3, 0.7)),
23.43 + MakeRandomVariableAccessor (&OnewayMobilityModel::m_speed),
23.44 + MakeRandomVariableChecker ())
23.45 + .AddAttribute ("Pause",
23.46 + "A random variable used to pick the pause of a random waypoint model.",
23.47 + RandomVariableValue (ConstantVariable (2.0)),
23.48 + MakeRandomVariableAccessor (&OnewayMobilityModel::m_pause),
23.49 + MakeRandomVariableChecker ())
23.50 + .AddAttribute ("Wait",
23.51 + "A wait duration before moving.",
23.52 + RandomVariableValue (ConstantVariable (10.0)),
23.53 + MakeRandomVariableAccessor (&OnewayMobilityModel::m_wait),
23.54 + MakeRandomVariableChecker ())
23.55 + .AddAttribute ("Destination",
23.56 + "Destination.",
23.57 + VectorValue (Vector (0.0, 100.0, 0.0)),
23.58 + MakeVectorAccessor (&OnewayMobilityModel::m_destination),
23.59 + MakeVectorChecker ())
23.60 + ;
23.61 +
23.62 + return tid;
23.63 +}
23.64 +
23.65 +OnewayMobilityModel::OnewayMobilityModel ()
23.66 +{
23.67 + Simulator::ScheduleNow (&OnewayMobilityModel::Start, this);
23.68 +}
23.69 +
23.70 +void
23.71 +OnewayMobilityModel::BeginWalk (void)
23.72 +{
23.73 + m_helper.Update ();
23.74 + Vector m_current = m_helper.GetCurrentPosition ();
23.75 + double dx = (m_destination.x - m_current.x);
23.76 + double dy = (m_destination.y - m_current.y);
23.77 + double dz = (m_destination.z - m_current.z);
23.78 + m_helper.SetVelocity (Vector (0.5*dx, 0.5*dy, 0.5*dz));
23.79 + m_helper.Unpause ();
23.80 + // Time travelDelay = Seconds (CalculateDistance (m_destination, m_current) / speed);
23.81 + Time travelDelay = Seconds (1.0);
23.82 + m_pause = ConstantVariable(1.0);
23.83 + m_event = Simulator::Schedule (travelDelay,
23.84 + &OnewayMobilityModel::Start, this);
23.85 + NotifyCourseChange ();
23.86 +}
23.87 +
23.88 +void
23.89 +OnewayMobilityModel::Start (void)
23.90 +{
23.91 + static int cnt = 0;
23.92 + if (cnt++ == 0)
23.93 + {
23.94 + m_pause = m_wait;
23.95 + }
23.96 + m_helper.Update ();
23.97 + m_helper.Pause ();
23.98 + Time pause = Seconds (m_pause.GetValue ());
23.99 + m_event = Simulator::Schedule (pause, &OnewayMobilityModel::BeginWalk, this);
23.100 + NotifyCourseChange ();
23.101 +}
23.102 +
23.103 +Vector
23.104 +OnewayMobilityModel::DoGetPosition (void) const
23.105 +{
23.106 + m_helper.Update ();
23.107 + return m_helper.GetCurrentPosition ();
23.108 +}
23.109 +void
23.110 +OnewayMobilityModel::DoSetPosition (const Vector &position)
23.111 +{
23.112 + m_helper.SetPosition (position);
23.113 + Simulator::Remove (m_event);
23.114 + Simulator::ScheduleNow (&OnewayMobilityModel::Start, this);
23.115 +}
23.116 +Vector
23.117 +OnewayMobilityModel::DoGetVelocity (void) const
23.118 +{
23.119 + return m_helper.GetVelocity ();
23.120 +}
23.121 +
23.122 +
23.123 +} // namespace ns3
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/src/mobility/oneway-mobility-model.h Thu Oct 01 23:37:18 2009 +0900
24.3 @@ -0,0 +1,68 @@
24.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
24.5 +/*
24.6 + * Copyright (c) 2009 WIDE Project
24.7 + *
24.8 + * This program is free software; you can redistribute it and/or modify
24.9 + * it under the terms of the GNU General Public License version 2 as
24.10 + * published by the Free Software Foundation;
24.11 + *
24.12 + * This program is distributed in the hope that it will be useful,
24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.15 + * GNU General Public License for more details.
24.16 + *
24.17 + * You should have received a copy of the GNU General Public License
24.18 + * along with this program; if not, write to the Free Software
24.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24.20 + *
24.21 + * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
24.22 + */
24.23 +#ifndef ONEWAY_MOBILITY_MODEL_H
24.24 +#define ONEWAY_MOBILITY_MODEL_H
24.25 +
24.26 +#include "constant-velocity-helper.h"
24.27 +#include "ns3/event-id.h"
24.28 +#include "mobility-model.h"
24.29 +#include "position-allocator.h"
24.30 +#include "ns3/ptr.h"
24.31 +#include "ns3/random-variable.h"
24.32 +
24.33 +namespace ns3 {
24.34 +
24.35 +/**
24.36 + * \brief a random waypoint mobility model
24.37 + *
24.38 + * Each object chooses a random destination "waypoint", a random speed,
24.39 + * and a random pause time: it then pauses for the specified pause time,
24.40 + * and starts moving towards the specified destination with the specified
24.41 + * speed. Once the destination is reached the process starts again.
24.42 + *
24.43 + * The implementation of this model is not 2d-specific. i.e. if you provide
24.44 + * a 3d random waypoint position model to this mobility model, the model
24.45 + * will still work. There is no 3d position allocator for now but it should
24.46 + * be trivial to add one.
24.47 + */
24.48 +class OnewayMobilityModel : public MobilityModel
24.49 +{
24.50 +public:
24.51 + static TypeId GetTypeId (void);
24.52 + OnewayMobilityModel ();
24.53 +private:
24.54 + void Start (void);
24.55 + void BeginWalk (void);
24.56 + virtual Vector DoGetPosition (void) const;
24.57 + virtual void DoSetPosition (const Vector &position);
24.58 + virtual Vector DoGetVelocity (void) const;
24.59 +
24.60 + ConstantVelocityHelper m_helper;
24.61 + Ptr<PositionAllocator> m_position;
24.62 + Vector m_destination;
24.63 + RandomVariable m_speed;
24.64 + RandomVariable m_pause;
24.65 + RandomVariable m_wait;
24.66 + EventId m_event;
24.67 +};
24.68 +
24.69 +} // namespace ns3
24.70 +
24.71 +#endif /* ONEWAY_MOBILITY_MODEL_H */
25.1 --- a/src/mobility/wscript Mon Sep 07 15:45:12 2009 +0200
25.2 +++ b/src/mobility/wscript Thu Oct 01 23:37:18 2009 +0900
25.3 @@ -14,6 +14,7 @@
25.4 'random-walk-2d-mobility-model.cc',
25.5 'random-direction-2d-mobility-model.cc',
25.6 'constant-acceleration-mobility-model.cc',
25.7 + 'oneway-mobility-model.cc',
25.8 ]
25.9
25.10 headers = bld.new_task_gen('ns3header')
25.11 @@ -30,4 +31,5 @@
25.12 'random-walk-2d-mobility-model.h',
25.13 'random-direction-2d-mobility-model.h',
25.14 'constant-acceleration-mobility-model.h',
25.15 + 'oneway-mobility-model.h',
25.16 ]
26.1 --- a/src/node/ipv6-address.cc Mon Sep 07 15:45:12 2009 +0200
26.2 +++ b/src/node/ipv6-address.cc Thu Oct 01 23:37:18 2009 +0900
26.3 @@ -680,6 +680,33 @@
26.4 return lookuphash (buf, sizeof (buf), 0);
26.5 }
26.6
26.7 +uint8_t
26.8 +Ipv6Prefix::PrefixLen (void)
26.9 +{
26.10 +
26.11 + uint8_t *pnt;
26.12 + uint8_t val;
26.13 + uint8_t len = 0;
26.14 + pnt = (uint8_t *) & m_prefix;
26.15 +
26.16 + while ((*pnt == 0xff) && len < 128)
26.17 + {
26.18 + len += 8;
26.19 + pnt++;
26.20 + }
26.21 +
26.22 + if (len < 128)
26.23 + {
26.24 + val = *pnt;
26.25 + while (val)
26.26 + {
26.27 + len++;
26.28 + val <<= 1;
26.29 + }
26.30 + }
26.31 + return len;
26.32 +}
26.33 +
26.34 ATTRIBUTE_HELPER_CPP (Ipv6Address);
26.35 ATTRIBUTE_HELPER_CPP (Ipv6Prefix);
26.36
27.1 --- a/src/node/ipv6-address.h Mon Sep 07 15:45:12 2009 +0200
27.2 +++ b/src/node/ipv6-address.h Thu Oct 01 23:37:18 2009 +0900
27.3 @@ -373,6 +373,8 @@
27.4 */
27.5 static Ipv6Prefix GetZero ();
27.6
27.7 + uint8_t PrefixLen (void);
27.8 +
27.9 private:
27.10 /**
27.11 * \brief The prefix representation.
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/src/node/netlink-attribute.cc Thu Oct 01 23:37:18 2009 +0900
28.3 @@ -0,0 +1,447 @@
28.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
28.5 +/*
28.6 +* Copyright (c) 2008 Liu Jian
28.7 +*
28.8 +* This program is free software; you can redistribute it and/or modify
28.9 +* it under the terms of the GNU General Public License version 2 as
28.10 +* published by the Free Software Foundation;
28.11 +*
28.12 +* This program is distributed in the hope that it will be useful,
28.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
28.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28.15 +* GNU General Public License for more details.
28.16 +*
28.17 +* You should have received a copy of the GNU General Public License
28.18 +* along with this program; if not, write to the Free Software
28.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28.20 +*
28.21 +* Author: Liu Jian <liujatp@gmail.com>
28.22 +*/
28.23 +
28.24 +#include "ns3/netlink-attribute.h"
28.25 +#include "ns3/netlink-message.h"
28.26 +#include "ns3/netlink-message-route.h"
28.27 +#include "ns3/address-utils.h"
28.28 +
28.29 +namespace ns3 {
28.30 +
28.31 +
28.32 +/***********************************************************************************
28.33 +* \ NetlinkAttributeValue
28.34 +***********************************************************************************/
28.35 +NetlinkAttributeValue::NetlinkAttributeValue ()
28.36 +{
28.37 + m_type = UNSPEC;
28.38 + m_u32 = 0;
28.39 +}
28.40 +
28.41 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, uint8_t v)
28.42 +{
28.43 + NS_ASSERT(type == U8);
28.44 + m_type = U8;
28.45 + m_u8 = v;
28.46 +}
28.47 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, uint16_t v)
28.48 +{
28.49 + NS_ASSERT(type == U16);
28.50 + m_type = U16;
28.51 + m_u16 = v;
28.52 +}
28.53 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, uint32_t v)
28.54 +{
28.55 + NS_ASSERT(type == U32);
28.56 + m_type = U32;
28.57 + m_u32 = v;
28.58 +}
28.59 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, uint64_t v)
28.60 +{
28.61 + NS_ASSERT(type == U64);
28.62 + m_type = U64;
28.63 + m_u64 = v;
28.64 +}
28.65 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, std::string v)
28.66 +{
28.67 + NS_ASSERT(type == STRING);
28.68 + m_type = STRING;
28.69 + m_string = v;
28.70 +}
28.71 +NetlinkAttributeValue:: NetlinkAttributeValue (NetlinkAttributeValueType type, Address v)
28.72 +{
28.73 + NS_ASSERT(type == ADDRESS);
28.74 + m_type = ADDRESS;
28.75 + m_address = v;
28.76 +}
28.77 +
28.78 +void
28.79 +NetlinkAttributeValue::SetType (NetlinkAttributeValueType type)
28.80 +{
28.81 + m_type = type;
28.82 +}
28.83 +NetlinkAttributeValueType
28.84 +NetlinkAttributeValue::GetType (void) const
28.85 +{
28.86 + return m_type;
28.87 +}
28.88 +void
28.89 +NetlinkAttributeValue::SetAddress (Address value)
28.90 +{
28.91 + m_address = value;
28.92 +}
28.93 +void
28.94 +NetlinkAttributeValue::SetString (std::string value)
28.95 +{
28.96 + m_string = value;
28.97 +}
28.98 +void
28.99 +NetlinkAttributeValue::SetU64 (uint64_t value)
28.100 +{
28.101 + m_u64 = value;
28.102 +}
28.103 +void
28.104 +NetlinkAttributeValue::SetU32 (uint32_t value)
28.105 +{
28.106 + m_u32 = value;
28.107 +}
28.108 +void
28.109 +NetlinkAttributeValue::SetU16 (uint16_t value)
28.110 +{
28.111 + m_u16 = value;
28.112 +}
28.113 +void
28.114 +NetlinkAttributeValue::SetU8 (uint8_t value)
28.115 +{
28.116 + m_u8 = value;
28.117 +}
28.118 +Address
28.119 +NetlinkAttributeValue::GetAddress (void) const
28.120 +{
28.121 + return m_address;
28.122 +}
28.123 +std::string
28.124 +NetlinkAttributeValue::GetString (void) const
28.125 +{
28.126 + return m_string;
28.127 +}
28.128 +uint64_t
28.129 +NetlinkAttributeValue::GetU64 (void) const
28.130 +{
28.131 + return m_u64;
28.132 +}
28.133 +uint32_t
28.134 +NetlinkAttributeValue::GetU32 (void) const
28.135 +{
28.136 + return m_u32;
28.137 +}
28.138 +uint16_t
28.139 +NetlinkAttributeValue::GetU16 (void) const
28.140 +{
28.141 + return m_u16;
28.142 +}
28.143 +uint8_t
28.144 +NetlinkAttributeValue::GetU8 (void) const
28.145 +{
28.146 + return m_u8;
28.147 +}
28.148 +
28.149 +void
28.150 +NetlinkAttributeValue::Serialize (Buffer::Iterator& start) const
28.151 +{
28.152 + uint32_t len;
28.153 +
28.154 + if (m_type == U8)
28.155 + {
28.156 + start.WriteU8 (m_u8);
28.157 + len = 1;
28.158 + }
28.159 + else if(m_type == U16)
28.160 + {
28.161 + start.WriteU16 (m_u16);
28.162 + len = 2;
28.163 + }
28.164 + else if(m_type == U32)
28.165 + {
28.166 + start.WriteU32 (m_u32);
28.167 + len = 4;
28.168 + }
28.169 + else if(m_type == STRING)
28.170 + {
28.171 + start.Write ((const uint8_t *)m_string.c_str (), (uint32_t)m_string.size ()+1);
28.172 + len = (uint32_t)m_string.size () + 1;
28.173 + }
28.174 + else if(m_type == ADDRESS)
28.175 + {
28.176 + WriteTo(start, m_address);
28.177 + len = m_address.GetLength ();
28.178 + }
28.179 + else
28.180 + {
28.181 + len = 0;
28.182 + }
28.183 + //netlink align
28.184 + start.WriteU8 (0, NETLINK_MSG_ALIGN(len) - len);
28.185 +}
28.186 +
28.187 +uint32_t
28.188 +NetlinkAttributeValue::DeserializeWithType (Buffer::Iterator& start, NetlinkAttributeValueType_e type, uint16_t remaining)
28.189 +{
28.190 + uint32_t len =0;
28.191 + m_type = type;
28.192 +
28.193 + if (m_type == U8)
28.194 + {
28.195 + m_u8 = start.ReadU8 ();
28.196 + len = 1;
28.197 + }
28.198 + else if(m_type == U16)
28.199 + {
28.200 + m_u16 = start.ReadU16 ();
28.201 + len = 2;
28.202 + }
28.203 + else if(m_type == U32)
28.204 + {
28.205 + m_u32 = start.ReadU32 ();
28.206 + len = 4;
28.207 + }
28.208 + else if (m_type == U64)
28.209 + {
28.210 + m_u64 = start.ReadU64 ();
28.211 + }
28.212 + else if(m_type == STRING)
28.213 + {
28.214 + char buf[512];
28.215 + uint32_t i = 0;
28.216 + do
28.217 + {
28.218 + buf[i] = start.ReadU8 ();
28.219 + } while (buf[i++]);
28.220 +
28.221 + m_string = std::string(buf);
28.222 + len = (uint32_t)m_string.size () + 1;
28.223 + }
28.224 + else if(m_type == ADDRESS)
28.225 + {
28.226 + ReadFrom(start, m_address, remaining);
28.227 + len = m_address.GetLength ();
28.228 + }
28.229 + else
28.230 + {
28.231 + len = 0;
28.232 + }
28.233 +
28.234 + //netlink align
28.235 + uint8_t buf[4];
28.236 + start.Read(buf, NETLINK_MSG_ALIGN(len) - len);
28.237 +
28.238 + return NETLINK_MSG_ALIGN(len);
28.239 +}
28.240 +
28.241 +uint32_t
28.242 +NetlinkAttributeValue::GetSerializedSize ()const
28.243 +{
28.244 + return NETLINK_MSG_ALIGN(GetSize ());
28.245 +}
28.246 +
28.247 +uint32_t
28.248 +NetlinkAttributeValue::GetSize () const
28.249 +{
28.250 + uint32_t len;
28.251 +
28.252 + if (m_type == U8)
28.253 + {
28.254 + len = 1;
28.255 + }
28.256 + else if(m_type == U16)
28.257 + {
28.258 + len = 2;
28.259 + }
28.260 + else if(m_type == U32)
28.261 + {
28.262 + len = 4;
28.263 + }
28.264 + else if (m_type == STRING)
28.265 + {
28.266 + len = uint32_t(m_string.size () + 1);
28.267 + }
28.268 + else if (m_type == ADDRESS)
28.269 + {
28.270 + len = m_address.GetLength ();
28.271 + }
28.272 + else
28.273 + {
28.274 + len = 0;
28.275 + }
28.276 +
28.277 + return len;
28.278 +}
28.279 +
28.280 +void
28.281 +NetlinkAttributeValue::Print(std::ostream &os) const
28.282 +{
28.283 + os << "NetlinkAttributeValue (type= " << m_type <<", v= ";
28.284 + if (m_type == U8)
28.285 + {
28.286 + os << m_u8;
28.287 + }
28.288 + else if(m_type == U16)
28.289 + {
28.290 + os << m_u16;
28.291 + }
28.292 + else if(m_type == U32)
28.293 + {
28.294 + os << m_u32;
28.295 + }
28.296 + else if (m_type == U64)
28.297 + {
28.298 + os << m_u64;
28.299 + }
28.300 + else if (m_type == STRING)
28.301 + {
28.302 + os << m_string;
28.303 + }
28.304 + else if (m_type == ADDRESS)
28.305 + {
28.306 + os << "address(" << m_address <<")";
28.307 + }
28.308 + else
28.309 + {
28.310 + os << "NULL";
28.311 + }
28.312 + os <<")";
28.313 +}
28.314 +
28.315 +
28.316 +/***********************************************************************************
28.317 +* \ NetlinkAttribute
28.318 +***********************************************************************************/
28.319 +
28.320 +NetlinkAttribute::NetlinkAttribute ()
28.321 +: m_len(4),
28.322 + m_type (0)
28.323 +{
28.324 +}
28.325 +
28.326 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint8_t payload)
28.327 +{
28.328 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.329 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.330 + m_type = type;
28.331 +}
28.332 +
28.333 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint16_t payload)
28.334 +{
28.335 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.336 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.337 + m_type = type;
28.338 +}
28.339 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint32_t payload)
28.340 +{
28.341 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.342 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.343 + m_type = type;;
28.344 +}
28.345 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint64_t payload)
28.346 +{
28.347 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.348 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.349 + m_type = type;
28.350 +}
28.351 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, std::string payload)
28.352 +{
28.353 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.354 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.355 + m_type = type;
28.356 +}
28.357 +NetlinkAttribute::NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, Address payload)
28.358 +{
28.359 + m_payload = NetlinkAttributeValue (payloadtype, payload);
28.360 + m_len = NETLINK_MSG_ATTR_SIZE + m_payload.GetSize ();
28.361 + m_type = type;
28.362 +}
28.363 +
28.364 +void
28.365 +NetlinkAttribute::SetAttrLen(uint16_t v)
28.366 +{
28.367 + m_len = v;
28.368 +}
28.369 +void
28.370 +NetlinkAttribute::SetAttrType (uint16_t v)
28.371 +{
28.372 + m_type = v;
28.373 +}
28.374 +void
28.375 +NetlinkAttribute::SetAttrPayload(NetlinkAttributeValue v)
28.376 +{
28.377 + m_payload = v;
28.378 +}
28.379 +uint16_t
28.380 +NetlinkAttribute::GetAttrLen() const
28.381 +{
28.382 + return m_len;
28.383 +}
28.384 +uint16_t
28.385 +NetlinkAttribute::GetAttrType () const
28.386 +{
28.387 + return m_type;
28.388 +}
28.389 +NetlinkAttributeValue
28.390 +NetlinkAttribute::GetAttrPayload() const
28.391 +{
28.392 + return m_payload;
28.393 +}
28.394 +
28.395 +//TypeId
28.396 +//NetlinkAttribute::GetTypeId (void)
28.397 +//{
28.398 +// static TypeId tid = TypeId ("ns3::NetlinkAttribute")
28.399 +// .SetParent<Header> ()
28.400 +// .AddConstructor<NetlinkAttribute> ()
28.401 +// ;
28.402 +// return tid;
28.403 +//}
28.404 +//
28.405 +//TypeId
28.406 +//NetlinkAttribute::GetInstanceTypeId (void) const
28.407 +//{
28.408 +// return GetTypeId ();
28.409 +//}
28.410 +
28.411 +void
28.412 +NetlinkAttribute::Print (std::ostream &os) const
28.413 +{
28.414 + os << "NetlinkAttribute "
28.415 + << "len: " << m_len << " "
28.416 + << "type: " << m_type<<" "
28.417 + << "payload:[";
28.418 + m_payload.Print(os);
28.419 + os<<"]";
28.420 +}
28.421 +
28.422 +uint32_t
28.423 +NetlinkAttribute::GetSerializedSize (void) const
28.424 +{
28.425 + /* this is the size of an nlattr payload. */
28.426 + return NETLINK_MSG_ATTR_SIZE + m_payload.GetSerializedSize ();
28.427 +}
28.428 +
28.429 +void
28.430 +NetlinkAttribute::Serialize (Buffer::Iterator& start) const
28.431 +{
28.432 + start.WriteU16 (m_len);
28.433 + start.WriteU16 (m_type);
28.434 + m_payload.Serialize (start);
28.435 +}
28.436 +
28.437 +uint32_t
28.438 +NetlinkAttribute::Deserialize (Buffer::Iterator& start, NetlinkAttributeValueType vtypes[])
28.439 +{
28.440 + NetlinkAttributeValueType type;
28.441 +
28.442 + m_len = start.ReadU16 ();
28.443 + m_type = start.ReadU16 ();
28.444 + type = vtypes[m_type];
28.445 + m_payload.DeserializeWithType (start, type, m_len - 4);
28.446 +
28.447 + return GetSerializedSize ();
28.448 +}
28.449 +
28.450 +}; // namespace ns3
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/src/node/netlink-attribute.h Thu Oct 01 23:37:18 2009 +0900
29.3 @@ -0,0 +1,123 @@
29.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
29.5 +/*
29.6 +* Copyright (c) 2008 Liu Jian
29.7 +*
29.8 +* This program is free software; you can redistribute it and/or modify
29.9 +* it under the terms of the GNU General Public License version 2 as
29.10 +* published by the Free Software Foundation;
29.11 +*
29.12 +* This program is distributed in the hope that it will be useful,
29.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
29.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29.15 +* GNU General Public License for more details.
29.16 +*
29.17 +* You should have received a copy of the GNU General Public License
29.18 +* along with this program; if not, write to the Free Software
29.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29.20 +*
29.21 +* Author: Liu Jian <liujatp@gmail.com>
29.22 +*/
29.23 +
29.24 +#ifndef NETLINK_ATTRIBUTE_H
29.25 +#define NETLINK_ATTRIBUTE_H
29.26 +
29.27 +
29.28 +#include <stdint.h>
29.29 +#include <string>
29.30 +#include <ostream>
29.31 +#include "ns3/address.h"
29.32 +#include "ns3/buffer.h"
29.33 +
29.34 +namespace ns3 {
29.35 +
29.36 +/**
29.37 +* \brief The Netlink Attribute
29.38 +*/
29.39 +
29.40 +typedef enum NetlinkAttributeValueType_e {
29.41 + UNSPEC, // invalid initial value.
29.42 + U8,
29.43 + U16,
29.44 + U32,
29.45 + U64,
29.46 + STRING,
29.47 + ADDRESS,
29.48 +}NetlinkAttributeValueType;
29.49 +
29.50 +class NetlinkAttributeValue
29.51 +{
29.52 +public:
29.53 + NetlinkAttributeValue ();
29.54 + NetlinkAttributeValue(NetlinkAttributeValueType type, uint8_t v);
29.55 + NetlinkAttributeValue(NetlinkAttributeValueType type, uint16_t v);
29.56 + NetlinkAttributeValue(NetlinkAttributeValueType type, uint32_t v);
29.57 + NetlinkAttributeValue(NetlinkAttributeValueType type, uint64_t v);
29.58 + NetlinkAttributeValue(NetlinkAttributeValueType type, std::string v);
29.59 + NetlinkAttributeValue(NetlinkAttributeValueType type, Address v);
29.60 +
29.61 + void Serialize (Buffer::Iterator& start) const;
29.62 + uint32_t DeserializeWithType (Buffer::Iterator& start, NetlinkAttributeValueType type, uint16_t remaining);
29.63 + uint32_t GetSerializedSize (void) const;
29.64 + uint32_t GetSize (void) const;
29.65 + void Print (std::ostream &os) const;
29.66 +
29.67 + void SetType(NetlinkAttributeValueType type);
29.68 + NetlinkAttributeValueType GetType (void) const;
29.69 + void SetAddress (Address value);
29.70 + void SetString (std::string value);
29.71 + void SetU64 (uint64_t value);
29.72 + void SetU32 (uint32_t value);
29.73 + void SetU16 (uint16_t value);
29.74 + void SetU8 (uint8_t value);
29.75 + Address GetAddress (void) const;
29.76 + std::string GetString (void) const;
29.77 + uint64_t GetU64(void) const;
29.78 + uint32_t GetU32 (void) const;
29.79 + uint16_t GetU16 (void) const;
29.80 + uint8_t GetU8 (void) const;
29.81 +
29.82 +private:
29.83 + NetlinkAttributeValueType m_type;
29.84 + uint64_t m_u64;
29.85 + uint32_t m_u32;
29.86 + uint16_t m_u16;
29.87 + uint8_t m_u8;
29.88 + std::string m_string;
29.89 + Address m_address;
29.90 +};
29.91 +
29.92 +struct NetlinkAttribute
29.93 +{
29.94 +public:
29.95 + NetlinkAttribute();
29.96 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint8_t payload);
29.97 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint16_t payload);
29.98 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint32_t payload);
29.99 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, uint64_t payload);
29.100 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, std::string payload);
29.101 + NetlinkAttribute (uint16_t type, NetlinkAttributeValueType payloadtype, Address payload);
29.102 +
29.103 + //static TypeId GetTypeId (void);
29.104 + //virtual TypeId GetInstanceTypeId (void) const;
29.105 + void Print (std::ostream &os) const;
29.106 + uint32_t GetSerializedSize (void) const;
29.107 + void Serialize (Buffer::Iterator& start) const;
29.108 + uint32_t Deserialize (Buffer::Iterator& start, NetlinkAttributeValueType vtypes[]);
29.109 +
29.110 + void SetAttrLen(uint16_t v);
29.111 + void SetAttrType(uint16_t v);
29.112 + void SetAttrPayload(NetlinkAttributeValue v);
29.113 + uint16_t GetAttrLen() const;
29.114 + uint16_t GetAttrType() const;
29.115 + NetlinkAttributeValue GetAttrPayload() const;
29.116 +
29.117 +private:
29.118 + static const int NETLINK_MSG_ATTR_SIZE = 4; /* size of the nlattr field*/
29.119 + uint16_t m_len;
29.120 + uint16_t m_type;
29.121 + NetlinkAttributeValue m_payload;
29.122 +};
29.123 +
29.124 +}; // namespace ns3
29.125 +
29.126 +#endif /* NETLINK_ATTRIBUTE_H */
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/src/node/netlink-ipv6-routing-table.cc Thu Oct 01 23:37:18 2009 +0900
30.3 @@ -0,0 +1,365 @@
30.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
30.5 +/*
30.6 + * Copyright (c) 2009 WIDE Project
30.7 + *
30.8 + * This program is free software; you can redistribute it and/or modify
30.9 + * it under the terms of the GNU General Public License version 2 as
30.10 + * published by the Free Software Foundation;
30.11 + *
30.12 + * This program is distributed in the hope that it will be useful,
30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30.15 + * GNU General Public License for more details.
30.16 + *
30.17 + * You should have received a copy of the GNU General Public License
30.18 + * along with this program; if not, write to the Free Software
30.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30.20 + *
30.21 + * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
30.22 + */
30.23 +
30.24 +#include "ns3/log.h"
30.25 +#include "ns3/packet.h"
30.26 +#include "ns3/net-device.h"
30.27 +#include "ns3/ipv6-address.h"
30.28 +#include "ns3/ipv6-route.h"
30.29 +#include "ns3/ipv6-routing-table-entry.h"
30.30 +#include "netlink-ipv6-routing-table.h"
30.31 +
30.32 +NS_LOG_COMPONENT_DEFINE("NetlinkIpv6RoutingTable");
30.33 +
30.34 +namespace ns3
30.35 +{
30.36 +
30.37 + NS_OBJECT_ENSURE_REGISTERED (NetlinkIpv6RoutingTable);
30.38 +
30.39 + TypeId
30.40 + NetlinkIpv6RoutingTable::GetTypeId (void)
30.41 + {
30.42 + static TypeId tid = TypeId ("ns3::NetlinkIpv6RoutingTable")
30.43 + .SetParent<Ipv6RoutingProtocol> ();
30.44 + return tid;
30.45 + }
30.46 +
30.47 + TypeId
30.48 + NetlinkIpv6RoutingTable::GetInstanceTypeId (void) const
30.49 + {
30.50 + return GetTypeId ();
30.51 + }
30.52 +
30.53 +
30.54 + NetlinkIpv6RoutingTable::NetlinkIpv6RoutingTable()
30.55 + {
30.56 + NS_LOG_FUNCTION_NOARGS();
30.57 + }
30.58 +
30.59 + void NetlinkIpv6RoutingTable::AddRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
30.60 + {
30.61 + NS_LOG_FUNCTION(this << network << networkPrefix << nextHop << interface << prefixToUse);
30.62 + Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
30.63 + *route=Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, nextHop, interface, prefixToUse);
30.64 + m_RouteTable.push_back(route);
30.65 + }
30.66 +
30.67 +
30.68 + bool NetlinkIpv6RoutingTable::HasNetworkDest(Ipv6Address network, uint32_t interfaceIndex)
30.69 + {
30.70 + NS_LOG_FUNCTION(this << network << interfaceIndex);
30.71 +
30.72 + /* in the network table */
30.73 + for (std::list<Ipv6RoutingTableEntry *>::iterator j=m_RouteTable.begin(); j!=m_RouteTable.end();j++)
30.74 + {
30.75 + NS_ASSERT((*j)->IsNetwork());
30.76 + Ipv6Prefix prefix= (*j)->GetDestNetworkPrefix();
30.77 + Ipv6Address entry=(*j)->GetDestNetwork();
30.78 +
30.79 + if (prefix.IsMatch(network, entry) && (*j)->GetInterface() == interfaceIndex)
30.80 + {
30.81 + return true;
30.82 + }
30.83 + }
30.84 +
30.85 + /* beuh!!! not route at all */
30.86 + return false;
30.87 + }
30.88 +
30.89 + Ptr<Ipv6Route> NetlinkIpv6RoutingTable::Lookup (Ipv6Address dst, uint32_t interface)
30.90 + {
30.91 + NS_LOG_FUNCTION(this << dst);
30.92 + Ipv6RoutingTableEntry *longest = NULL;
30.93 + Ptr<Ipv6Route> rtentry = 0;
30.94 +
30.95 + if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast () ||
30.96 + dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
30.97 + {
30.98 + NS_ASSERT_MSG (interface > 0, "Try to send on link-local multicast address, and no interface index is given!");
30.99 + rtentry = Create<Ipv6Route> ();
30.100 + rtentry->SetSource (m_ipv6->GetAddress (interface, 0).GetAddress ());
30.101 + rtentry->SetDestination (dst);
30.102 + rtentry->SetGateway (Ipv6Address::GetZero ());
30.103 + rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interface));
30.104 + return rtentry;
30.105 + }
30.106 +
30.107 + /* or in the network table */
30.108 + for (std::list<Ipv6RoutingTableEntry *>::iterator j=m_RouteTable.begin(); j!=m_RouteTable.end();j++)
30.109 + {
30.110 + Ipv6Prefix prefix= (*j)->GetDestNetworkPrefix();
30.111 + Ipv6Address entry=(*j)->GetDestNetwork();
30.112 +
30.113 + if (prefix.IsMatch(dst, entry))
30.114 + {
30.115 + // Longest Match!
30.116 + if(longest == NULL ||
30.117 + longest->GetDestNetworkPrefix().PrefixLen() <
30.118 + (*j)->GetDestNetworkPrefix().PrefixLen() )
30.119 + longest = *j;
30.120 + }
30.121 + }
30.122 + if(longest)
30.123 + {
30.124 + Ptr<Ipv6Route> rtentry = 0;
30.125 + rtentry = Create<Ipv6Route> ();
30.126 + rtentry->SetDestination (dst);
30.127 + rtentry->SetGateway (longest->GetGateway());
30.128 + rtentry->SetOutputDevice (m_ipv6->GetNetDevice (longest->GetInterface ()));
30.129 + return rtentry;
30.130 + }
30.131 +
30.132 + /* beuh!!! not route at all */
30.133 + return 0;
30.134 + }
30.135 +
30.136 + void NetlinkIpv6RoutingTable::DoDispose ()
30.137 + {
30.138 + NS_LOG_FUNCTION_NOARGS();
30.139 + for (std::list<Ipv6RoutingTableEntry *>::iterator j = m_RouteTable.begin (); j != m_RouteTable.end (); j = m_RouteTable.erase (j))
30.140 + {
30.141 + delete (*j);
30.142 + }
30.143 + Ipv6RoutingProtocol::DoDispose ();
30.144 + }
30.145 +
30.146 +
30.147 + uint32_t NetlinkIpv6RoutingTable::GetNRoutes ()
30.148 + {
30.149 + NS_LOG_FUNCTION_NOARGS();
30.150 + return m_RouteTable.size ();
30.151 + }
30.152 +
30.153 +
30.154 + Ipv6RoutingTableEntry* NetlinkIpv6RoutingTable::GetRoute (uint32_t index)
30.155 + {
30.156 + NS_LOG_FUNCTION(this << index);
30.157 + uint32_t tmp = 0;
30.158 + for (std::list<Ipv6RoutingTableEntry *>::iterator j = m_RouteTable.begin (); j != m_RouteTable.end (); j++)
30.159 + {
30.160 + if (tmp == index)
30.161 + {
30.162 + return *j;
30.163 + }
30.164 + tmp++;
30.165 + }
30.166 + NS_ASSERT (false);
30.167 + // quiet compiler.
30.168 + return 0;
30.169 + }
30.170 +
30.171 + void NetlinkIpv6RoutingTable::RemoveRoute (uint32_t index)
30.172 + {
30.173 + NS_LOG_FUNCTION(this << index);
30.174 + uint32_t tmp = 0;
30.175 + for (std::list<Ipv6RoutingTableEntry *>::iterator j = m_RouteTable.begin ();j != m_RouteTable.end (); j++)
30.176 + {
30.177 + if (tmp == index)
30.178 + {
30.179 + delete *j;
30.180 + m_RouteTable.erase (j);
30.181 + return;
30.182 + }
30.183 + tmp++;
30.184 + }
30.185 + NS_ASSERT (false);
30.186 + }
30.187 +
30.188 + void NetlinkIpv6RoutingTable::RemoveRoute(Ipv6Address network)
30.189 + {
30.190 + NS_LOG_FUNCTION(this << network);
30.191 + for (std::list<Ipv6RoutingTableEntry *>::iterator i = m_RouteTable.begin (); i != m_RouteTable.end (); i++)
30.192 + {
30.193 + if(network == (*i)->GetDest())
30.194 + {
30.195 + delete *i;
30.196 + m_RouteTable.erase (i);
30.197 + return;
30.198 + }
30.199 + }
30.200 + }
30.201 +
30.202 + void NetlinkIpv6RoutingTable::RemoveRoute(Ipv6Address network, Ipv6Prefix prefix, uint32_t ifIndex)
30.203 + {
30.204 + NS_LOG_FUNCTION(this << network << prefix << ifIndex);
30.205 + for (std::list<Ipv6RoutingTableEntry *>::iterator i = m_RouteTable.begin (); i != m_RouteTable.end (); i++)
30.206 + {
30.207 + if(network == (*i)->GetDest() and (*i)->GetInterface() == ifIndex)
30.208 + {
30.209 + delete *i;
30.210 + m_RouteTable.erase (i);
30.211 + return;
30.212 + }
30.213 + }
30.214 + }
30.215 +
30.216 + Ptr<Ipv6Route> NetlinkIpv6RoutingTable::RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
30.217 + {
30.218 + NS_LOG_FUNCTION (this << header << oif);
30.219 + Ipv6Address destination = header.GetDestinationAddress ();
30.220 + Ptr<Ipv6Route> rtentry = 0;
30.221 +
30.222 + if (destination.IsMulticast ())
30.223 + {
30.224 + // Note: Multicast routes for outbound packets are stored in the
30.225 + // normal unicast table. An implication of this is that it is not
30.226 + // possible to source multicast datagrams on multiple interfaces.
30.227 + // This is a well-known property of sockets implementation on
30.228 + // many Unix variants.
30.229 + // So, we just log it and fall through to LookupStatic ()
30.230 + NS_LOG_LOGIC ("RouteOutput ()::Multicast destination");
30.231 + }
30.232 +
30.233 + rtentry = Lookup (destination, oif);
30.234 + if (rtentry)
30.235 + {
30.236 + sockerr = Socket::ERROR_NOTERROR;
30.237 + }
30.238 + else
30.239 + {
30.240 + sockerr = Socket::ERROR_NOROUTETOHOST;
30.241 + }
30.242 + return rtentry;
30.243 + }
30.244 +
30.245 + bool NetlinkIpv6RoutingTable::RouteInput(Ptr<const Packet> packet, const Ipv6Header &ipHeader, Ptr<const NetDevice> idev,
30.246 + UnicastForwardCallback ucb, MulticastForwardCallback mcb,
30.247 + LocalDeliverCallback lcb, ErrorCallback ecb)
30.248 +
30.249 + {
30.250 + NS_LOG_FUNCTION(this << idev << &ipHeader << packet << &ucb);
30.251 +
30.252 + NS_LOG_LOGIC("source = " << ipHeader.GetSourceAddress());
30.253 + NS_LOG_LOGIC("destination = " << ipHeader.GetDestinationAddress());
30.254 +
30.255 + if (ipHeader.GetDestinationAddress().IsMulticast())
30.256 + {
30.257 + NS_LOG_LOGIC ("Multicast destination");
30.258 + return false;
30.259 + }
30.260 +
30.261 + /* check if we have a unicast route */
30.262 + NS_LOG_LOGIC("Unicast destination");
30.263 + Ptr<Ipv6Route> route=Lookup(ipHeader.GetDestinationAddress(), 0);
30.264 + if (route)
30.265 + {
30.266 + NS_LOG_LOGIC("found route to destination");
30.267 + ucb(route, packet, ipHeader);
30.268 +
30.269 + return true;
30.270 + }
30.271 + else
30.272 + {
30.273 + NS_LOG_LOGIC("not found route to destination");
30.274 + return false; /* maybe other routing protocols can handle this route request */
30.275 + }
30.276 + }
30.277 +
30.278 + bool NetlinkIpv6RoutingTable::RequestIfIndex(Ipv6Address destination, uint32_t & ifIndex)
30.279 + {
30.280 + NS_LOG_FUNCTION(this << destination << &ifIndex);
30.281 +
30.282 + if (destination.IsMulticast())
30.283 + {
30.284 + NS_LOG_LOGIC("Multicast destination");
30.285 + return false;
30.286 + }
30.287 +
30.288 + /* see if this is a unicast packet we have a route for */
30.289 + NS_LOG_LOGIC("Unicast destination");
30.290 + Ptr<Ipv6Route> route=Lookup(destination, 0);
30.291 +
30.292 + if (route)
30.293 + {
30.294 + ifIndex=route->GetOutputDevice()->GetIfIndex();
30.295 + return true;
30.296 + }
30.297 + else
30.298 + {
30.299 + return false;
30.300 + }
30.301 + }
30.302 +
30.303 +#if 0
30.304 + bool NetlinkIpv6RoutingTable::RequestIfIndex(Ipv6Address destination, uint32_t & ifIndex, Ipv6Address& prefixToUse)
30.305 + {
30.306 + NS_LOG_FUNCTION(this << destination << &ifIndex);
30.307 +
30.308 + if (destination.IsMulticast())
30.309 + {
30.310 + NS_LOG_LOGIC("Multicast destination");
30.311 + return false;
30.312 + }
30.313 +
30.314 + /* see if this is a unicast packet we have a route for */
30.315 + NS_LOG_LOGIC("Unicast destination " << destination );
30.316 + Ptr<Ipv6Route> route=Lookup(destination, 0);
30.317 +
30.318 + if (route)
30.319 + {
30.320 + ifIndex=route->GetOutputDevice()->GetInterface();
30.321 + prefixToUse=route->GetPrefixToUse();
30.322 + return true;
30.323 + }
30.324 + else
30.325 + {
30.326 + return false;
30.327 + }
30.328 + }
30.329 +#endif
30.330 +
30.331 + void NetlinkIpv6RoutingTable::NotifyInterfaceUp (uint32_t interface)
30.332 + {
30.333 + return;
30.334 + }
30.335 +
30.336 + void NetlinkIpv6RoutingTable::NotifyInterfaceDown (uint32_t interface)
30.337 + {
30.338 + return;
30.339 + }
30.340 +
30.341 + void NetlinkIpv6RoutingTable::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address)
30.342 + {
30.343 + return;
30.344 + }
30.345 +
30.346 + void NetlinkIpv6RoutingTable::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address)
30.347 + {
30.348 + return;
30.349 + }
30.350 +
30.351 + void NetlinkIpv6RoutingTable::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
30.352 + {
30.353 + return;
30.354 + }
30.355 +
30.356 + void NetlinkIpv6RoutingTable::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface)
30.357 + {
30.358 + return;
30.359 + }
30.360 +
30.361 + void NetlinkIpv6RoutingTable::SetIpv6 (Ptr<Ipv6> ipv6)
30.362 + {
30.363 + m_ipv6 = ipv6;
30.364 + return;
30.365 + }
30.366 +
30.367 +} /* namespace ns3 */
30.368 +
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/src/node/netlink-ipv6-routing-table.h Thu Oct 01 23:37:18 2009 +0900
31.3 @@ -0,0 +1,168 @@
31.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
31.5 +/*
31.6 + * Copyright (c) 2009 WIDE Project
31.7 + *
31.8 + * This program is free software; you can redistribute it and/or modify
31.9 + * it under the terms of the GNU General Public License version 2 as
31.10 + * published by the Free Software Foundation;
31.11 + *
31.12 + * This program is distributed in the hope that it will be useful,
31.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
31.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31.15 + * GNU General Public License for more details.
31.16 + *
31.17 + * You should have received a copy of the GNU General Public License
31.18 + * along with this program; if not, write to the Free Software
31.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31.20 + *
31.21 + * Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
31.22 + */
31.23 +
31.24 +#ifndef NETLINK_IPV6_ROUTING_TABLE_H
31.25 +#define NETLINK_IPV6_ROUTING_TABLE_H
31.26 +
31.27 +#include <list>
31.28 +#include <stdint.h>
31.29 +#include "ns3/ipv6-address.h"
31.30 +#include "ns3/ipv6-header.h"
31.31 +#include "ns3/ptr.h"
31.32 +#include "ns3/ipv6.h"
31.33 +#include "ns3/ipv6-routing-protocol.h"
31.34 +#include "ns3/ipv6-routing-table-entry.h"
31.35 +
31.36 +namespace ns3
31.37 +{
31.38 + class Packet;
31.39 + class NetDevice;
31.40 + class Ipv6Interface;
31.41 + class Ipv6Route;
31.42 + class Node;
31.43 +
31.44 + /**
31.45 + * \class Ipv6NetlinkRoutingTable
31.46 + * \brief Routing protocol by Netlink for IP version 6 stacks.
31.47 + * \see Ipv6NetlinkRoutingTable
31.48 + * \see Ipv6L3Protocol::AddRoutingProtocol
31.49 + * \see Ipv6L3Protocol::Ipv6L3Protocol
31.50 + */
31.51 + class NetlinkIpv6RoutingTable : public Ipv6RoutingProtocol
31.52 + {
31.53 + public:
31.54 + static TypeId GetTypeId (void);
31.55 + TypeId GetInstanceTypeId (void) const;
31.56 + /**
31.57 + * \brief Constructor.
31.58 + */
31.59 + NetlinkIpv6RoutingTable();
31.60 +
31.61 + /**
31.62 + * \brief Synchronously check to see if we can determine the interface index
31.63 + * that will be used if a packet is sent to this destination.
31.64 + * \param dst The Ipv6Address if the destination of a hypothetical packet. This may be
31.65 + * a multicast group address.
31.66 + * \param ifIndex A reference to the interface index over which a packet
31.67 + * sent to this destination would be sent.
31.68 + * \return true if a route is found to the destination that involves a
31.69 + * single output interface index, false otherwise.
31.70 + */
31.71 + virtual bool RequestIfIndex(Ipv6Address dst, uint32_t & ifIndex);
31.72 +
31.73 + /**
31.74 + * \brief Synchronously check to see if we can determine the interface index
31.75 + * that will be used if a packet is sent to this destination.
31.76 + * \param dst The Ipv6Address if the destination of a hypothetical packet. This may be
31.77 + * a multicast group address.
31.78 + * \param ifIndex A reference to the interface index over which a packet
31.79 + * sent to this destination would be sent.
31.80 + * \param prefixToUse prefix to use (i.e for multihoming)
31.81 + * \return true if a route is found to the destination that involves a
31.82 + * single output interface index, false otherwise.
31.83 + */
31.84 +#if 0
31.85 + virtual bool RequestIfIndex(Ipv6Address dst, uint32_t & ifIndex, Ipv6Address& prefixToUse);
31.86 +#endif
31.87 +
31.88 + virtual Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
31.89 + virtual bool RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
31.90 + UnicastForwardCallback ucb, MulticastForwardCallback mcb,
31.91 + LocalDeliverCallback lcb, ErrorCallback ecb);
31.92 + virtual void NotifyInterfaceUp (uint32_t interface);
31.93 + virtual void NotifyInterfaceDown (uint32_t interface);
31.94 + virtual void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address);
31.95 + virtual void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address);
31.96 + virtual void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse);
31.97 + virtual void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface);
31.98 + virtual void SetIpv6 (Ptr<Ipv6> ipv6);
31.99 +
31.100 +
31.101 + /**
31.102 + * \brief Add route
31.103 + * \param network network address
31.104 + * \param networkPrefix network prefix*
31.105 + * \param nextHop next hop address to route the packet
31.106 + * \param interface interface index
31.107 + */
31.108 + void AddRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address("::"));
31.109 +
31.110 + /**
31.111 + * \brief Get the number or entries in the routing table.
31.112 + * \return number of entries
31.113 + */
31.114 + uint32_t GetNRoutes();
31.115 +
31.116 + /**
31.117 + * \brief Get a specified route.
31.118 + * \param i index
31.119 + * \return the route whose index is i
31.120 + */
31.121 + Ipv6RoutingTableEntry* GetRoute(uint32_t i);
31.122 +
31.123 + /**
31.124 + * \brief Remove a route from the routing table.
31.125 + * \param i index
31.126 + */
31.127 + void RemoveRoute(uint32_t i);
31.128 +
31.129 + void RemoveRoute(Ipv6Address network);
31.130 +
31.131 + /**
31.132 + * \brief Remove a route from the routing table.
31.133 + * \param network IPv6 network
31.134 + * \param prefix IPv6 prefix
31.135 + * \param ifIndex interface index
31.136 + */
31.137 + void RemoveRoute(Ipv6Address network, Ipv6Prefix prefix, uint32_t ifIndex);
31.138 +
31.139 + /**
31.140 + * \brief Lookup in the forwarding table for destination.
31.141 + * \param dest destination address
31.142 + * \return Ipv6Route to route the packet to reach dest address
31.143 + */
31.144 + Ptr<Ipv6Route> Lookup (Ipv6Address dest, uint32_t interface);
31.145 +
31.146 + /**
31.147 + * \brief If the destination is already present in network destination list.
31.148 + * \param dest destination address
31.149 + * \param interfaceIndex interface index
31.150 + * \return true if dest is already in list, false otherwise
31.151 + */
31.152 + bool HasNetworkDest(Ipv6Address dest, uint32_t interfaceIndex);
31.153 +
31.154 + protected:
31.155 + /**
31.156 + * \brief Dispose this object.
31.157 + */
31.158 + void DoDispose();
31.159 +
31.160 + private:
31.161 + /**
31.162 + * \brief the forwarding table for network.
31.163 + */
31.164 + std::list<Ipv6RoutingTableEntry *> m_RouteTable;
31.165 + Ptr<Ipv6> m_ipv6;
31.166 + };
31.167 +
31.168 +} /* namespace ns3 */
31.169 +
31.170 +#endif /* NETLINK_IPV6_ROUTING_TABLE_H */
31.171 +
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/src/node/netlink-message-route.cc Thu Oct 01 23:37:18 2009 +0900
32.3 @@ -0,0 +1,652 @@
32.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
32.5 +/*
32.6 +* Copyright (c) 2008 Liu Jian
32.7 +*
32.8 +* This program is free software; you can redistribute it and/or modify
32.9 +* it under the terms of the GNU General Public License version 2 as
32.10 +* published by the Free Software Foundation;
32.11 +*
32.12 +* This program is distributed in the hope that it will be useful,
32.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
32.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.15 +* GNU General Public License for more details.
32.16 +*
32.17 +* You should have received a copy of the GNU General Public License
32.18 +* along with this program; if not, write to the Free Software
32.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32.20 +*
32.21 +* Author: Liu Jian <liujatp@gmail.com>
32.22 +*/
32.23 +
32.24 +#include "ns3/netlink-message-route.h"
32.25 +#include "ns3/netlink-message.h"
32.26 +
32.27 +namespace ns3 {
32.28 +
32.29 +/***********************************************************************************
32.30 +* \ NetlinkPayload
32.31 +***********************************************************************************/
32.32 +TypeId
32.33 +NetlinkPayload::GetTypeId (void)
32.34 +{
32.35 + static TypeId tid = TypeId ("ns3::NetlinkPayload")
32.36 + .SetParent<ObjectBase> ()
32.37 + ;
32.38 + return tid;
32.39 +}
32.40 +
32.41 +
32.42 +/***********************************************************************************
32.43 +* \ GeneralMessage
32.44 +***********************************************************************************/
32.45 +
32.46 +NS_OBJECT_ENSURE_REGISTERED (GeneralMessage);
32.47 +NS_OBJECT_ENSURE_REGISTERED (InterfaceInfoMessage);
32.48 +NS_OBJECT_ENSURE_REGISTERED (InterfaceAddressMessage);
32.49 +NS_OBJECT_ENSURE_REGISTERED (RouteMessage);
32.50 +
32.51 +GeneralMessage::GeneralMessage ()
32.52 +: m_family(0)
32.53 +{}
32.54 +GeneralMessage::~GeneralMessage()
32.55 +{}
32.56 +
32.57 +void
32.58 +GeneralMessage::SetFamily(uint8_t v)
32.59 +{
32.60 + m_family = v;
32.61 +}
32.62 +uint8_t
32.63 +GeneralMessage::GetFamily(void) const
32.64 +{
32.65 + return m_family;
32.66 +}
32.67 +
32.68 +TypeId
32.69 +GeneralMessage::GetTypeId (void)
32.70 +{
32.71 + static TypeId tid = TypeId ("ns3::GeneralMessage")
32.72 + .SetParent<NetlinkPayload> ()
32.73 + .AddConstructor<GeneralMessage> ()
32.74 + ;
32.75 + return tid;
32.76 +}
32.77 +
32.78 +TypeId
32.79 +GeneralMessage::GetInstanceTypeId (void) const
32.80 +{
32.81 + return GetTypeId ();
32.82 +}
32.83 +void
32.84 +GeneralMessage::Print (std::ostream &os) const
32.85 +{
32.86 + os << " ----GeneralMessage ("
32.87 + << "family: " << (uint32_t)m_family << ")";
32.88 +}
32.89 +
32.90 +uint32_t
32.91 +GeneralMessage::GetSerializedSize (void) const
32.92 +{
32.93 + /* this is the size of an nlmsghdr payload. */
32.94 + return NETLINK_MSG_ALIGN(NETLINK_GENMSG_SIZE);
32.95 +}
32.96 +
32.97 +
32.98 +void
32.99 +GeneralMessage::Serialize (Buffer::Iterator& start) const
32.100 +{
32.101 + start.WriteU8 (m_family);
32.102 + start.WriteU8 (0, 3);
32.103 +}
32.104 +
32.105 +uint32_t
32.106 +GeneralMessage::Deserialize (Buffer::Iterator& start)
32.107 +{
32.108 + uint8_t buf[3];
32.109 +
32.110 + m_family = start.ReadU8 ();
32.111 + start.Read (buf, 3);
32.112 +
32.113 + return GetSerializedSize ();
32.114 +}
32.115 +
32.116 +uint32_t
32.117 +GeneralMessage::Deserialize (Buffer::Iterator& start, uint32_t len)
32.118 +{
32.119 + uint8_t buf[3];
32.120 +
32.121 + m_family = start.ReadU8 ();
32.122 + start.Read (buf, 3);
32.123 +
32.124 + return GetSerializedSize ();
32.125 +}
32.126 +
32.127 +
32.128 +uint32_t
32.129 +GeneralMessage::GetNNetlinkAttribute(void)const
32.130 +{
32.131 + return m_attributes.size();
32.132 +}
32.133 +NetlinkAttribute
32.134 +GeneralMessage::GetNetlinkAttribute(uint32_t index)const
32.135 +{
32.136 + NS_ASSERT(index < GetNNetlinkAttribute());
32.137 +
32.138 + return m_attributes[index];
32.139 +}
32.140 +
32.141 +uint32_t
32.142 +GeneralMessage::GetAttributeSerializedSize (void) const
32.143 +{
32.144 + uint32_t size = 0;
32.145 +
32.146 + for (uint32_t i = 0; i < m_attributes.size (); i ++)
32.147 + {
32.148 + size += m_attributes[i].GetSerializedSize();
32.149 + }
32.150 + return size;
32.151 +}
32.152 +bool
32.153 +GeneralMessage::GetAttributeByType(NetlinkAttribute& attr, uint16_t type)
32.154 +{
32.155 + for (uint32_t i = 0; i < m_attributes.size(); i ++)
32.156 + {
32.157 + if (type == m_attributes[i].GetAttrType())
32.158 + {
32.159 + attr = m_attributes[i];
32.160 + return true;
32.161 + }
32.162 + }
32.163 + return false;
32.164 +}
32.165 +void
32.166 +GeneralMessage::AppendAttribute (NetlinkAttribute v)
32.167 +{
32.168 + m_attributes.push_back(v);
32.169 +}
32.170 +
32.171 +void
32.172 +GeneralMessage::SerializeAttribute (Buffer::Iterator& start) const
32.173 +{
32.174 + for (uint32_t i = 0; i < m_attributes.size (); i ++)
32.175 + {
32.176 + m_attributes[i].Serialize (start);
32.177 + }
32.178 +}
32.179 +
32.180 +void
32.181 +GeneralMessage::PrintAttribute (std::ostream &os) const
32.182 +{
32.183 + for (uint32_t i = 0; i < m_attributes.size (); i ++)
32.184 + {
32.185 + os << " ----Attribute (" << i << "):";
32.186 + m_attributes[i].Print(os);
32.187 + }
32.188 +}
32.189 +
32.190 +/***********************************************************************************
32.191 +* \ InterfaceInfoMessage
32.192 +***********************************************************************************/
32.193 +InterfaceInfoMessage::InterfaceInfoMessage ()
32.194 +: m_reserved (0),
32.195 + m_deviceType (0),
32.196 + m_interfaceIndex(0),
32.197 + m_deviceFlags (0),
32.198 + m_changeMask (0)
32.199 +{
32.200 + memset((void*)m_attributeTypes, 0, sizeof(m_attributeTypes));
32.201 + m_attributeTypes[IFL_A_UNSPEC] = UNSPEC;
32.202 + m_attributeTypes[IFL_A_ADDRESS] = ADDRESS;
32.203 + m_attributeTypes[IFL_A_BROADCAST] = ADDRESS;
32.204 + m_attributeTypes[IFL_A_IFNAME] = STRING;
32.205 + m_attributeTypes[IFL_A_MTU] = U32;
32.206 + m_attributeTypes[IFL_A_LINK] = U32;
32.207 + m_attributeTypes[IFL_A_QDISC] = U8;
32.208 + m_attributeTypes[IFL_A_STATS] = UNSPEC;
32.209 + m_attributeTypes[IFL_A_COST] = UNSPEC;
32.210 +}
32.211 +InterfaceInfoMessage::~InterfaceInfoMessage()
32.212 +{}
32.213 +void
32.214 +InterfaceInfoMessage::SetDeviceType (uint16_t type)
32.215 +{
32.216 + m_deviceType = type;
32.217 +}
32.218 +void
32.219 +InterfaceInfoMessage::SetInterfaceIndex (int32_t index)
32.220 +{
32.221 + m_interfaceIndex = index;
32.222 +}
32.223 +void
32.224 +InterfaceInfoMessage::SetDeviceFlags (uint32_t flags)
32.225 +{
32.226 + m_deviceFlags = flags;
32.227 +}
32.228 +void
32.229 +InterfaceInfoMessage::SetChangeMask (uint32_t mask)
32.230 +{
32.231 + m_changeMask = mask;
32.232 +}
32.233 +uint16_t
32.234 +InterfaceInfoMessage::GetDeviceType (void) const
32.235 +{
32.236 + return m_deviceType;
32.237 +}
32.238 +int32_t
32.239 +InterfaceInfoMessage::GetInterfaceIndex (void) const
32.240 +{
32.241 + return m_interfaceIndex;
32.242 +}
32.243 +uint32_t
32.244 +InterfaceInfoMessage::GetDeviceFlags (void) const
32.245 +{
32.246 + return m_deviceFlags;
32.247 +}
32.248 +uint32_t
32.249 +InterfaceInfoMessage::GetChangeMask (void) const
32.250 +{
32.251 + return m_changeMask;
32.252 +}
32.253 +TypeId
32.254 +InterfaceInfoMessage::GetTypeId (void)
32.255 +{
32.256 + static TypeId tid = TypeId ("ns3::InterfaceInfoMessage")
32.257 + .SetParent<GeneralMessage> ()
32.258 + .AddConstructor<InterfaceInfoMessage> ()
32.259 + ;
32.260 + return tid;
32.261 +}
32.262 +TypeId
32.263 +InterfaceInfoMessage::GetInstanceTypeId (void) const
32.264 +{
32.265 + return GetTypeId ();
32.266 +}
32.267 +void
32.268 +InterfaceInfoMessage::Print (std::ostream &os) const
32.269 +{
32.270 + os << " ----InterfaceInfoMessage ("
32.271 + << "deviceType: " << m_deviceType << " "
32.272 + << "interfaceIndex: " << m_interfaceIndex << " "
32.273 + << "deviceFlags: " << m_deviceFlags << " "
32.274 + << "changeMask: " << m_changeMask << ")" ;
32.275 + PrintAttribute(os);
32.276 +}
32.277 +uint32_t
32.278 +InterfaceInfoMessage::GetSerializedSize (void) const
32.279 +{
32.280 + return NETLINK_INTERFACE_SIZE + GetAttributeSerializedSize();
32.281 +}
32.282 +
32.283 +void
32.284 +InterfaceInfoMessage::Serialize (Buffer::Iterator& start) const
32.285 +{
32.286 + start.WriteU8 (m_family);
32.287 + start.WriteU8 (m_reserved);
32.288 + start.WriteU16 (m_deviceType);
32.289 + start.WriteU32 (m_interfaceIndex);
32.290 + start.WriteU32 (m_deviceFlags);
32.291 + start.WriteU32 (m_changeMask);
32.292 +
32.293 + SerializeAttribute(start);
32.294 +}
32.295 +uint32_t
32.296 +InterfaceInfoMessage::Deserialize (Buffer::Iterator& start, uint32_t len)
32.297 +{
32.298 + m_family = start.ReadU8 ();
32.299 + m_reserved = start.ReadU8 ();
32.300 + m_deviceType = start.ReadU16 ();
32.301 + m_interfaceIndex = start.ReadU32 ();
32.302 + m_deviceFlags = start.ReadU32 ();
32.303 + m_changeMask = start.ReadU32 ();
32.304 +
32.305 + len -= NETLINK_INTERFACE_SIZE;
32.306 +
32.307 + while (len)
32.308 + {
32.309 + NetlinkAttribute attr;
32.310 +
32.311 + len -= attr.Deserialize (start, m_attributeTypes);
32.312 + m_attributes.push_back (attr);
32.313 + }
32.314 +
32.315 + return GetSerializedSize ();
32.316 +}
32.317 +
32.318 +
32.319 +
32.320 +/***********************************************************************************
32.321 +* \InterfaceAddressMessage
32.322 +***********************************************************************************/
32.323 +InterfaceAddressMessage::InterfaceAddressMessage ()
32.324 +: m_length (0),
32.325 + m_flags (0),
32.326 + m_scope (0),
32.327 + m_index(0)
32.328 +{
32.329 + memset((void*)m_attributeTypes, 0, sizeof(m_attributeTypes));
32.330 + m_attributeTypes[IF_A_UNSPEC] = UNSPEC;
32.331 + m_attributeTypes[IF_A_ADDRESS] = ADDRESS;
32.332 + m_attributeTypes[IF_A_LOCAL] = ADDRESS;
32.333 + m_attributeTypes[IF_A_LABEL] = STRING;
32.334 + m_attributeTypes[IF_A_BROADCAST] = ADDRESS;
32.335 + m_attributeTypes[IF_A_ANYCAST] = ADDRESS;
32.336 + m_attributeTypes[IF_A_CACHEINFO] = UNSPEC;
32.337 + m_attributeTypes[IF_A_MULTICAST] = ADDRESS;
32.338 +}
32.339 +InterfaceAddressMessage::~InterfaceAddressMessage()
32.340 +{
32.341 +}
32.342 +void
32.343 +InterfaceAddressMessage::SetFamily (uint8_t family)
32.344 +{
32.345 + m_family = family;
32.346 +}
32.347 +void
32.348 +InterfaceAddressMessage::SetLength (uint8_t length)
32.349 +{
32.350 + m_length = length;
32.351 +}
32.352 +void
32.353 +InterfaceAddressMessage::SetFlags (uint8_t flags)
32.354 +{
32.355 + m_flags = flags;
32.356 +}
32.357 +void
32.358 +InterfaceAddressMessage::SetScope (uint8_t scope)
32.359 +{
32.360 + m_scope = scope;
32.361 +}
32.362 +void
32.363 +InterfaceAddressMessage::SetInterfaceIndex (int32_t index)
32.364 +{
32.365 + m_index = index;
32.366 +}
32.367 +
32.368 +uint8_t
32.369 +InterfaceAddressMessage::GetFamily (void) const
32.370 +{
32.371 + return m_family;
32.372 +}
32.373 +uint8_t
32.374 +InterfaceAddressMessage::GetLength (void) const
32.375 +{
32.376 + return m_length;
32.377 +}
32.378 +uint8_t
32.379 +InterfaceAddressMessage::GetFlags (void) const
32.380 +{
32.381 + return m_flags;
32.382 +}
32.383 +uint8_t
32.384 +InterfaceAddressMessage::GetScope (void) const
32.385 +{
32.386 + return m_scope;
32.387 +}
32.388 +int32_t
32.389 +InterfaceAddressMessage::GetInterfaceIndex (void) const
32.390 +{
32.391 + return m_index;
32.392 +}
32.393 +
32.394 +TypeId
32.395 +InterfaceAddressMessage::GetTypeId (void)
32.396 +{
32.397 + static TypeId tid = TypeId ("ns3::InterfaceAddressMessage")
32.398 + .SetParent<GeneralMessage> ()
32.399 + .AddConstructor<InterfaceAddressMessage> ()
32.400 + ;
32.401 + return tid;
32.402 +}
32.403 +TypeId
32.404 +InterfaceAddressMessage::GetInstanceTypeId (void) const
32.405 +{
32.406 + return GetTypeId ();
32.407 +}
32.408 +void
32.409 +InterfaceAddressMessage::Print (std::ostream &os) const
32.410 +{
32.411 + os << " ----InterfaceAddressMessage ("
32.412 + << "family: " << (uint32_t)m_family << " "
32.413 + << "length: " << (uint32_t)m_length << " "
32.414 + << "flags: " << (uint32_t)m_flags << " "
32.415 + << "scope: " << (uint32_t)m_scope << " "
32.416 + << "index: " << m_index << ")";
32.417 + PrintAttribute(os);
32.418 +}
32.419 +uint32_t
32.420 +InterfaceAddressMessage::GetSerializedSize (void) const
32.421 +{
32.422 + return NETLINK_ADDRESS_SIZE + GetAttributeSerializedSize();
32.423 +}
32.424 +
32.425 +void
32.426 +InterfaceAddressMessage::Serialize (Buffer::Iterator& start) const
32.427 +{
32.428 + start.WriteU8 (m_family);
32.429 + start.WriteU8 (m_length);
32.430 + start.WriteU8 (m_flags);
32.431 + start.WriteU8 (m_scope);
32.432 + start.WriteU32 (m_index);
32.433 +
32.434 + SerializeAttribute(start);
32.435 +}
32.436 +
32.437 +uint32_t
32.438 +InterfaceAddressMessage::Deserialize (Buffer::Iterator& start, uint32_t len)
32.439 +{
32.440 + m_family = start.ReadU8 ();
32.441 + m_length = start.ReadU8 ();
32.442 + m_flags = start.ReadU8 ();
32.443 + m_scope = start.ReadU8 ();
32.444 + m_index = start.ReadU32 ();
32.445 +
32.446 + len -= NETLINK_ADDRESS_SIZE;
32.447 +
32.448 + while (len)
32.449 + {
32.450 + NetlinkAttribute attr;
32.451 +
32.452 + len -= attr.Deserialize (start, m_attributeTypes);
32.453 + m_attributes.push_back (attr);
32.454 + }
32.455 +
32.456 + return GetSerializedSize ();
32.457 +}
32.458 +
32.459 +
32.460 +
32.461 +/***********************************************************************************
32.462 +* \ RouteMessage
32.463 +***********************************************************************************/
32.464 +RouteMessage::RouteMessage ()
32.465 +: m_dstLen (0),
32.466 + m_srcLen (0),
32.467 + m_tos (0),
32.468 + m_tableId (0),
32.469 + m_protocol(0),
32.470 + m_scope (0),
32.471 + m_type (0),
32.472 + m_flags (0)
32.473 +{
32.474 + memset((void*)m_attributeTypes, 0, sizeof(m_attributeTypes));
32.475 + m_attributeTypes[RT_A_UNSPEC] = UNSPEC;
32.476 + m_attributeTypes[RT_A_DST] = ADDRESS;
32.477 + m_attributeTypes[RT_A_SRC] = ADDRESS;
32.478 + m_attributeTypes[RT_A_IIF] = U32;
32.479 + m_attributeTypes[RT_A_OIF] = U32;
32.480 + m_attributeTypes[RT_A_GATEWAY] = ADDRESS;
32.481 + m_attributeTypes[RT_A_PRIORITY] = U8;
32.482 + m_attributeTypes[RT_A_PREFSRC] = ADDRESS;
32.483 + m_attributeTypes[RT_A_METRICS] = UNSPEC;
32.484 + //others default value UNSPEC
32.485 +}
32.486 +RouteMessage::~RouteMessage ()
32.487 +{}
32.488 +
32.489 +void
32.490 +RouteMessage::SetFamily (uint8_t v)
32.491 +{
32.492 + m_family = v;
32.493 +}
32.494 +void
32.495 +RouteMessage::SetDstLength (uint8_t v)
32.496 +{
32.497 + m_dstLen = v;
32.498 +}
32.499 +void
32.500 +RouteMessage::SetSrcLength (uint8_t v)
32.501 +{
32.502 + m_srcLen = v;
32.503 +}
32.504 +void
32.505 +RouteMessage::SetTos (uint8_t v)
32.506 +{
32.507 + m_tos = v;
32.508 +}
32.509 +void
32.510 +RouteMessage::SetTableId (uint8_t v)
32.511 +{
32.512 + m_tableId = v;
32.513 +}
32.514 +void
32.515 +RouteMessage::SetProtocol (uint8_t v)
32.516 +{
32.517 + m_protocol = v;
32.518 +}
32.519 +void
32.520 +RouteMessage::SetScope (uint8_t v)
32.521 +{
32.522 + m_scope = v;
32.523 +}
32.524 +void
32.525 +RouteMessage::SetType (uint8_t v)
32.526 +{
32.527 + m_type = v;
32.528 +}
32.529 +void
32.530 +RouteMessage::SetFlags (uint32_t v)
32.531 +{
32.532 + m_flags = v;
32.533 +}
32.534 +uint8_t
32.535 +RouteMessage::GetFamily (void) const
32.536 +{
32.537 + return m_family;
32.538 +}
32.539 +uint8_t
32.540 +RouteMessage::GetDstLength (void) const
32.541 +{
32.542 + return m_dstLen;
32.543 +}
32.544 +uint8_t
32.545 +RouteMessage::GetSrcLength (void) const
32.546 +{
32.547 + return m_srcLen;
32.548 +}
32.549 +uint8_t
32.550 +RouteMessage::GetTos (void) const
32.551 +{
32.552 + return m_tos;
32.553 +}
32.554 +uint8_t
32.555 +RouteMessage::GetTableId (void) const
32.556 +{
32.557 + return m_tableId;
32.558 +}
32.559 +uint8_t
32.560 +RouteMessage::GetProtocol(void) const
32.561 +{
32.562 + return m_protocol;
32.563 +}
32.564 +uint8_t
32.565 +RouteMessage::GetType (void) const
32.566 +{
32.567 + return m_type;
32.568 +}
32.569 +uint8_t
32.570 +RouteMessage::GetScope (void) const
32.571 +{
32.572 + return m_scope;
32.573 +}
32.574 +uint32_t
32.575 +RouteMessage::GetFlags (void) const
32.576 +{
32.577 + return m_flags;
32.578 +}
32.579 +
32.580 +TypeId
32.581 +RouteMessage::GetTypeId (void)
32.582 +{
32.583 + static TypeId tid = TypeId ("ns3::RouteMessage")
32.584 + .SetParent<GeneralMessage> ()
32.585 + .AddConstructor<RouteMessage> ()
32.586 + ;
32.587 + return tid;
32.588 +}
32.589 +TypeId
32.590 +RouteMessage::GetInstanceTypeId (void) const
32.591 +{
32.592 + return GetTypeId ();
32.593 +}
32.594 +void
32.595 +RouteMessage::Print (std::ostream &os) const
32.596 +{
32.597 + os << " ----RouteMessage ("
32.598 + << "family: " << (uint32_t)m_family << " "
32.599 + << "dstLen: " << (uint32_t)m_dstLen << " "
32.600 + << "srcLen: " << (uint32_t)m_srcLen << " "
32.601 + << "tos: " << (uint32_t)m_tos << " "
32.602 + << "tableId: " << (uint32_t)m_tableId << " "
32.603 + << "protocol: " << (uint32_t)m_protocol << " "
32.604 + << "scope: " << (uint32_t)m_scope << " "
32.605 + << "type: " << (uint32_t)m_type << " "
32.606 + << "flags: " << m_flags<< ")" ;
32.607 + PrintAttribute(os);
32.608 +}
32.609 +uint32_t
32.610 +RouteMessage::GetSerializedSize (void) const
32.611 +{
32.612 + return NETLINK_ROUTE_SIZE + GetAttributeSerializedSize();
32.613 +}
32.614 +
32.615 +void
32.616 +RouteMessage::Serialize (Buffer::Iterator& start) const
32.617 +{
32.618 + start.WriteU8 (m_family);
32.619 + start.WriteU8 (m_dstLen);
32.620 + start.WriteU8 (m_srcLen);
32.621 + start.WriteU8 (m_tos);
32.622 + start.WriteU8 (m_tableId);
32.623 + start.WriteU8 (m_protocol);
32.624 + start.WriteU8 (m_scope);
32.625 + start.WriteU8 (m_type);
32.626 + start.WriteU32 (m_flags);
32.627 +
32.628 + SerializeAttribute(start);
32.629 +}
32.630 +uint32_t
32.631 +RouteMessage::Deserialize (Buffer::Iterator& start, uint32_t len)
32.632 +{
32.633 + m_family = start.ReadU8 ();
32.634 + m_dstLen = start.ReadU8 ();
32.635 + m_srcLen = start.ReadU8 ();
32.636 + m_tos = start.ReadU8 ();
32.637 + m_tableId = start.ReadU8 ();
32.638 + m_protocol = start.ReadU8 ();
32.639 + m_scope = start.ReadU8 ();
32.640 + m_type = start.ReadU8 ();
32.641 + m_flags = start.ReadU32 ();
32.642 +
32.643 + len -= NETLINK_ROUTE_SIZE;
32.644 +
32.645 + while (len)
32.646 + {
32.647 + NetlinkAttribute attr;
32.648 +
32.649 + len -= attr.Deserialize (start, m_attributeTypes);
32.650 + m_attributes.push_back (attr);
32.651 + }
32.652 +
32.653 + return GetSerializedSize ();
32.654 +}
32.655 +}; // namespace ns3
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/src/node/netlink-message-route.h Thu Oct 01 23:37:18 2009 +0900
33.3 @@ -0,0 +1,398 @@
33.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
33.5 +/*
33.6 +* Copyright (c) 2008 Liu Jian
33.7 +*
33.8 +* This program is free software; you can redistribute it and/or modify
33.9 +* it under the terms of the GNU General Public License version 2 as
33.10 +* published by the Free Software Foundation;
33.11 +*
33.12 +* This program is distributed in the hope that it will be useful,
33.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
33.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33.15 +* GNU General Public License for more details.
33.16 +*
33.17 +* You should have received a copy of the GNU General Public License
33.18 +* along with this program; if not, write to the Free Software
33.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33.20 +*
33.21 +* Author: Liu Jian <liujatp@gmail.com>
33.22 +*/
33.23 +
33.24 +#ifndef NETLINK_MESSAGE_ROUTE_H
33.25 +#define NETLINK_MESSAGE_ROUTE_H
33.26 +
33.27 +#include "ns3/object-base.h"
33.28 +#include "ns3/address.h"
33.29 +#include "ns3/netlink-attribute.h"
33.30 +#include <string>
33.31 +
33.32 +namespace ns3 {
33.33 +
33.34 +/*
33.35 +* this file define some netlink message of NETLINK_ROUTE protocol,
33.36 +* there are mainly three types:interface address, interface info, route entry
33.37 +* just implemented them for quagga porting.
33.38 +*/
33.39 +
33.40 +
33.41 +
33.42 +/**
33.43 +* \Types of messages,here we only define the route message types quagga used
33.44 +*/
33.45 +enum NetlinkRtmType_e
33.46 +{
33.47 + NETLINK_RTM_BASE = 16,
33.48 +
33.49 + NETLINK_RTM_NEWLINK = 16,
33.50 + NETLINK_RTM_DELLINK,
33.51 + NETLINK_RTM_GETLINK,
33.52 + NETLINK_RTM_SETLINK,
33.53 +
33.54 + NETLINK_RTM_NEWADDR = 20,
33.55 + NETLINK_RTM_DELADDR,
33.56 + NETLINK_RTM_GETADDR,
33.57 +
33.58 + NETLINK_RTM_NEWROUTE = 24,
33.59 + NETLINK_RTM_DELROUTE,
33.60 + NETLINK_RTM_GETROUTE,
33.61 +
33.62 + NETLINK_RTM_MAX,
33.63 +};
33.64 +
33.65 +/**
33.66 +* \Types of netlink groups,here we only define types quagga used
33.67 +*/
33.68 +enum NetlinkRtmGroup_e
33.69 +{
33.70 + NETLINK_RTM_GRP_LINK = 1,
33.71 + NETLINK_RTM_GRP_IPV4_IFADDR = 0x10,
33.72 + NETLINK_RTM_GRP_IPV4_ROUTE = 0x40,
33.73 + RTMGRP_IPV6_IFADDR = 0x100,
33.74 + RTMGRP_IPV6_ROUTE = 0x400,
33.75 +};
33.76 +
33.77 +class NetlinkPayload :public ObjectBase
33.78 +{
33.79 +public:
33.80 + static TypeId GetTypeId (void);
33.81 + virtual TypeId GetInstanceTypeId (void) const = 0;
33.82 + virtual void Serialize (Buffer::Iterator& start) const = 0;
33.83 + virtual void Print (std::ostream &os) const = 0;
33.84 + virtual uint32_t GetSerializedSize (void) const = 0;
33.85 +};
33.86 +
33.87 +/***
33.88 +* General form of address family dependent message.
33.89 +**
33.90 + struct rtgenmsg
33.91 + {
33.92 + unsigned char rtgen_family;
33.93 + };
33.94 +**/
33.95 +
33.96 +class GeneralMessage : public NetlinkPayload
33.97 +{
33.98 +public:
33.99 + GeneralMessage ();
33.100 + virtual ~GeneralMessage();
33.101 +
33.102 + static TypeId GetTypeId (void);
33.103 + virtual TypeId GetInstanceTypeId (void) const;
33.104 + virtual void Serialize (Buffer::Iterator& start) const;
33.105 + virtual uint32_t Deserialize (Buffer::Iterator& start);
33.106 + virtual uint32_t Deserialize (Buffer::Iterator& start, uint32_t len);
33.107 + virtual void Print (std::ostream &os) const;
33.108 + virtual uint32_t GetSerializedSize (void) const;
33.109 +
33.110 +
33.111 + virtual uint32_t GetNNetlinkAttribute(void)const;
33.112 + virtual NetlinkAttribute GetNetlinkAttribute(uint32_t index)const;
33.113 + virtual void AppendAttribute (NetlinkAttribute v);
33.114 + virtual void SerializeAttribute (Buffer::Iterator& start) const;
33.115 + virtual void PrintAttribute (std::ostream &os) const;
33.116 + virtual uint32_t GetAttributeSerializedSize (void) const;
33.117 + virtual bool GetAttributeByType(NetlinkAttribute& attr, uint16_t type);
33.118 +
33.119 +
33.120 + void SetFamily(uint8_t v);
33.121 + uint8_t GetFamily(void) const;
33.122 +
33.123 +private:
33.124 + static const int NETLINK_GENMSG_SIZE = 1; /* size of the struct rtgenmsg */
33.125 +protected:
33.126 + uint8_t m_family; //always set to AF_UNSPEC
33.127 + //attribute can exist or not
33.128 + std::vector<NetlinkAttribute> m_attributes;
33.129 +};
33.130 +
33.131 +
33.132 +
33.133 +/**
33.134 +* \brief Link layer specific messages
33.135 +*
33.136 +* struct ifinfomsg
33.137 +* passes link level specific information, not dependent
33.138 +* on network protocol.
33.139 +*
33.140 + struct ifinfomsg
33.141 + {
33.142 + unsigned char ifi_family;
33.143 + unsigned char __ifi_pad;
33.144 + unsigned short ifi_type;
33.145 + int ifi_index;
33.146 + unsigned ifi_flags;
33.147 + unsigned ifi_change;
33.148 + };
33.149 +*/
33.150 +class InterfaceInfoMessage : public GeneralMessage
33.151 +{
33.152 +public:
33.153 + InterfaceInfoMessage ();
33.154 + virtual ~InterfaceInfoMessage();
33.155 +
33.156 + static TypeId GetTypeId (void);
33.157 + virtual TypeId GetInstanceTypeId (void) const;
33.158 + virtual void Serialize (Buffer::Iterator& start) const;
33.159 + virtual uint32_t Deserialize (Buffer::Iterator& start, uint32_t len);
33.160 + virtual void Print (std::ostream &os) const;
33.161 + virtual uint32_t GetSerializedSize (void) const;
33.162 +
33.163 + enum IflAttr_e
33.164 + {
33.165 + IFL_A_UNSPEC,
33.166 + IFL_A_ADDRESS,
33.167 + IFL_A_BROADCAST,
33.168 + IFL_A_IFNAME,
33.169 + IFL_A_MTU,
33.170 + IFL_A_LINK,
33.171 + IFL_A_QDISC,
33.172 + IFL_A_STATS,
33.173 + IFL_A_COST,
33.174 + IFL_A_PRIORITY,
33.175 + IFL_A_MASTER,
33.176 + IFL_A_WIRELESS,
33.177 + IFL_A_PROTINFO,
33.178 + IFL_A_TXQLEN,
33.179 + IFL_A_MAP,
33.180 + IFL_A_WEIGHT,
33.181 + IFL_A_OPERSTATE,
33.182 + IFL_A_LINKMODE,
33.183 + IFL_A_MAX,
33.184 + };
33.185 +
33.186 + enum Type_e{
33.187 + UP = 1,
33.188 + BROADCAST = 2,
33.189 + DBG = 4,
33.190 + };
33.191 +
33.192 + void SetDeviceType (uint16_t type);
33.193 + void SetInterfaceIndex (int32_t index);
33.194 + void SetDeviceFlags (uint32_t index);
33.195 + void SetChangeMask (uint32_t mask);
33.196 +
33.197 + uint16_t GetDeviceType (void) const;
33.198 + int32_t GetInterfaceIndex (void) const;
33.199 + uint32_t GetDeviceFlags (void) const;
33.200 + uint32_t GetChangeMask (void) const;
33.201 +private:
33.202 + static const int NETLINK_INTERFACE_SIZE = 16; /* size of the struct ifinfomsg */
33.203 + uint8_t m_reserved; //not used
33.204 + uint16_t m_deviceType;
33.205 + int32_t m_interfaceIndex;
33.206 + uint32_t m_deviceFlags;
33.207 + uint32_t m_changeMask;
33.208 + NetlinkAttributeValueType m_attributeTypes[IFL_A_MAX];
33.209 +};
33.210 +
33.211 +
33.212 +
33.213 +
33.214 +/**
33.215 +* \brief Interface address.
33.216 +*
33.217 + struct ifaddrmsg
33.218 + {
33.219 + unsigned char ifa_family;
33.220 + unsigned char ifa_prefixlen;
33.221 + unsigned char ifa_flags;
33.222 + unsigned char ifa_scope;
33.223 + int ifa_index;
33.224 + };
33.225 +*/
33.226 +
33.227 +class InterfaceAddressMessage : public GeneralMessage
33.228 +{
33.229 +public:
33.230 + InterfaceAddressMessage ();
33.231 + virtual ~InterfaceAddressMessage();
33.232 +
33.233 + static TypeId GetTypeId (void);
33.234 + virtual TypeId GetInstanceTypeId (void) const;
33.235 + virtual void Serialize (Buffer::Iterator& start) const;
33.236 + virtual uint32_t Deserialize (Buffer::Iterator& start, uint32_t len);
33.237 + virtual void Print (std::ostream &os) const;
33.238 + virtual uint32_t GetSerializedSize (void) const;
33.239 +
33.240 + enum IfAttr_e
33.241 + {
33.242 + IF_A_UNSPEC,
33.243 + IF_A_ADDRESS,
33.244 + IF_A_LOCAL,
33.245 + IF_A_LABEL,
33.246 + IF_A_BROADCAST,
33.247 + IF_A_ANYCAST,
33.248 + IF_A_CACHEINFO,
33.249 + IF_A_MULTICAST,
33.250 + IF_A_MAX
33.251 + };
33.252 +
33.253 + enum {
33.254 + F_SECONDARY = 0x01,
33.255 + F_PERMANENT = 0x80,
33.256 + F_DEPRECATED = 0x20,
33.257 + F_TENTATIVE = 0x40
33.258 + };
33.259 + enum {
33.260 + SCOPE_UNIVERSE = 0,
33.261 + SCOPE_SITE = 200,
33.262 + SCOPE_LINK = 253,
33.263 + SCOPE_HOST = 254
33.264 + };
33.265 +
33.266 +
33.267 + void SetFamily (uint8_t family);
33.268 + void SetLength (uint8_t length);
33.269 + void SetFlags (uint8_t flags);
33.270 + void SetScope (uint8_t scope);
33.271 + void SetInterfaceIndex (int32_t index);
33.272 +
33.273 + uint8_t GetFamily (void) const;
33.274 + uint8_t GetLength (void) const;
33.275 + uint8_t GetFlags (void) const;
33.276 + uint8_t GetScope (void) const;
33.277 + int32_t GetInterfaceIndex (void) const;
33.278 +
33.279 +private:
33.280 + static const int NETLINK_ADDRESS_SIZE = 8; /* size of the struct ifaddrmsg */
33.281 + uint8_t m_length;
33.282 + uint8_t m_flags;
33.283 + uint8_t m_scope;
33.284 + int32_t m_index;
33.285 + NetlinkAttributeValueType m_attributeTypes[IF_A_MAX];
33.286 +};
33.287 +
33.288 +
33.289 +
33.290 +
33.291 +/**
33.292 +* \brief Definitions used in routing table administration.
33.293 +*
33.294 + struct rtmsg
33.295 + {
33.296 + unsigned char rtm_family;
33.297 + unsigned char rtm_dst_len;
33.298 + unsigned char rtm_src_len;
33.299 + unsigned char rtm_tos;
33.300 +
33.301 + unsigned char rtm_table; // Routing table id
33.302 + unsigned char rtm_protocol; //Routing protocol;
33.303 + unsigned char rtm_scope;
33.304 + unsigned char rtm_type;
33.305 +
33.306 + unsigned rtm_flags;
33.307 + };
33.308 +*/
33.309 +
33.310 +class RouteMessage : public GeneralMessage
33.311 +{
33.312 +public:
33.313 + RouteMessage ();
33.314 + virtual ~RouteMessage ();
33.315 +
33.316 + static TypeId GetTypeId (void);
33.317 + virtual TypeId GetInstanceTypeId (void) const;
33.318 + virtual void Serialize (Buffer::Iterator& start) const;
33.319 + virtual uint32_t Deserialize (Buffer::Iterator& start, uint32_t len);
33.320 + virtual void Print (std::ostream &os) const;
33.321 + virtual uint32_t GetSerializedSize (void) const;
33.322 +
33.323 + uint8_t GetFamily (void) const;
33.324 + uint8_t GetDstLength (void) const;
33.325 + uint8_t GetSrcLength (void) const;
33.326 + uint8_t GetTos (void) const;
33.327 + uint8_t GetTableId (void) const;
33.328 + uint8_t GetProtocol(void) const;
33.329 + uint8_t GetType (void) const;
33.330 + uint8_t GetScope (void) const;
33.331 + uint32_t GetFlags (void) const;
33.332 + void SetFamily (uint8_t v);
33.333 + void SetDstLength (uint8_t v);
33.334 + void SetSrcLength (uint8_t v);
33.335 + void SetTos (uint8_t v);
33.336 + void SetTableId (uint8_t v);
33.337 + void SetProtocol (uint8_t v);
33.338 + void SetScope (uint8_t v);
33.339 + void SetType (uint8_t v);
33.340 + void SetFlags (uint32_t v);
33.341 +
33.342 + enum RtProtocol_e
33.343 + {
33.344 + RT_PROT_UNSPEC = 0,
33.345 + };
33.346 +
33.347 + enum RtFlags_e
33.348 + {
33.349 + RT_F_CLONED = 0x200,
33.350 + };
33.351 +
33.352 + enum RtScope_e
33.353 + {
33.354 + RT_SCOPE_UNIVERSE=0,
33.355 + RT_SCOPE_LINK = 253,
33.356 + };
33.357 +
33.358 + enum RtClass_e
33.359 + {
33.360 + RT_TABLE_UNSPEC = 0,
33.361 + RT_TABLE_MAIN = 254,
33.362 + };
33.363 +
33.364 + enum RtAttr_e
33.365 + {
33.366 + RT_A_UNSPEC,
33.367 + RT_A_DST,
33.368 + RT_A_SRC,
33.369 + RT_A_IIF,
33.370 + RT_A_OIF,
33.371 + RT_A_GATEWAY,
33.372 + RT_A_PRIORITY,
33.373 + RT_A_PREFSRC,
33.374 + RT_A_METRICS,
33.375 + RT_A_MULTIPATH,
33.376 + RT_A_PROTOINFO,
33.377 + RT_A_FLOW,
33.378 + RT_A_CACHEINFO,
33.379 + RT_A_SESSION,
33.380 + RT_A_MP_ALGO,
33.381 + RT_A_TABLE,
33.382 + RT_A_MAX
33.383 + };
33.384 +
33.385 +
33.386 +private:
33.387 + static const int NETLINK_ROUTE_SIZE = 12; /* size of the struct rtmsg */
33.388 + uint8_t m_dstLen;
33.389 + uint8_t m_srcLen;
33.390 + uint8_t m_tos;
33.391 + uint8_t m_tableId;
33.392 + uint8_t m_protocol;
33.393 + uint8_t m_scope;
33.394 + uint8_t m_type;
33.395 + uint32_t m_flags;
33.396 + NetlinkAttributeValueType m_attributeTypes[RT_A_MAX];
33.397 +};
33.398 +
33.399 +}; // namespace ns3
33.400 +
33.401 +#endif /* NETLINK_MESSAGE_ROUTE_H */
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/src/node/netlink-message.cc Thu Oct 01 23:37:18 2009 +0900
34.3 @@ -0,0 +1,658 @@
34.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
34.5 +/*
34.6 +* Copyright (c) 2008 Liu Jian
34.7 +*
34.8 +* This program is free software; you can redistribute it and/or modify
34.9 +* it under the terms of the GNU General Public License version 2 as
34.10 +* published by the Free Software Foundation;
34.11 +*
34.12 +* This program is distributed in the hope that it will be useful,
34.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
34.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34.15 +* GNU General Public License for more details.
34.16 +*
34.17 +* You should have received a copy of the GNU General Public License
34.18 +* along with this program; if not, write to the Free Software
34.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34.20 +*
34.21 +* Author: Liu Jian <liujatp@gmail.com>
34.22 +*/
34.23 +
34.24 +#include "ns3/netlink-message.h"
34.25 +#include "ns3/address-utils.h"
34.26 +#include "ns3/log.h"
34.27 +
34.28 +NS_LOG_COMPONENT_DEFINE ("NetlinkMessage");
34.29 +namespace ns3 {
34.30 +
34.31 +/***********************************************************************************
34.32 +* \ NetlinkMessageHeader
34.33 +***********************************************************************************/
34.34 +NS_OBJECT_ENSURE_REGISTERED (NetlinkMessageHeader);
34.35 +NS_OBJECT_ENSURE_REGISTERED (NetlinkMessage);
34.36 +
34.37 +NetlinkMessageHeader::NetlinkMessageHeader ()
34.38 +: m_nlmsgLen (16),
34.39 + m_nlmsgType (0),
34.40 + m_nlmsgFlags (0),
34.41 + m_nlmsgSeq (0),
34.42 + m_nlmsgPid (0)
34.43 +{}
34.44 +
34.45 +NetlinkMessageHeader::NetlinkMessageHeader (uint16_t type, uint16_t flags, uint32_t seq, uint32_t pid)
34.46 +: m_nlmsgLen (16),
34.47 + m_nlmsgType (type),
34.48 + m_nlmsgFlags (flags),
34.49 + m_nlmsgSeq (seq),
34.50 + m_nlmsgPid (pid)
34.51 +{}
34.52 +
34.53 +void
34.54 +NetlinkMessageHeader::SetMsgLen (uint32_t v)
34.55 +{
34.56 + m_nlmsgLen = v;
34.57 +}
34.58 +void
34.59 +NetlinkMessageHeader::SetMsgFlags (uint16_t v)
34.60 +{
34.61 + m_nlmsgFlags = v;
34.62 +}
34.63 +void
34.64 +NetlinkMessageHeader::SetMsgType (uint16_t v)
34.65 +{
34.66 + m_nlmsgType = v;
34.67 +}
34.68 +void
34.69 +NetlinkMessageHeader::SetMsgSeq (uint32_t v)
34.70 +{
34.71 + m_nlmsgSeq = v;
34.72 +}
34.73 +void
34.74 +NetlinkMessageHeader::SetMsgPid (uint32_t v)
34.75 +{
34.76 + m_nlmsgPid = v;
34.77 +}
34.78 +uint16_t
34.79 +NetlinkMessageHeader::GetMsgFlags (void) const
34.80 +{
34.81 + return m_nlmsgFlags;
34.82 +}
34.83 +uint32_t
34.84 +NetlinkMessageHeader::GetMsgLen (void) const
34.85 +{
34.86 + return m_nlmsgLen;
34.87 +}
34.88 +uint16_t
34.89 +NetlinkMessageHeader::GetMsgType (void) const
34.90 +{
34.91 + return m_nlmsgType;
34.92 +}
34.93 +uint32_t
34.94 +NetlinkMessageHeader::GetMsgSeq (void) const
34.95 +{
34.96 + return m_nlmsgSeq;
34.97 +}
34.98 +uint32_t
34.99 +NetlinkMessageHeader::GetMsgPid (void) const
34.100 +{
34.101 + return m_nlmsgPid;
34.102 +}
34.103 +uint32_t
34.104 +NetlinkMessageHeader::GetHeaderSize ()
34.105 +{
34.106 + return NETLINK_MSG_HEADER_SIZE;
34.107 +}
34.108 +uint32_t
34.109 +NetlinkMessageHeader::GetPayloadSize (void) const
34.110 +{
34.111 + return NETLINK_MSG_ALIGN(m_nlmsgLen - NETLINK_MSG_HEADER_SIZE);
34.112 +}
34.113 +
34.114 +TypeId
34.115 +NetlinkMessageHeader::GetTypeId (void)
34.116 +{
34.117 + static TypeId tid = TypeId ("ns3::NetlinkMessageHeader")
34.118 + .SetParent<Header> ()
34.119 + .AddConstructor<NetlinkMessageHeader> ()
34.120 + ;
34.121 + return tid;
34.122 +}
34.123 +TypeId
34.124 +NetlinkMessageHeader::GetInstanceTypeId (void) const
34.125 +{
34.126 + return GetTypeId ();
34.127 +}
34.128 +void
34.129 +NetlinkMessageHeader::Print (std::ostream &os) const
34.130 +{
34.131 + os << "NetlinkMessageHeader "
34.132 + << "len: " << m_nlmsgLen << " "
34.133 + << "flags: " << m_nlmsgFlags << " "
34.134 + << "type: " << m_nlmsgType << " "
34.135 + << "seq: " << m_nlmsgSeq << " "
34.136 + << "pid: " << m_nlmsgPid;
34.137 +}
34.138 +
34.139 +uint32_t
34.140 +NetlinkMessageHeader::GetSerializedSize (void) const
34.141 +{
34.142 + /* this is the size of an nlmsghdr payload. */
34.143 + return NETLINK_MSG_HEADER_SIZE;
34.144 +}
34.145 +
34.146 +void
34.147 +NetlinkMessageHeader::Serialize (Buffer::Iterator& start) const
34.148 +{
34.149 + start.WriteU32 (m_nlmsgLen);
34.150 + start.WriteU16 (m_nlmsgType);
34.151 + start.WriteU16 (m_nlmsgFlags);
34.152 + start.WriteU32 (m_nlmsgSeq);
34.153 + start.WriteU32 (m_nlmsgPid);
34.154 +}
34.155 +
34.156 +uint32_t
34.157 +NetlinkMessageHeader::Deserialize (Buffer::Iterator& start)
34.158 +{
34.159 + m_nlmsgLen = start.ReadU32 ();
34.160 + m_nlmsgType = start.ReadU16 ();
34.161 + m_nlmsgFlags = start.ReadU16 ();
34.162 + m_nlmsgSeq = start.ReadU32 ();
34.163 + m_nlmsgPid = start.ReadU32 ();
34.164 +
34.165 + return GetSerializedSize ();
34.166 +}
34.167 +
34.168 +
34.169 +
34.170 +
34.171 +/***********************************************************************************
34.172 +* \ NetlinkMessageError
34.173 +***********************************************************************************/
34.174 +
34.175 +NetlinkMessageError::NetlinkMessageError ()
34.176 +: m_error (0)
34.177 +{
34.178 +}
34.179 +NetlinkMessageError::~NetlinkMessageError()
34.180 +{}
34.181 +void
34.182 +NetlinkMessageError::SetError (int32_t v)
34.183 +{
34.184 + m_error = v;
34.185 +}
34.186 +int32_t
34.187 +NetlinkMessageError::GetError (void) const
34.188 +{
34.189 + return m_error;
34.190 +}
34.191 +void
34.192 +NetlinkMessageError::SetMsg (NetlinkMessageHeader v)
34.193 +{
34.194 + m_msg = v;
34.195 +}
34.196 +NetlinkMessageHeader
34.197 +NetlinkMessageError::GetMsg (void) const
34.198 +{
34.199 + return m_msg;
34.200 +}
34.201 +
34.202 +TypeId
34.203 +NetlinkMessageError::GetTypeId (void)
34.204 +{
34.205 + static TypeId tid = TypeId ("ns3::NetlinkMessageError")
34.206 + .SetParent<NetlinkPayload> ()
34.207 + .AddConstructor<NetlinkMessageError> ()
34.208 + ;
34.209 + return tid;
34.210 +}
34.211 +
34.212 +TypeId
34.213 +NetlinkMessageError::GetInstanceTypeId (void) const
34.214 +{
34.215 + return GetTypeId ();
34.216 +}
34.217 +void
34.218 +NetlinkMessageError::Print (std::ostream &os) const
34.219 +{
34.220 + os << "----NetlinkMessageError "
34.221 + << "error: " << m_error << " "
34.222 + << "msg:( ";
34.223 + m_msg.Print(os);
34.224 + os << " )";
34.225 +}
34.226 +
34.227 +uint32_t
34.228 +NetlinkMessageError::GetSerializedSize (void) const
34.229 +{
34.230 + /* this is the size of an nlmsgerr payload. */
34.231 + return NETLINK_MSG_ERROR_SIZE;
34.232 +}
34.233 +
34.234 +void
34.235 +NetlinkMessageError::Serialize (Buffer::Iterator& start) const
34.236 +{
34.237 + start.WriteU32 (m_error);
34.238 + m_msg.Serialize (start);
34.239 +}
34.240 +
34.241 +uint32_t
34.242 +NetlinkMessageError::Deserialize (Buffer::Iterator& start)
34.243 +{
34.244 + m_error = start.ReadU32 ();
34.245 + m_msg.Deserialize (start);
34.246 +
34.247 + return GetSerializedSize ();
34.248 +}
34.249 +
34.250 +
34.251 +
34.252 +
34.253 +/***********************************************************************************
34.254 +* \ NetlinkMessage
34.255 +***********************************************************************************/
34.256 +NetlinkMessage::NetlinkMessage ()
34.257 +{}
34.258 +
34.259 +void
34.260 +NetlinkMessage::SetHeader (NetlinkMessageHeader hdr)
34.261 +{
34.262 + m_hdr = hdr;
34.263 +}
34.264 +NetlinkMessageHeader
34.265 +NetlinkMessage::GetHeader(void)const
34.266 +{
34.267 + return m_hdr;
34.268 +}
34.269 +void
34.270 +NetlinkMessage::SetGeneralMessage (GeneralMessage genmsg)
34.271 +{
34.272 + m_genmsg = genmsg;
34.273 + m_hdr.SetMsgLen (m_hdr.GetSerializedSize () + genmsg.GetSerializedSize ());
34.274 +}
34.275 +void
34.276 +NetlinkMessage::SetErrorMessage(NetlinkMessageError errmsg)
34.277 +{
34.278 + m_errorMessage = errmsg;
34.279 + m_hdr.SetMsgLen(m_hdr.GetSerializedSize() + errmsg.GetSerializedSize());
34.280 +}
34.281 +// the type is one of RTM_NEWLINK,RTM_DELLINK,RTM_GETLINK
34.282 +void
34.283 +NetlinkMessage::SetInterfaceInfoMessage (InterfaceInfoMessage v)
34.284 +{
34.285 + m_hdr.SetMsgLen (m_hdr.GetSerializedSize () + v.GetSerializedSize ());
34.286 + m_interfaceTemplate = v;
34.287 +}
34.288 +// the type is one of RTM_NEWADDR,RTM_DELADDR,RTM_GETADDR
34.289 +void NetlinkMessage::SetInterfaceAddressMessage (InterfaceAddressMessage v)
34.290 +{
34.291 + m_hdr.SetMsgLen (m_hdr.GetSerializedSize () + v.GetSerializedSize ());
34.292 + m_addressTemplate = v;
34.293 +}
34.294 +// the type is one of RTM_NEWROUTE,RTM_DELROUTE,RTM_GETROUTE
34.295 +void NetlinkMessage::SetRouteMessage (RouteMessage v)
34.296 +{
34.297 + m_hdr.SetMsgLen (m_hdr.GetSerializedSize () + v.GetSerializedSize ());
34.298 + m_routeTemplate = v;
34.299 +}
34.300 +GeneralMessage
34.301 +NetlinkMessage::GetGeneralMessage (void) const
34.302 +{
34.303 + return m_genmsg;
34.304 +}
34.305 +NetlinkMessageError
34.306 +NetlinkMessage::GetErrorMessage (void) const
34.307 +{
34.308 + return m_errorMessage;
34.309 +}
34.310 +InterfaceInfoMessage
34.311 +NetlinkMessage::GetInterfaceInfoMessage (void) const
34.312 +{
34.313 + return m_interfaceTemplate;
34.314 +}
34.315 +InterfaceAddressMessage
34.316 +NetlinkMessage::GetInterfaceAddressMessage (void) const
34.317 +{
34.318 + return m_addressTemplate;
34.319 +}
34.320 +RouteMessage
34.321 +NetlinkMessage::GetRouteMessage (void) const
34.322 +{
34.323 + return m_routeTemplate;
34.324 +}
34.325 +bool
34.326 +NetlinkMessage::IsMessageNetlinkControl (uint16_t type)
34.327 +{
34.328 + return (type < NETLINK_RTM_BASE);
34.329 +}
34.330 +bool
34.331 +NetlinkMessage::IsMessageNetlinkRoute (uint16_t type)
34.332 +{
34.333 + return (type >= NETLINK_RTM_BASE && type < NETLINK_RTM_MAX);
34.334 +}
34.335 +bool
34.336 +NetlinkMessage::IsMessageAddress (uint16_t type)
34.337 +{
34.338 + return (type >= NETLINK_RTM_NEWADDR && type <= NETLINK_RTM_GETADDR);
34.339 +}
34.340 +bool
34.341 +NetlinkMessage::IsMessageInterface (uint16_t type)
34.342 +{
34.343 + return (type >= NETLINK_RTM_NEWLINK && type <= NETLINK_RTM_SETLINK);
34.344 +}
34.345 +bool
34.346 +NetlinkMessage::IsMessageRoute (uint16_t type)
34.347 +{
34.348 + return (type >= NETLINK_RTM_NEWROUTE && type <= NETLINK_RTM_GETROUTE);
34.349 +}
34.350 +bool
34.351 +NetlinkMessage::IsMessageTypeGet (uint16_t type)
34.352 +{
34.353 + return ((( type - NETLINK_RTM_BASE)&3) == 2);
34.354 +}
34.355 +bool
34.356 +NetlinkMessage::IsMessageFlagsAck (uint16_t flags)
34.357 +{
34.358 + return (flags & NETLINK_MSG_F_ACK) ? true : false;
34.359 +}
34.360 +bool
34.361 +NetlinkMessage::IsMessageFlagsRequest (uint16_t flags)
34.362 +{
34.363 + return (flags & NETLINK_MSG_F_REQUEST) ? true : false;
34.364 +}
34.365 +bool
34.366 +NetlinkMessage::IsMessageFlagsDump (uint16_t flags)
34.367 +{
34.368 + return (flags & NETLINK_MSG_F_DUMP) ? true : false;
34.369 +}
34.370 +
34.371 +NetlinkMessage::operator MultipartNetlinkMessage (void) const
34.372 +{
34.373 + MultipartNetlinkMessage multi_nlmsg;
34.374 + multi_nlmsg.AppendMessage(*this);
34.375 + return multi_nlmsg;
34.376 +}
34.377 +
34.378 +TypeId
34.379 +NetlinkMessage::GetTypeId (void)
34.380 +{
34.381 + static TypeId tid = TypeId ("ns3::NetlinkMessage")
34.382 + .SetParent<Header> ()
34.383 + .AddConstructor<NetlinkMessage> ()
34.384 + ;
34.385 + return tid;
34.386 +}
34.387 +TypeId
34.388 +NetlinkMessage::GetInstanceTypeId (void) const
34.389 +{
34.390 + return GetTypeId ();
34.391 +}
34.392 +
34.393 +uint32_t
34.394 +NetlinkMessage::GetTotalSize (void) const
34.395 +{
34.396 + return NETLINK_MSG_ALIGN(m_hdr.GetMsgLen ());
34.397 +}
34.398 +
34.399 +uint32_t
34.400 +NetlinkMessage::GetMsgSize (void) const
34.401 +{
34.402 + return m_hdr.GetMsgLen ();
34.403 +}
34.404 +
34.405 +uint32_t
34.406 +NetlinkMessage::GetPayloadSize (void) const
34.407 +{
34.408 + return m_hdr.GetPayloadSize ();
34.409 +}
34.410 +uint16_t
34.411 +NetlinkMessage::GetMsgType (void) const
34.412 +{
34.413 + return m_hdr.GetMsgType ();
34.414 +}
34.415 +
34.416 +uint8_t
34.417 +NetlinkMessage::GetFamily(void) const
34.418 +{
34.419 + if (IsMessageFlagsDump(m_hdr.GetMsgFlags()))
34.420 + {
34.421 + return m_genmsg.GetFamily();
34.422 + }
34.423 + else if (IsMessageAddress(m_hdr.GetMsgType()))
34.424 + {
34.425 + return m_addressTemplate.GetFamily();
34.426 + }
34.427 + else if (IsMessageInterface(m_hdr.GetMsgType()))
34.428 + {
34.429 + return m_interfaceTemplate.GetFamily();
34.430 + }
34.431 + else if (IsMessageRoute(m_hdr.GetMsgType()))
34.432 + {
34.433 + return m_routeTemplate.GetFamily();
34.434 + }
34.435 + else
34.436 + {
34.437 + NS_LOG_WARN("Netlink message type not supported, return AF_UNSPEC");
34.438 + return 0;
34.439 + }
34.440 +}
34.441 +
34.442 +void
34.443 +NetlinkMessage::Print (std::ostream &os) const
34.444 +{
34.445 + uint16_t type = m_hdr.GetMsgType ();
34.446 +
34.447 + os << "NetlinkMessage ";
34.448 + os << " ----Header:(";
34.449 + m_hdr.Print(os);
34.450 + os << ")";
34.451 +
34.452 + if (type == NETLINK_MSG_DONE )
34.453 + {
34.454 + os << "multipart message ends here";
34.455 + }
34.456 + else if (type == NETLINK_MSG_ERROR )
34.457 + {
34.458 + m_errorMessage.Print(os);
34.459 + }
34.460 + else if (type == NETLINK_RTM_GETROUTE || type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETLINK)
34.461 + {
34.462 + m_genmsg.Print(os);
34.463 + }
34.464 + else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE)
34.465 + {
34.466 + m_routeTemplate.Print(os);
34.467 + }
34.468 + else if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
34.469 + {
34.470 + m_addressTemplate.Print(os);
34.471 + }
34.472 + else if (type == NETLINK_RTM_NEWLINK || type == NETLINK_RTM_DELLINK)
34.473 + {
34.474 + m_interfaceTemplate.Print(os);
34.475 + }
34.476 + else
34.477 + {
34.478 + os << "service not supported yet( " << type <<")";
34.479 + }
34.480 +}
34.481 +uint32_t
34.482 +NetlinkMessage::GetSerializedSize (void) const
34.483 +{
34.484 + return NETLINK_MSG_ALIGN(m_hdr.GetMsgLen ());
34.485 +}
34.486 +
34.487 +void
34.488 +NetlinkMessage::Serialize (Buffer::Iterator& start) const
34.489 +{
34.490 + uint16_t type = m_hdr.GetMsgType();
34.491 +
34.492 + m_hdr.Serialize (start);
34.493 +
34.494 + if (type == NETLINK_MSG_DONE)
34.495 + {
34.496 + //nothing done
34.497 + }
34.498 + else if (type == NETLINK_MSG_ERROR)
34.499 + {
34.500 + m_errorMessage.Serialize(start);
34.501 + }
34.502 + else if (NetlinkMessage::IsMessageFlagsDump(m_hdr.GetMsgFlags()) && (type == NETLINK_RTM_GETROUTE
34.503 + || type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETLINK))
34.504 + {
34.505 + m_genmsg.Serialize (start);
34.506 + }
34.507 + else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
34.508 + {
34.509 + m_routeTemplate.Serialize (start);
34.510 + }
34.511 + else if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
34.512 + {
34.513 + m_addressTemplate.Serialize (start);
34.514 + }
34.515 + else if (type == NETLINK_RTM_NEWLINK || type == NETLINK_RTM_SETLINK)
34.516 + {
34.517 + m_interfaceTemplate.Serialize (start);
34.518 + }
34.519 + else
34.520 + {
34.521 + }
34.522 +}
34.523 +
34.524 +
34.525 +uint32_t
34.526 +NetlinkMessage::Deserialize (Buffer::Iterator&start)
34.527 +{
34.528 + uint32_t remaining;
34.529 +
34.530 + m_hdr.Deserialize (start);
34.531 + remaining = NETLINK_MSG_ALIGN(m_hdr.GetMsgLen ()) - m_hdr.GetSerializedSize ();
34.532 +
34.533 + //Deserialize service module
34.534 + uint16_t type = GetMsgType ();
34.535 + if (remaining)
34.536 + {
34.537 + if (type == NETLINK_MSG_DONE)
34.538 + {
34.539 + //do nothing
34.540 + }
34.541 + else if (type == NETLINK_MSG_ERROR)
34.542 + {
34.543 + remaining -= m_errorMessage.Deserialize(start);
34.544 + }
34.545 + else if (NetlinkMessage::IsMessageFlagsDump(m_hdr.GetMsgFlags()) && (type == NETLINK_RTM_GETROUTE
34.546 + || type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETLINK))
34.547 + {
34.548 + remaining -= m_genmsg.Deserialize (start, remaining);
34.549 + }
34.550 + else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
34.551 + {
34.552 + remaining -= m_routeTemplate.Deserialize (start, remaining);
34.553 + }
34.554 + else if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
34.555 + {
34.556 + remaining -= m_addressTemplate.Deserialize (start, remaining);
34.557 + }
34.558 + else if (type == NETLINK_RTM_NEWLINK || type == NETLINK_RTM_SETLINK)
34.559 + {
34.560 + remaining -= m_interfaceTemplate.Deserialize (start, remaining);
34.561 + }
34.562 + else
34.563 + {
34.564 + //do nothing
34.565 + }
34.566 + }
34.567 +
34.568 + return GetSerializedSize ();
34.569 +}
34.570 +
34.571 +
34.572 +/***********************************************************************************
34.573 +* \ MultipartNetlinkMessage
34.574 +***********************************************************************************/
34.575 +MultipartNetlinkMessage::MultipartNetlinkMessage()
34.576 +{}
34.577 +
34.578 +TypeId
34.579 +MultipartNetlinkMessage::GetTypeId (void)
34.580 +{
34.581 + static TypeId tid = TypeId ("ns3::MultipartNetlinkMessage")
34.582 + .SetParent<Header> ()
34.583 + .AddConstructor<MultipartNetlinkMessage> ()
34.584 + ;
34.585 + return tid;
34.586 +}
34.587 +TypeId
34.588 +MultipartNetlinkMessage::GetInstanceTypeId (void) const
34.589 +{
34.590 + return GetTypeId ();
34.591 +}
34.592 +
34.593 +void
34.594 +MultipartNetlinkMessage::Print (std::ostream &os) const
34.595 +{
34.596 + for (uint32_t i = 0; i < m_netlinkMessages.size (); i ++)
34.597 + {
34.598 + m_netlinkMessages[i].Print(os);
34.599 + }
34.600 +}
34.601 +uint32_t
34.602 +MultipartNetlinkMessage::GetSerializedSize (void) const
34.603 +{
34.604 + uint32_t len = 0;
34.605 +
34.606 + for (uint32_t i = 0; i < m_netlinkMessages.size (); i ++)
34.607 + {
34.608 + len += m_netlinkMessages[i].GetSerializedSize ();
34.609 + }
34.610 + return len;
34.611 +}
34.612 +void
34.613 +MultipartNetlinkMessage::Serialize (Buffer::Iterator start) const
34.614 +{
34.615 + for (uint32_t i = 0; i < m_netlinkMessages.size (); i ++)
34.616 + {
34.617 + m_netlinkMessages[i].Serialize(start);
34.618 + }
34.619 +}
34.620 +uint32_t
34.621 +MultipartNetlinkMessage::Deserialize (Buffer::Iterator start)
34.622 +{
34.623 + while (1)
34.624 + {
34.625 + NetlinkMessage nlmsg;
34.626 + nlmsg.Deserialize (start);
34.627 + AppendMessage(nlmsg);
34.628 +
34.629 + if (!(nlmsg.GetHeader().GetMsgFlags()&NETLINK_MSG_F_MULTI))
34.630 + break;
34.631 +
34.632 + if (nlmsg.GetHeader().GetMsgType() == NETLINK_MSG_DONE)
34.633 + break;
34.634 + }
34.635 + return GetSerializedSize ();
34.636 +}
34.637 +
34.638 +void
34.639 +MultipartNetlinkMessage::AppendMessage (NetlinkMessage nlmsg)
34.640 +{
34.641 + m_netlinkMessages.push_back(nlmsg);
34.642 +}
34.643 +
34.644 +void
34.645 +MultipartNetlinkMessage::Clear()
34.646 +{
34.647 + m_netlinkMessages.clear();
34.648 +}
34.649 +
34.650 +uint32_t
34.651 +MultipartNetlinkMessage::GetNMessages (void) const
34.652 +{
34.653 + return m_netlinkMessages.size();
34.654 +}
34.655 +NetlinkMessage
34.656 +MultipartNetlinkMessage::GetMessage(uint32_t index) const
34.657 +{
34.658 + NS_ASSERT(index < m_netlinkMessages.size());
34.659 + return m_netlinkMessages[index];
34.660 +}
34.661 +}; // namespace ns3
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/src/node/netlink-message.h Thu Oct 01 23:37:18 2009 +0900
35.3 @@ -0,0 +1,255 @@
35.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
35.5 +/*
35.6 +* Copyright (c) 2008 Liu Jian
35.7 +*
35.8 +* This program is free software; you can redistribute it and/or modify
35.9 +* it under the terms of the GNU General Public License version 2 as
35.10 +* published by the Free Software Foundation;
35.11 +*
35.12 +* This program is distributed in the hope that it will be useful,
35.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
35.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.15 +* GNU General Public License for more details.
35.16 +*
35.17 +* You should have received a copy of the GNU General Public License
35.18 +* along with this program; if not, write to the Free Software
35.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35.20 +*
35.21 +* Author: Liu Jian <liujatp@gmail.com>
35.22 +*/
35.23 +
35.24 +#ifndef NETLINK_MESSAGE_H
35.25 +#define NETLINK_MESSAGE_H
35.26 +
35.27 +#include "ns3/header.h"
35.28 +#include "ns3/address.h"
35.29 +#include "ns3/netlink-message-route.h"
35.30 +#include "ns3/netlink-attribute.h"
35.31 +
35.32 +
35.33 +namespace ns3 {
35.34 + class NetlinkPayload;
35.35 + class GeneralMessage;
35.36 + class InterfaceAddressMessage;
35.37 + class InterfaceInfoMessage;
35.38 + class RouteMessage;
35.39 + class MultipartNetlinkMessage;
35.40 +
35.41 +/**
35.42 +* \brief The Netlink message structure for an netlink packet
35.43 +*
35.44 +There are three levels to a Netlink message: The general Netlink
35.45 +message header, the IP service specific template, and the IP service
35.46 +specific data.
35.47 +
35.48 +0 1 2 3
35.49 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
35.50 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35.51 +| |
35.52 +| Netlink message header |
35.53 +| |
35.54 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35.55 +| |
35.56 +| IP Service Template |
35.57 +| |
35.58 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35.59 +| |
35.60 +| IP Service specific data in TLVs |
35.61 +| |
35.62 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35.63 +*/
35.64 +
35.65 + enum NetlinkMessageFlag
35.66 + {
35.67 + NETLINK_MSG_F_REQUEST = 1, /* It is request message. */
35.68 + NETLINK_MSG_F_MULTI = 2, /* Multipart message, terminated by NETLINK_MSG_DONE */
35.69 + NETLINK_MSG_F_ACK = 4, /* Reply with ack, with zero or error code */
35.70 + NETLINK_MSG_F_ECHO = 8, /* Echo this request = */
35.71 +
35.72 + /* Modifiers to Get request */
35.73 + NETLINK_MSG_F_ROOT = 0x100, /* specify tree root */
35.74 + NETLINK_MSG_F_MATCH = 0x200, /* return all matching */
35.75 + NETLINK_MSG_F_ATOMIC = 0x400, /* atomic Get = */
35.76 + NETLINK_MSG_F_DUMP = (NETLINK_MSG_F_ROOT|NETLINK_MSG_F_MATCH),
35.77 +
35.78 + /* Modifiers to NEW request */
35.79 + NETLINK_MSG_F_REPLACE = 0x100, /* Override existing = */
35.80 + NETLINK_MSG_F_EXCL = 0x200, /* Do not touch, if it exists */
35.81 + NETLINK_MSG_F_CREATE = 0x400, /* Create, if it does not exist */
35.82 + NETLINK_MSG_F_APPEND = 0x800, /* Add to end of list = */
35.83 + };
35.84 +
35.85 + enum NetlinkMessageType
35.86 + {
35.87 + NETLINK_MSG_NOOP = 0x1, /* Nothing. */
35.88 + NETLINK_MSG_ERROR = 0x2, /* Error */
35.89 + NETLINK_MSG_DONE = 0x3, /* End of a dump */
35.90 + NETLINK_MSG_OVERRUN = 0x4, /* Data lost */
35.91 + NETLINK_MSG_MIN_TYPE = 0x10, /* < 0x10: reserved control messages */
35.92 + };
35.93 +
35.94 +#define NETLINK_MSG_ALIGNTO 4
35.95 +#define NETLINK_MSG_ALIGN(len) ( ((len)+NETLINK_MSG_ALIGNTO-1) & ~(NETLINK_MSG_ALIGNTO-1) )
35.96 +
35.97 +class NetlinkMessageHeader : public ObjectBase
35.98 +{
35.99 +public:
35.100 + NetlinkMessageHeader ();
35.101 + NetlinkMessageHeader (uint16_t type, uint16_t flags, uint32_t seq, uint32_t pid);
35.102 +
35.103 + static TypeId GetTypeId (void);
35.104 + virtual TypeId GetInstanceTypeId (void) const;
35.105 + void Print (std::ostream &os) const;
35.106 + uint32_t GetSerializedSize (void) const;
35.107 + void Serialize (Buffer::Iterator& start) const;
35.108 + uint32_t Deserialize (Buffer::Iterator& start);
35.109 +
35.110 + void SetMsgLen (uint32_t v);
35.111 + void SetMsgFlags (uint16_t v);
35.112 + void SetMsgType (uint16_t v);
35.113 + void SetMsgSeq (uint32_t v);
35.114 + void SetMsgPid (uint32_t v);
35.115 + uint32_t GetMsgLen (void) const;
35.116 + uint16_t GetMsgFlags (void) const;
35.117 + uint16_t GetMsgType (void) const;
35.118 + uint32_t GetMsgSeq (void) const;
35.119 + uint32_t GetMsgPid (void) const;
35.120 +
35.121 + static uint32_t GetHeaderSize ();
35.122 + uint32_t GetPayloadSize (void) const;
35.123 +
35.124 +private:
35.125 + static const uint32_t NETLINK_MSG_HEADER_SIZE = 16; /* size of the nlmsghdr field*/
35.126 + uint32_t m_nlmsgLen; /* Length of message including header */
35.127 + uint16_t m_nlmsgType; /* Message content */
35.128 + uint16_t m_nlmsgFlags; /* Additional flags */
35.129 + uint32_t m_nlmsgSeq; /* Sequence number */
35.130 + uint32_t m_nlmsgPid; /* Sending process PID */
35.131 +};
35.132 +
35.133 +/**
35.134 +* \brief The struct nlmsgerr
35.135 +*/
35.136 +class NetlinkMessageError : public NetlinkPayload
35.137 +{
35.138 +public:
35.139 + NetlinkMessageError ();
35.140 + virtual ~NetlinkMessageError();
35.141 +
35.142 + static TypeId GetTypeId (void);
35.143 + virtual TypeId GetInstanceTypeId (void) const;
35.144 + virtual void Serialize (Buffer::Iterator& start) const;
35.145 + virtual uint32_t Deserialize (Buffer::Iterator& start);
35.146 + virtual void Print (std::ostream &os) const;
35.147 + virtual uint32_t GetSerializedSize (void) const;
35.148 +
35.149 + void SetError (int32_t v);
35.150 + int32_t GetError (void) const;
35.151 + void SetMsg(NetlinkMessageHeader v);
35.152 + NetlinkMessageHeader GetMsg (void) const;
35.153 +
35.154 +private:
35.155 + static const int NETLINK_MSG_ERROR_SIZE = 20; /* size of the nlmsgerror field*/
35.156 + int32_t m_error;
35.157 + NetlinkMessageHeader m_msg;
35.158 +};
35.159 +
35.160 +
35.161 +class NetlinkMessage : public ObjectBase
35.162 +{
35.163 +public:
35.164 + NetlinkMessage ();
35.165 +
35.166 + static TypeId GetTypeId (void);
35.167 + TypeId GetInstanceTypeId (void) const;
35.168 + void Print (std::ostream &os) const;
35.169 + uint32_t GetSerializedSize (void) const;
35.170 + void Serialize (Buffer::Iterator& start) const;
35.171 + uint32_t Deserialize (Buffer::Iterator& start);
35.172 +
35.173 + operator MultipartNetlinkMessage (void) const;
35.174 +
35.175 + uint32_t GetTotalSize (void) const; //length of netlink message including padding
35.176 + uint32_t GetMsgSize (void) const; //length of netlink message not including padding
35.177 + uint32_t GetPayloadSize (void) const; //length of message payload
35.178 + uint16_t GetMsgType (void) const;
35.179 + uint8_t GetFamily(void) const;
35.180 +
35.181 + void SetHeader (NetlinkMessageHeader hdr);
35.182 + NetlinkMessageHeader GetHeader (void) const;
35.183 +
35.184 + //before set message body, should set header first
35.185 + void SetErrorMessage (NetlinkMessageError errmsg);
35.186 + void SetGeneralMessage (GeneralMessage genmsg);
35.187 + void SetInterfaceInfoMessage (InterfaceInfoMessage v);
35.188 + void SetInterfaceAddressMessage (InterfaceAddressMessage v);
35.189 + void SetRouteMessage (RouteMessage v);
35.190 + NetlinkMessageError GetErrorMessage (void) const;
35.191 + GeneralMessage GetGeneralMessage (void) const;
35.192 + InterfaceInfoMessage GetInterfaceInfoMessage (void) const;
35.193 + InterfaceAddressMessage GetInterfaceAddressMessage (void) const;
35.194 + RouteMessage GetRouteMessage (void) const;
35.195 +
35.196 + /**
35.197 + * \returns true if type was control type, false otherwise.
35.198 + */
35.199 + static bool IsMessageNetlinkControl (uint16_t type);
35.200 + /**
35.201 + * \returns true if type was netlink route, false otherwise.
35.202 + */
35.203 + static bool IsMessageNetlinkRoute (uint16_t type);
35.204 + static bool IsMessageAddress (uint16_t type);
35.205 + static bool IsMessageInterface (uint16_t type);
35.206 + static bool IsMessageRoute (uint16_t type);
35.207 + /**
35.208 + * \returns true if type was GETxxx , false otherwise.
35.209 + */
35.210 + static bool IsMessageTypeGet (uint16_t type);
35.211 + /**
35.212 + * \returns true if flag has ack , false otherwise.
35.213 + */
35.214 + static bool IsMessageFlagsAck (uint16_t flags);
35.215 + /**
35.216 + * \returns true if flag has request , false otherwise.
35.217 + */
35.218 + static bool IsMessageFlagsRequest (uint16_t flags);
35.219 + /**
35.220 + * \returns true if flag has dump , false otherwise.
35.221 + */
35.222 + static bool IsMessageFlagsDump (uint16_t flags);
35.223 +
35.224 +private:
35.225 + NetlinkMessageHeader m_hdr;
35.226 +
35.227 + //only one type of messages below exists in real world application
35.228 + NetlinkMessageError m_errorMessage;
35.229 + GeneralMessage m_genmsg;
35.230 + InterfaceInfoMessage m_interfaceTemplate;
35.231 + InterfaceAddressMessage m_addressTemplate;
35.232 + RouteMessage m_routeTemplate;
35.233 +};
35.234 +
35.235 +class MultipartNetlinkMessage : public Header
35.236 +{
35.237 +public:
35.238 + MultipartNetlinkMessage ();
35.239 +
35.240 + static TypeId GetTypeId (void);
35.241 + virtual TypeId GetInstanceTypeId (void) const;
35.242 + virtual void Print (std::ostream &os) const;
35.243 + virtual uint32_t GetSerializedSize (void) const;
35.244 + virtual void Serialize (Buffer::Iterator start) const;
35.245 + virtual uint32_t Deserialize (Buffer::Iterator start);
35.246 +
35.247 + void AppendMessage (NetlinkMessage nlmsg);
35.248 + void Clear();
35.249 + uint32_t GetNMessages (void) const;
35.250 + NetlinkMessage GetMessage(uint32_t index) const;
35.251 +
35.252 +private:
35.253 + std::vector<NetlinkMessage> m_netlinkMessages;
35.254 +};
35.255 +
35.256 +}; // namespace ns3
35.257 +
35.258 +#endif /* NETLINK_MESSAGE_H */
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/src/node/netlink-socket-address.cc Thu Oct 01 23:37:18 2009 +0900
36.3 @@ -0,0 +1,118 @@
36.4 +/* -*- Mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
36.5 +/*
36.6 +* Copyright (c) 2008 Liu Jian
36.7 +*
36.8 +* This program is free software; you can redistribute it and/or modify
36.9 +* it under the terms of the GNU General Public License version 2 as
36.10 +* published by the Free Software Foundation;
36.11 +*
36.12 +* This program is distributed in the hope that it will be useful,
36.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
36.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.15 +* GNU General Public License for more details.
36.16 +*
36.17 +* You should have received a copy of the GNU General Public License
36.18 +* along with this program; if not, write to the Free Software
36.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36.20 +*
36.21 +* Author: Liu Jian <liujatp@gmail.com>
36.22 +*/
36.23 +
36.24 +#include "netlink-socket-address.h"
36.25 +
36.26 +namespace ns3 {
36.27 +
36.28 +NetlinkSocketAddress::NetlinkSocketAddress(uint32_t pid, uint32_t groups)
36.29 + :m_pid(pid), m_groups(groups)
36.30 +{}
36.31 +
36.32 +NetlinkSocketAddress::NetlinkSocketAddress ()
36.33 + :m_pid (0),m_groups (0)
36.34 +{}
36.35 +
36.36 +NetlinkSocketAddress::~NetlinkSocketAddress ()
36.37 +{}
36.38 +
36.39 +void NetlinkSocketAddress::SetProcessID (uint32_t pid)
36.40 +{
36.41 + m_pid = pid;
36.42 +}
36.43 +
36.44 +void NetlinkSocketAddress::SetGroupsMask (uint32_t mask)
36.45 +{
36.46 + m_groups = mask;
36.47 +}
36.48 +
36.49 +uint32_t NetlinkSocketAddress::GetProcessID (void) const
36.50 +{
36.51 + return m_pid;
36.52 +}
36.53 +
36.54 +uint32_t NetlinkSocketAddress::GetGroupsMask (void) const
36.55 +{
36.56 + return m_groups;
36.57 +}
36.58 +
36.59 +NetlinkSocketAddress::operator Address (void) const
36.60 +{
36.61 + return ConvertTo ();
36.62 +}
36.63 +
36.64 +Address NetlinkSocketAddress::ConvertTo (void) const
36.65 +{
36.66 + uint8_t buffer[8];
36.67 +
36.68 + buffer[0] = (m_pid >> 24) & 0xff;
36.69 + buffer[1] = (m_pid >> 16) & 0xff;
36.70 + buffer[2] = (m_pid >> 8) & 0xff;
36.71 + buffer[3] = (m_pid >> 0) & 0xff;
36.72 + buffer[4] = (m_groups >> 24) & 0xff;
36.73 + buffer[5] = (m_groups >> 16) & 0xff;
36.74 + buffer[6] = (m_groups >> 8) & 0xff;
36.75 + buffer[7] = (m_groups >> 0) & 0xff;
36.76 +
36.77 + return Address (GetType (), buffer, 8);
36.78 +}
36.79 +
36.80 +NetlinkSocketAddress NetlinkSocketAddress::ConvertFrom (const Address &address)
36.81 +{
36.82 + NS_ASSERT (IsMatchingType (address));
36.83 +
36.84 + NetlinkSocketAddress nl;
36.85 + uint8_t buf[8];
36.86 +
36.87 + address.CopyTo (buf);
36.88 +
36.89 + nl.m_pid = 0;
36.90 + nl.m_pid |= buf[0];
36.91 + nl.m_pid <<= 8;
36.92 + nl.m_pid |= buf[1];
36.93 + nl.m_pid <<= 8;
36.94 + nl.m_pid |= buf[2];
36.95 + nl.m_pid <<= 8;
36.96 + nl.m_pid |= buf[3];
36.97 +
36.98 + nl.m_groups = 0;
36.99 + nl.m_groups |= buf[4];
36.100 + nl.m_groups <<= 8;
36.101 + nl.m_groups |= buf[5];
36.102 + nl.m_groups <<= 8;
36.103 + nl.m_groups |= buf[6];
36.104 + nl.m_groups <<= 8;
36.105 + nl.m_groups |= buf[7];
36.106 +
36.107 + return nl;
36.108 +}
36.109 +
36.110 +bool NetlinkSocketAddress::IsMatchingType (const Address &address)
36.111 +{
36.112 + return address.IsMatchingType (GetType ());
36.113 +}
36.114 +
36.115 +uint8_t NetlinkSocketAddress::GetType (void)
36.116 +{
36.117 + static uint8_t type = Address::Register ();
36.118 + return type;
36.119 +}
36.120 +
36.121 +} // namespace ns3
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/src/node/netlink-socket-address.h Thu Oct 01 23:37:18 2009 +0900
37.3 @@ -0,0 +1,69 @@
37.4 +/* -*- Mode:C; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
37.5 +/*
37.6 +* Copyright (c) 2008 Liu Jian
37.7 +*
37.8 +* This program is free software; you can redistribute it and/or modify
37.9 +* it under the terms of the GNU General Public License version 2 as
37.10 +* published by the Free Software Foundation;
37.11 +*
37.12 +* This program is distributed in the hope that it will be useful,
37.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
37.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.15 +* GNU General Public License for more details.
37.16 +*
37.17 +* You should have received a copy of the GNU General Public License
37.18 +* along with this program; if not, write to the Free Software
37.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37.20 +*
37.21 +* Author: Liu Jian <liujatp@gmail.com>
37.22 +*/
37.23 +#ifndef NETLINK_SOCKET_ADDRESS_H
37.24 +#define NETLINK_SOCKET_ADDRESS_H
37.25 +
37.26 +#include "ns3/ptr.h"
37.27 +#include "address.h"
37.28 +
37.29 +namespace ns3 {
37.30 +
37.31 +class NetlinkSocketAddress
37.32 +{
37.33 +public:
37.34 + NetlinkSocketAddress (uint32_t pid, uint32_t groups);
37.35 + NetlinkSocketAddress ();
37.36 + ~NetlinkSocketAddress ();
37.37 +
37.38 + void SetProcessID (uint32_t pid);
37.39 + void SetGroupsMask (uint32_t mask);
37.40 +
37.41 + uint32_t GetProcessID (void) const;
37.42 + uint32_t GetGroupsMask (void) const;
37.43 +
37.44 + /**
37.45 + * \returns an Address instance which represents this
37.46 + * NetlinkSocketAddress instance.
37.47 + */
37.48 + operator Address (void) const;
37.49 + /**
37.50 + * \param address the Address instance to convert from.
37.51 + *
37.52 + * Returns an NetlinkSocketAddress which corresponds to the input
37.53 + * Address
37.54 + */
37.55 + static NetlinkSocketAddress ConvertFrom (const Address &address);
37.56 + /**
37.57 + * \returns true if the address matches, false otherwise.
37.58 + */
37.59 + static bool IsMatchingType (const Address &address);
37.60 +private:
37.61 + static uint8_t GetType (void);
37.62 + Address ConvertTo (void) const;
37.63 +
37.64 + uint32_t m_pid;
37.65 + uint32_t m_groups;
37.66 +
37.67 +};
37.68 +
37.69 +
37.70 +} // namespace ns3
37.71 +
37.72 +#endif /* NETLINK_SOCKET_ADDRESS_H */
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/src/node/netlink-socket-factory.cc Thu Oct 01 23:37:18 2009 +0900
38.3 @@ -0,0 +1,47 @@
38.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
38.5 +/*
38.6 +* Copyright (c) 2008 Liu Jian
38.7 +*
38.8 +* This program is free software; you can redistribute it and/or modify
38.9 +* it under the terms of the GNU General Public License version 2 as
38.10 +* published by the Free Software Foundation;
38.11 +*
38.12 +* This program is distributed in the hope that it will be useful,
38.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
38.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38.15 +* GNU General Public License for more details.
38.16 +*
38.17 +* You should have received a copy of the GNU General Public License
38.18 +* along with this program; if not, write to the Free Software
38.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38.20 +*
38.21 +* Author: Liu Jian <liujatp@gmail.com>
38.22 +*/
38.23 +
38.24 +#include "netlink-socket-factory.h"
38.25 +#include "node.h"
38.26 +#include "netlink-socket.h"
38.27 +
38.28 +namespace ns3 {
38.29 +
38.30 +NS_OBJECT_ENSURE_REGISTERED (NetlinkSocketFactory);
38.31 +
38.32 +TypeId
38.33 +NetlinkSocketFactory::GetTypeId (void)
38.34 +{
38.35 + static TypeId tid = TypeId ("ns3::NetlinkSocketFactory")
38.36 + .SetParent<SocketFactory> ();
38.37 + return tid;
38.38 +}
38.39 +
38.40 +NetlinkSocketFactory::NetlinkSocketFactory ()
38.41 +{}
38.42 +
38.43 +Ptr<Socket> NetlinkSocketFactory::CreateSocket (void)
38.44 +{
38.45 + Ptr<Node> node = GetObject<Node> ();
38.46 + Ptr<NetlinkSocket> socket = CreateObject<NetlinkSocket> ();
38.47 + socket->SetNode (node);
38.48 + return socket;
38.49 +}
38.50 +} // namespace ns3
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/src/node/netlink-socket-factory.h Thu Oct 01 23:37:18 2009 +0900
39.3 @@ -0,0 +1,50 @@
39.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
39.5 +/*
39.6 + * Copyright (c) 2008 Liu Jian
39.7 + *
39.8 + * This program is free software; you can redistribute it and/or modify
39.9 + * it under the terms of the GNU General Public License version 2 as
39.10 + * published by the Free Software Foundation;
39.11 + *
39.12 + * This program is distributed in the hope that it will be useful,
39.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39.15 + * GNU General Public License for more details.
39.16 + *
39.17 + * You should have received a copy of the GNU General Public License
39.18 + * along with this program; if not, write to the Free Software
39.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39.20 + *
39.21 + * Author: Liu Jian <liujatp@gmail.com>
39.22 + */
39.23 +#ifndef NETLINK_SOCKET_FACTORY_H
39.24 +#define NETLINK_SOCKET_FACTORY_H
39.25 +
39.26 +#include "socket-factory.h"
39.27 +
39.28 +namespace ns3 {
39.29 +
39.30 +class Socket;
39.31 +
39.32 +/**
39.33 + * This can be used as an interface in a node in order for the node to
39.34 + * generate NetlinkSockets.
39.35 + */
39.36 +class NetlinkSocketFactory : public SocketFactory
39.37 +{
39.38 +public:
39.39 + static TypeId GetTypeId (void);
39.40 +
39.41 + NetlinkSocketFactory ();
39.42 +
39.43 + /**
39.44 + * Creates a NetlinkSocket and returns a pointer to it.
39.45 + *
39.46 + * \return a pointer to the created socket
39.47 + */
39.48 + virtual Ptr<Socket> CreateSocket (void);
39.49 +};
39.50 +
39.51 +} // namespace ns3
39.52 +
39.53 +#endif /* NETLINK_SOCKET_FACTORY_H */
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/src/node/netlink-socket-test.cc Thu Oct 01 23:37:18 2009 +0900
40.3 @@ -0,0 +1,555 @@
40.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
40.5 +/*
40.6 +* Copyright (c) 2008 Liu Jian
40.7 +*
40.8 +* This program is free software; you can redistribute it and/or modify
40.9 +* it under the terms of the GNU General Public License version 2 as
40.10 +* published by the Free Software Foundation;
40.11 +*
40.12 +* This program is distributed in the hope that it will be useful,
40.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
40.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40.15 +* GNU General Public License for more details.
40.16 +*
40.17 +* You should have received a copy of the GNU General Public License
40.18 +* along with this program; if not, write to the Free Software
40.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40.20 +*
40.21 +* Author: Liu Jian <liujatp@gmail.com>
40.22 +*/
40.23 +#ifdef RUN_SELF_TESTS
40.24 +
40.25 +#include "ns3/test.h"
40.26 +#include "ns3/core-module.h"
40.27 +#include "ns3/simulator-module.h"
40.28 +#include "ns3/node-module.h"
40.29 +#include "ns3/helper-module.h"
40.30 +#include "ns3/global-route-manager.h"
40.31 +#include "ns3/assert.h"
40.32 +#include "ns3/log.h"
40.33 +#include <string>
40.34 +#include <list>
40.35 +
40.36 +
40.37 +NS_LOG_COMPONENT_DEFINE ("NetlinkSocketTest");
40.38 +
40.39 +using namespace ns3;
40.40 +
40.41 +
40.42 +class NetlinkSocketTest: public Test
40.43 +{
40.44 +public:
40.45 + NetlinkSocketTest ();
40.46 + virtual bool RunTests (void);
40.47 +private:
40.48 + NetlinkMessage BuildGetMessage (uint16_t type, uint16_t flags);
40.49 + NetlinkMessage BuildAddressMessage (uint16_t type, uint16_t flags);
40.50 + NetlinkMessage BuildLinkChangeMessage (uint16_t type, uint16_t flags);
40.51 + NetlinkMessage BuildRouteMessage (uint16_t type, uint16_t flags);
40.52 + MultipartNetlinkMessage BuildMultipartMessage (uint16_t type, uint16_t flags);
40.53 +
40.54 + bool CheckIsAck (NetlinkMessage nlmsg);
40.55 + bool CheckIsDump (MultipartNetlinkMessage nlmsg);
40.56 + bool CheckIsEqual (NetlinkMessageHeader nhr1, NetlinkMessageHeader nhr2);
40.57 + bool CheckIsEqual (NetlinkMessage nlmsg1, NetlinkMessage nlmsg2);
40.58 + bool CheckIsEqual (MultipartNetlinkMessage mulmsg1, MultipartNetlinkMessage mulmsg2);
40.59 +
40.60 + bool TestNetlinkSerilization ();
40.61 + bool TestInterfaceAddressMessage ();
40.62 + bool TestInferfaceInfoMessage ();
40.63 + bool TestRouteMessage ();
40.64 + bool TestBroadcastMessage ();
40.65 +
40.66 + void ReceiveUnicastPacket (Ptr<Socket> socket);
40.67 + void ReceiveMulticastPacket (Ptr<Socket> socket);
40.68 + void SendCmdToKernel (uint16_t type);
40.69 + void SendNetlinkMessage (NetlinkMessage nlmsg);
40.70 + void MonitorKernelChanges ();
40.71 +
40.72 + std::list<MultipartNetlinkMessage> m_unicastList;
40.73 + std::list<MultipartNetlinkMessage> m_multicastList;
40.74 + Ptr<Socket> m_cmdSock;
40.75 + Ptr<Socket> m_groupSock;
40.76 + int m_pid;
40.77 +};
40.78 +
40.79 +
40.80 +
40.81 +NetlinkMessage
40.82 +NetlinkSocketTest::BuildGetMessage(uint16_t type, uint16_t flags)
40.83 +{
40.84 + NS_ASSERT(type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE);
40.85 +
40.86 + NetlinkMessage nlmsg;
40.87 + flags |= (NETLINK_MSG_F_DUMP|NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST);
40.88 + nlmsg.SetHeader(NetlinkMessageHeader(type, flags, 0, 0));
40.89 + GeneralMessage genmsg;
40.90 + genmsg.SetFamily(2);
40.91 + nlmsg.SetGeneralMessage(genmsg);
40.92 + //no attributes appended
40.93 + return nlmsg;
40.94 +}
40.95 +
40.96 +NetlinkMessage
40.97 +NetlinkSocketTest::BuildAddressMessage( uint16_t type, uint16_t flags)
40.98 +{
40.99 + NS_ASSERT(type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
40.100 +
40.101 + flags |= (NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST);
40.102 + if (type == NETLINK_RTM_NEWADDR)
40.103 + {
40.104 + flags |= NETLINK_MSG_F_CREATE;
40.105 + }
40.106 +
40.107 + NetlinkMessage nlmsg;
40.108 + //set header
40.109 + nlmsg.SetHeader(NetlinkMessageHeader(type, flags, 0, 0));
40.110 +
40.111 + //set service module
40.112 + InterfaceAddressMessage ifamsg;
40.113 + {
40.114 + ifamsg.SetFamily(2);
40.115 + ifamsg.SetLength(24);
40.116 + ifamsg.SetInterfaceIndex(3);
40.117 +
40.118 + ifamsg.AppendAttribute(NetlinkAttribute(InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, Ipv4Address("192.168.0.1")));
40.119 + ifamsg.AppendAttribute(NetlinkAttribute(InterfaceAddressMessage::IF_A_ADDRESS,ADDRESS, Ipv4Address("192.168.0.2")));
40.120 + ifamsg.AppendAttribute(NetlinkAttribute(InterfaceAddressMessage::IF_A_LABEL, STRING, "TESTSTRING"));
40.121 + }
40.122 +
40.123 + nlmsg.SetInterfaceAddressMessage(ifamsg);
40.124 +
40.125 + return nlmsg;
40.126 +}
40.127 +
40.128 +NetlinkMessage
40.129 +NetlinkSocketTest::BuildLinkChangeMessage( uint16_t type, uint16_t flags)
40.130 +{
40.131 + NetlinkMessage nlmsg;
40.132 + NS_LOG_WARN(this<<type<<flags<< " not supported");
40.133 + return nlmsg;
40.134 +}
40.135 +
40.136 +NetlinkMessage
40.137 +NetlinkSocketTest::BuildRouteMessage(uint16_t type, uint16_t flags)
40.138 +{
40.139 + NS_ASSERT(type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE);
40.140 +
40.141 + flags |= (NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST);
40.142 + if (type == NETLINK_RTM_NEWROUTE)
40.143 + {
40.144 + flags |= NETLINK_MSG_F_CREATE;
40.145 + }
40.146 +
40.147 + NetlinkMessage nlmsg;
40.148 + //set header
40.149 + nlmsg.SetHeader(NetlinkMessageHeader(type, flags, 0, m_pid));
40.150 +
40.151 + //set service module
40.152 + RouteMessage rtmsg;
40.153 + //set attribute
40.154 + {
40.155 + rtmsg.AppendAttribute(NetlinkAttribute(RouteMessage::RT_A_DST, ADDRESS, Ipv4Address("192.168.0.10")));
40.156 + rtmsg.AppendAttribute(NetlinkAttribute(RouteMessage::RT_A_SRC, ADDRESS, Ipv4Address("192.168.2.10")));
40.157 + rtmsg.AppendAttribute(NetlinkAttribute(RouteMessage::RT_A_GATEWAY, ADDRESS, Ipv4Address("192.168.2.1")));
40.158 + rtmsg.AppendAttribute(NetlinkAttribute(RouteMessage::RT_A_OIF, U32, (uint32_t)2));
40.159 + }
40.160 +
40.161 + nlmsg.SetRouteMessage(rtmsg);
40.162 + return nlmsg;
40.163 +}
40.164 +
40.165 +MultipartNetlinkMessage
40.166 +NetlinkSocketTest::BuildMultipartMessage(uint16_t type, uint16_t flags)
40.167 +{
40.168 + //usually multi-part message used for message dump, kernel return to user space for NETLINK_RTM_GETxxx
40.169 + //type = NETLINK_RTM_NEWxxx, flags = NETLINK_MSG_F_MULTI, terminated by NETLINK_MSG_DONE,
40.170 + //here this example contain 2 NETLINK_MSG_F_MULTI
40.171 + NS_ASSERT(flags&NETLINK_MSG_F_MULTI);
40.172 +
40.173 + MultipartNetlinkMessage nlmsg;
40.174 + NetlinkMessage nlmsg1, nlmsg2, nlmsg3;
40.175 + nlmsg1 = BuildAddressMessage(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI);
40.176 + nlmsg.AppendMessage(nlmsg1);
40.177 + //the first nlmsg
40.178 + nlmsg2 = BuildRouteMessage(NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI);
40.179 + nlmsg.AppendMessage(nlmsg2);
40.180 + //the second nlmsg
40.181 + nlmsg3.SetHeader(NetlinkMessageHeader(NETLINK_MSG_DONE, flags, 1, m_pid));
40.182 + nlmsg.AppendMessage(nlmsg3);
40.183 +
40.184 + return nlmsg;
40.185 +}
40.186 +
40.187 +
40.188 +
40.189 +
40.190 +bool
40.191 +NetlinkSocketTest::CheckIsAck(NetlinkMessage nlmsg)
40.192 +{
40.193 + return (nlmsg.GetMsgType() == NETLINK_MSG_ERROR && nlmsg.GetErrorMessage().GetError() == 0);
40.194 +}
40.195 +
40.196 +bool
40.197 +NetlinkSocketTest::CheckIsDump(MultipartNetlinkMessage mulmsg)
40.198 +{
40.199 + return ( mulmsg.GetNMessages() > 0 && mulmsg.GetMessage(0).GetHeader().GetMsgFlags() & NETLINK_MSG_F_MULTI &&
40.200 + mulmsg.GetMessage(mulmsg.GetNMessages()-1).GetMsgType() == NETLINK_MSG_DONE);
40.201 +}
40.202 +
40.203 +bool
40.204 +NetlinkSocketTest::CheckIsEqual(NetlinkMessageHeader nhr1, NetlinkMessageHeader nhr2)
40.205 +{
40.206 + return (nhr1.GetMsgType() == nhr2.GetMsgType() && nhr1.GetMsgFlags() == nhr2.GetMsgFlags() && nhr1.GetMsgLen() == nhr2.GetMsgLen());
40.207 +}
40.208 +
40.209 +bool
40.210 +NetlinkSocketTest::CheckIsEqual(NetlinkMessage nlmsg1, NetlinkMessage nlmsg2)
40.211 +{
40.212 + return CheckIsEqual(nlmsg1.GetHeader(), nlmsg2.GetHeader());
40.213 +}
40.214 +
40.215 +bool
40.216 +NetlinkSocketTest::CheckIsEqual(MultipartNetlinkMessage mulmsg1, MultipartNetlinkMessage mulmsg2)
40.217 +{
40.218 + if (mulmsg1.GetNMessages() != mulmsg2.GetNMessages())
40.219 + return false;
40.220 +
40.221 + for (uint32_t i = 0; i < mulmsg1.GetNMessages(); i ++)
40.222 + {
40.223 + if (!CheckIsEqual(mulmsg1.GetMessage(i), mulmsg2.GetMessage(i)))
40.224 + return false;
40.225 + }
40.226 + return true;
40.227 +}
40.228 +
40.229 +bool
40.230 +NetlinkSocketTest::TestNetlinkSerilization()
40.231 +{
40.232 + MultipartNetlinkMessage multinlmsg1, multinlmsg2;
40.233 + Ptr<Packet> p = Create<Packet> ();
40.234 + bool result = true;
40.235 +
40.236 + multinlmsg1 = BuildMultipartMessage(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_REQUEST|NETLINK_MSG_F_MULTI);
40.237 + p->AddHeader (multinlmsg1);
40.238 + p->RemoveHeader(multinlmsg2);
40.239 + NS_TEST_ASSERT(CheckIsEqual(multinlmsg1, multinlmsg2));
40.240 +
40.241 + return result;
40.242 +}
40.243 +bool
40.244 +NetlinkSocketTest::TestInterfaceAddressMessage()
40.245 +{
40.246 + MultipartNetlinkMessage dump1, dump2, dump3;
40.247 + NetlinkMessage nlmsg1,nlmsg2;
40.248 + bool result = true;
40.249 +
40.250 + //dump interface address
40.251 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETADDR, 0));
40.252 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.253 + dump1 = m_unicastList.front();
40.254 + m_unicastList.pop_front();
40.255 + NS_TEST_ASSERT(CheckIsDump(dump1));
40.256 +
40.257 + //add interface address
40.258 + SendNetlinkMessage(BuildAddressMessage(NETLINK_RTM_NEWADDR,0));
40.259 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.260 + nlmsg1 = m_unicastList.front().GetMessage(0);
40.261 + m_unicastList.pop_front();
40.262 + NS_TEST_ASSERT(CheckIsAck(nlmsg1));
40.263 +
40.264 + //dump interface address
40.265 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETADDR, 0));
40.266 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.267 + dump2 = m_unicastList.front();
40.268 + m_unicastList.pop_front();
40.269 + NS_TEST_ASSERT(CheckIsDump(dump2));
40.270 +
40.271 + //del interface address
40.272 + SendNetlinkMessage(BuildAddressMessage(NETLINK_RTM_DELADDR,0));
40.273 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.274 + nlmsg2 = m_unicastList.front().GetMessage(0);
40.275 + m_unicastList.pop_front();
40.276 + NS_TEST_ASSERT(CheckIsAck(nlmsg2));
40.277 +
40.278 + //dump interface address
40.279 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETADDR, 0));
40.280 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.281 + dump3 = m_unicastList.front();
40.282 + m_unicastList.pop_front();
40.283 + NS_TEST_ASSERT(CheckIsDump(dump3));
40.284 +
40.285 + NS_TEST_ASSERT(CheckIsEqual(dump1, dump3));
40.286 +
40.287 + return result;
40.288 +}
40.289 +
40.290 +
40.291 +bool
40.292 +NetlinkSocketTest::TestRouteMessage()
40.293 +{
40.294 + MultipartNetlinkMessage dump1, dump2, dump3;
40.295 + NetlinkMessage nlmsg1,nlmsg2;
40.296 + bool result = true;
40.297 +
40.298 + //dump route entry
40.299 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETROUTE, 0));
40.300 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.301 + dump1 = m_unicastList.front();
40.302 + m_unicastList.pop_front();
40.303 + NS_TEST_ASSERT(CheckIsDump(dump1));
40.304 +
40.305 + //add route entry
40.306 + SendNetlinkMessage(BuildRouteMessage(NETLINK_RTM_NEWROUTE,0));
40.307 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.308 + nlmsg1 = m_unicastList.front().GetMessage(0);
40.309 + m_unicastList.pop_front();
40.310 + NS_TEST_ASSERT(CheckIsAck(nlmsg1));
40.311 +
40.312 + //dump route entry
40.313 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETROUTE, 0));
40.314 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.315 + dump2 = m_unicastList.front();
40.316 + m_unicastList.pop_front();
40.317 + NS_TEST_ASSERT(CheckIsDump(dump2));
40.318 +
40.319 + //del route entry
40.320 + SendNetlinkMessage(BuildRouteMessage(NETLINK_RTM_DELROUTE,0));
40.321 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.322 + nlmsg2 = m_unicastList.front().GetMessage(0);
40.323 + m_unicastList.pop_front();
40.324 + NS_ASSERT(CheckIsAck(nlmsg2));
40.325 +
40.326 + //dump route entry
40.327 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETROUTE, 0));
40.328 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.329 + dump3 = m_unicastList.front();
40.330 + m_unicastList.pop_front();
40.331 + NS_TEST_ASSERT(CheckIsDump(dump3));
40.332 +
40.333 + NS_TEST_ASSERT(CheckIsEqual(dump1, dump3));
40.334 +
40.335 + return result;
40.336 +}
40.337 +
40.338 +bool
40.339 +NetlinkSocketTest::TestInferfaceInfoMessage()
40.340 +{
40.341 + //now netlink not support NEWLINK/DELLINK yet
40.342 + MultipartNetlinkMessage multinlmsg;
40.343 + bool result = true;
40.344 +
40.345 + //dump interface address
40.346 + SendNetlinkMessage(BuildGetMessage(NETLINK_RTM_GETLINK, 0));
40.347 + NS_TEST_ASSERT_EQUAL(m_unicastList.size(), 1);
40.348 + multinlmsg = m_unicastList.front();
40.349 + m_unicastList.pop_front();
40.350 + NS_TEST_ASSERT(CheckIsDump(multinlmsg));
40.351 +
40.352 + NS_TEST_ASSERT(multinlmsg.GetNMessages() > 1 && multinlmsg.GetMessage(0).GetMsgType() == NETLINK_RTM_NEWLINK);
40.353 +
40.354 + return result;
40.355 +}
40.356 +
40.357 +bool
40.358 +NetlinkSocketTest::TestBroadcastMessage()
40.359 +{
40.360 + bool result = true;
40.361 + //at 2Xs, m_cmdSock send an request to kernel to add/del an interface address
40.362 + //and an route entry, the m_groupSock will recv the changed information
40.363 + //through the broadcast way
40.364 + m_multicastList.clear();
40.365 + Simulator::Schedule (Seconds (1), &NetlinkSocketTest::MonitorKernelChanges, this);
40.366 + Simulator::Schedule (Seconds (2), &NetlinkSocketTest::SendCmdToKernel, this, NETLINK_RTM_NEWADDR);
40.367 + Simulator::Schedule (Seconds (4), &NetlinkSocketTest::SendCmdToKernel, this, NETLINK_RTM_NEWROUTE);
40.368 + Simulator::Schedule (Seconds (6), &NetlinkSocketTest::SendCmdToKernel, this, NETLINK_RTM_DELADDR);
40.369 + Simulator::Schedule (Seconds (8), &NetlinkSocketTest::SendCmdToKernel, this, NETLINK_RTM_DELROUTE);
40.370 +
40.371 + return result;
40.372 +};
40.373 +
40.374 +
40.375 +void
40.376 +NetlinkSocketTest::SendNetlinkMessage(NetlinkMessage nlmsg)
40.377 +{
40.378 +#if 1
40.379 + Ptr<Packet> p = Create<Packet> ();
40.380 + p->AddHeader (MultipartNetlinkMessage(nlmsg));
40.381 +#else
40.382 + char buf[20] = {0x14,0x00,0x00,0x00,0x12,0x00,0x05,0x03,
40.383 + 0x34,0xb2,0xf5,0x47,0x01,0x00,0x00,0x00,
40.384 + 0x00,0x00,0x00,0x00};
40.385 + uint32_t count = 20;
40.386 + Ptr<Packet> p = ns3::Create<Packet> ((const uint8_t *)buf, (uint32_t)count);
40.387 +#endif
40.388 +
40.389 + m_cmdSock->Send (p);
40.390 +}
40.391 +void
40.392 +NetlinkSocketTest::SendCmdToKernel(uint16_t type)
40.393 +{
40.394 + NS_LOG_INFO("At = " << Simulator::Now ().GetSeconds () <<"s, user send cmd to kernel, cmd = " << type);
40.395 +
40.396 + if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
40.397 + {
40.398 + SendNetlinkMessage(BuildAddressMessage(type, 0));
40.399 + }
40.400 + else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE)
40.401 + {
40.402 + SendNetlinkMessage(BuildRouteMessage(type, 0));
40.403 + }
40.404 + else
40.405 + {
40.406 + NS_LOG_ERROR("netlink cmd not support , type = " << type);
40.407 + }
40.408 +}
40.409 +
40.410 +
40.411 +void
40.412 +NetlinkSocketTest::ReceiveUnicastPacket (Ptr<Socket> socket)
40.413 +{
40.414 + Ptr<Packet> packet;
40.415 + while (packet = socket->Recv ())
40.416 + {
40.417 + MultipartNetlinkMessage nlmsg;
40.418 + packet->RemoveHeader(nlmsg);
40.419 + m_unicastList.push_back(nlmsg);
40.420 + }
40.421 +}
40.422 +
40.423 +void
40.424 +NetlinkSocketTest::ReceiveMulticastPacket(Ptr<Socket> socket)
40.425 +{
40.426 + Ptr<Packet> packet;
40.427 + while (packet = socket->Recv ())
40.428 + {
40.429 + MultipartNetlinkMessage nlmsg;
40.430 + packet->RemoveHeader(nlmsg);
40.431 + m_multicastList.push_back(nlmsg);
40.432 + }
40.433 +}
40.434 +void
40.435 +NetlinkSocketTest::MonitorKernelChanges()
40.436 +{
40.437 + NS_LOG_INFO("At = " << Simulator::Now ().GetSeconds () << "s, group socket check the recv list");
40.438 +
40.439 + if (m_multicastList.size())
40.440 + {
40.441 + MultipartNetlinkMessage multinlmsg = m_multicastList.front();
40.442 +
40.443 + if (multinlmsg.GetNMessages() == 1)
40.444 + {
40.445 + NetlinkMessage nlmsg = multinlmsg.GetMessage(0);
40.446 + uint16_t type = nlmsg.GetMsgType();
40.447 + NS_ASSERT(type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR
40.448 + || type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE);
40.449 + NS_LOG_INFO("group socket recv netlink message, type =" << type);
40.450 + }
40.451 + else
40.452 + {
40.453 + NS_LOG_WARN("group socket recv an unwanted message");
40.454 + }
40.455 + m_multicastList.pop_front();
40.456 + }
40.457 +
40.458 + //restart this timer
40.459 + if (Simulator::Now ().GetSeconds () < 10)
40.460 + Simulator::Schedule (Seconds (1), &NetlinkSocketTest::MonitorKernelChanges, this);
40.461 +}
40.462 +
40.463 +
40.464 +
40.465 +
40.466 +NetlinkSocketTest::NetlinkSocketTest ()
40.467 +: Test ("Netlink"), m_pid(1) {}
40.468 +
40.469 +bool
40.470 +NetlinkSocketTest::RunTests (void)
40.471 +{
40.472 + bool result = true;
40.473 +
40.474 + //init nodes with stacks and device
40.475 + // Network topology
40.476 + //
40.477 + // n0
40.478 + // \ 5 Mb/s, 2ms
40.479 + // \ 1.5Mb/s, 10ms
40.480 + // n1 -------------------------n2
40.481 +
40.482 +
40.483 + NodeContainer nodes;
40.484 + nodes.Create (3);
40.485 + NodeContainer n0n1 = NodeContainer (nodes.Get(0), nodes.Get(1));
40.486 + NodeContainer n1n2 = NodeContainer (nodes.Get(1), nodes.Get(2));
40.487 +
40.488 + InternetStackHelper stack;
40.489 + stack.Install (nodes);
40.490 +
40.491 + NetlinkSocketHelper netlink;
40.492 + netlink.Install(nodes);
40.493 +
40.494 + //add a p2p device with an ip address
40.495 + PointToPointHelper p2p;
40.496 + p2p.SetDeviceAttribute("DataRate", StringValue ("5Mbps"));
40.497 + p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
40.498 + NetDeviceContainer d0d1 = p2p.Install (n0n1);
40.499 + p2p.SetDeviceAttribute ("DataRate", StringValue ("1.5Mbps"));
40.500 + p2p.SetChannelAttribute ("Delay", StringValue ("10ms"));
40.501 + NetDeviceContainer d1d2 = p2p.Install (n1n2);
40.502 +
40.503 + Ipv4AddressHelper ipv4;
40.504 + ipv4.SetBase ("10.1.1.0", "255.255.255.0");
40.505 + Ipv4InterfaceContainer i01 = ipv4.Assign (d0d1);
40.506 + ipv4.SetBase ("10.1.2.0", "255.255.255.0");
40.507 + Ipv4InterfaceContainer i12 = ipv4.Assign (d1d2);
40.508 +
40.509 + GlobalRouteManager::PopulateRoutingTables ();
40.510 +
40.511 +
40.512 + /*create two netlink sockets in node1
40.513 + one is to exchange information between userspace and kernel ,
40.514 + one is to monitor the changes happened in kernel
40.515 + */
40.516 + Ptr<Node>node0 = nodes.Get(1);
40.517 + TypeId tid = TypeId::LookupByName ("ns3::NetlinkSocketFactory");
40.518 + Ptr<SocketFactory> socketFactory = node0->GetObject<SocketFactory> (tid);
40.519 + NetlinkSocketAddress addr;
40.520 +
40.521 + /*creat an cmd netlink socket, it send cmd to kernel space*/
40.522 + m_cmdSock = socketFactory->CreateSocket ();
40.523 + m_cmdSock->SetRecvCallback (MakeCallback (&NetlinkSocketTest::ReceiveUnicastPacket, this));
40.524 + addr.SetProcessID(m_pid);
40.525 + addr.SetGroupsMask(0);
40.526 + m_cmdSock->Bind(addr);
40.527 +
40.528 + /*creat an group netlink socket, it monitor the kernel's changes*/
40.529 + m_groupSock = socketFactory->CreateSocket ();
40.530 + m_groupSock->SetRecvCallback (MakeCallback (&NetlinkSocketTest::ReceiveMulticastPacket, this));
40.531 + addr.SetProcessID(m_pid + 1);
40.532 + addr.SetGroupsMask(NETLINK_RTM_GRP_IPV4_IFADDR|NETLINK_RTM_GRP_IPV4_ROUTE);
40.533 + m_groupSock->Bind(addr);
40.534 +
40.535 + /*test 1: for Serialize and Deserialize*/
40.536 + NS_TEST_ASSERT_EQUAL(TestNetlinkSerilization(), true);
40.537 +
40.538 + /*test 2: for interface address dump/add/get message*/
40.539 + NS_TEST_ASSERT_EQUAL(TestInterfaceAddressMessage(), true);
40.540 +
40.541 + /*test 3: for interface info dump message*/
40.542 + NS_TEST_ASSERT_EQUAL(TestInferfaceInfoMessage(), true);
40.543 +
40.544 + /*test 4: for route dump/add/get message*/
40.545 + NS_TEST_ASSERT_EQUAL(TestRouteMessage(), true);
40.546 +
40.547 + /*test 5: for netlink broadcast */
40.548 + NS_TEST_ASSERT_EQUAL(TestBroadcastMessage(), true);
40.549 +
40.550 + Simulator::Run ();
40.551 +
40.552 + return result;
40.553 +}
40.554 +
40.555 +static NetlinkSocketTest g_netlinkTest;
40.556 +
40.557 +#endif /* RUN_SELF_TESTS */
40.558 +
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/src/node/netlink-socket.cc Thu Oct 01 23:37:18 2009 +0900
41.3 @@ -0,0 +1,1505 @@
41.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
41.5 +/*
41.6 +* Copyright (c) 2008 Liu Jian
41.7 +*
41.8 +* This program is free software; you can redistribute it and/or modify
41.9 +* it under the terms of the GNU General Public License version 2 as
41.10 +* published by the Free Software Foundation;
41.11 +*
41.12 +* This program is distributed in the hope that it will be useful,
41.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
41.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41.15 +* GNU General Public License for more details.
41.16 +*
41.17 +* You should have received a copy of the GNU General Public License
41.18 +* along with this program; if not, write to the Free Software
41.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41.20 +*
41.21 +* Author: Liu Jian <liujatp@gmail.com>
41.22 +*/
41.23 +
41.24 +#include "ns3/netlink-socket.h"
41.25 +#include "ns3/netlink-socket-address.h"
41.26 +#include "ns3/netlink-message.h"
41.27 +#include "ns3/netlink-message-route.h"
41.28 +#include "ns3/netlink-ipv6-routing-table.h"
41.29 +#include "ns3/log.h"
41.30 +#include "ns3/node.h"
41.31 +#include "ns3/packet.h"
41.32 +#include "ns3/ipv4-address.h"
41.33 +#include "ns3/ipv4.h"
41.34 +#include "ns3/simple-net-device.h"
41.35 +#include "ns3/uinteger.h"
41.36 +#include "ns3/trace-source-accessor.h"
41.37 +#include <iostream>
41.38 +#include <sstream>
41.39 +#include "ns3/ipv6-address.h"
41.40 +#include "ns3/ipv6.h"
41.41 +#include "ns3/ipv4-l3-protocol.h"
41.42 +#include "ns3/ipv4-static-routing-helper.h"
41.43 +#include "ns3/ipv4-routing-table-entry.h"
41.44 +#include "ns3/ipv6-l3-protocol.h"
41.45 +#include "ns3/ipv6-interface.h"
41.46 +#include "ns3/ipv6-static-routing-helper.h"
41.47 +#include "ns3/ipv6-routing-table-entry.h"
41.48 +#include "ns3/socket.h"
41.49 +#include "ns3/mac48-address.h"
41.50 +#include <sys/socket.h>
41.51 +#include <linux/if.h>
41.52 +#include <errno.h>
41.53 +
41.54 +NS_LOG_COMPONENT_DEFINE ("NetlinkSocket");
41.55 +
41.56 +namespace ns3 {
41.57 +
41.58 + /*
41.59 + GroupSockets store the netlinksocket with noero group value
41.60 + it was due to the mulitcast netlink messages.
41.61 + */
41.62 +class GroupSockets
41.63 +{
41.64 +public:
41.65 + static uint32_t GetNSockets(void)
41.66 + {
41.67 + return m_Sockets.size();
41.68 + }
41.69 + static Ptr<NetlinkSocket> GetSocket(uint32_t index)
41.70 + {
41.71 + NS_ASSERT(index < m_Sockets.size());
41.72 + return m_Sockets[index];
41.73 + }
41.74 + static void AddSocket(Ptr<NetlinkSocket>sock)
41.75 + {
41.76 + m_Sockets.push_back(sock);
41.77 + }
41.78 +private:
41.79 + /*use a std::vector to store the sockets with nozero group value*/
41.80 + static std::vector<Ptr<NetlinkSocket> >m_Sockets;
41.81 +};
41.82 +std::vector<Ptr<NetlinkSocket> >GroupSockets::m_Sockets;
41.83 +
41.84 +
41.85 +/*
41.86 +Netlink Socket
41.87 +*/
41.88 +TypeId
41.89 +NetlinkSocket::GetTypeId (void)
41.90 +{
41.91 + static TypeId tid = TypeId ("ns3::NetlinkSocket")
41.92 + .SetParent<Socket> ()
41.93 + .AddConstructor<NetlinkSocket> ()
41.94 + .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
41.95 + MakeTraceSourceAccessor (&NetlinkSocket::m_dropTrace))
41.96 + .AddAttribute ("RcvBufSize",
41.97 + "NetlinkSocket maximum receive buffer size (bytes)",
41.98 + UintegerValue (0xffffffffl),
41.99 + MakeUintegerAccessor (&NetlinkSocket::m_rcvBufSize),
41.100 + MakeUintegerChecker<uint32_t> ())
41.101 + .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
41.102 + CallbackValue (),
41.103 + MakeCallbackAccessor (&NetlinkSocket::m_icmpCallback),
41.104 + MakeCallbackChecker ())
41.105 + ;
41.106 + return tid;
41.107 +}
41.108 +NetlinkSocket::NetlinkSocket ()
41.109 +: m_shutdownSend(false),m_shutdownRecv(false),m_rxAvailable(0),
41.110 + m_srcPid(0),m_srcGroups(0), m_dstPid(0),m_dstGroups(0)
41.111 +{
41.112 + NS_LOG_FUNCTION_NOARGS ();
41.113 + m_errno = ERROR_NOTERROR;
41.114 +}
41.115 +
41.116 +int
41.117 +NetlinkSocket::ErrnoToSimuErrno (void)
41.118 +{
41.119 + switch (m_errno) {
41.120 + case Socket::ERROR_ISCONN:
41.121 + return EISCONN;
41.122 + case Socket::ERROR_NOTCONN:
41.123 + return ENOTCONN;
41.124 + case Socket::ERROR_MSGSIZE:
41.125 + return EMSGSIZE;
41.126 + case Socket::ERROR_AGAIN:
41.127 + return EAGAIN;
41.128 + case Socket::ERROR_SHUTDOWN:
41.129 + return ESHUTDOWN;
41.130 + case Socket::ERROR_OPNOTSUPP:
41.131 + return EOPNOTSUPP;
41.132 + case Socket::ERROR_AFNOSUPPORT:
41.133 + return EAFNOSUPPORT;
41.134 + case Socket::ERROR_INVAL:
41.135 + return EINVAL;
41.136 + case Socket::ERROR_BADF:
41.137 + return EBADF;
41.138 + case Socket::ERROR_NOROUTETOHOST:
41.139 + return EHOSTUNREACH;
41.140 + case Socket::ERROR_NODEV:
41.141 + return ENODEV;
41.142 + case Socket::ERROR_ADDRNOTAVAIL:
41.143 + return EADDRNOTAVAIL;
41.144 + case Socket::SOCKET_ERRNO_LAST:
41.145 + case Socket::ERROR_NOTERROR:
41.146 + default:
41.147 + NS_ASSERT (false);
41.148 + return 0; // quiet compiler
41.149 + break;
41.150 + }
41.151 +}
41.152 +
41.153 +void
41.154 +NetlinkSocket::SetNode (Ptr<Node> node)
41.155 +{
41.156 + NS_LOG_FUNCTION_NOARGS ();
41.157 + m_node = node;
41.158 +}
41.159 +
41.160 +NetlinkSocket::~NetlinkSocket ()
41.161 +{
41.162 + NS_LOG_FUNCTION_NOARGS ();
41.163 +}
41.164 +
41.165 +void
41.166 +NetlinkSocket::DoDispose (void)
41.167 +{
41.168 + NS_LOG_FUNCTION_NOARGS ();
41.169 +}
41.170 +
41.171 +enum Socket::SocketErrno
41.172 +NetlinkSocket::GetErrno (void) const
41.173 +{
41.174 + NS_LOG_FUNCTION_NOARGS ();
41.175 + return m_errno;
41.176 +}
41.177 +
41.178 +Ptr<Node>
41.179 +NetlinkSocket::GetNode (void) const
41.180 +{
41.181 + NS_LOG_FUNCTION_NOARGS ();
41.182 + return m_node;
41.183 +}
41.184 +
41.185 +uint32_t
41.186 +NetlinkSocket::GetSrcPid(void) const
41.187 +{
41.188 + NS_LOG_FUNCTION_NOARGS ();
41.189 + return m_srcPid;
41.190 +}
41.191 +uint32_t
41.192 +NetlinkSocket::GetSrcGroups(void)const
41.193 +{
41.194 + NS_LOG_FUNCTION_NOARGS ();
41.195 + return m_srcGroups;
41.196 +}
41.197 +uint32_t
41.198 +NetlinkSocket::GetDstPid(void) const
41.199 +{
41.200 + NS_LOG_FUNCTION_NOARGS ();
41.201 + return m_dstPid;
41.202 +}
41.203 +uint32_t
41.204 +NetlinkSocket::GetDstGroups(void)const
41.205 +{
41.206 + NS_LOG_FUNCTION_NOARGS ();
41.207 + return m_dstGroups;
41.208 +}
41.209 +int
41.210 +NetlinkSocket::Bind (void)
41.211 +{
41.212 + NS_LOG_FUNCTION_NOARGS ();
41.213 + NetlinkSocketAddress address;
41.214 + return DoBind (address);
41.215 +}
41.216 +
41.217 +int
41.218 +NetlinkSocket::Bind (const Address &address)
41.219 +{
41.220 + NS_LOG_FUNCTION (this << address);
41.221 +
41.222 + if (!NetlinkSocketAddress::IsMatchingType (address))
41.223 + {
41.224 + m_errno = ERROR_INVAL;
41.225 + return -1;
41.226 + }
41.227 + NetlinkSocketAddress ad = NetlinkSocketAddress::ConvertFrom (address);
41.228 +
41.229 + return DoBind (ad);
41.230 +}
41.231 +
41.232 +int
41.233 +NetlinkSocket::DoBind (const NetlinkSocketAddress &address)
41.234 +{
41.235 + NS_LOG_FUNCTION (this << address);
41.236 +
41.237 + m_srcPid = address.GetProcessID ();
41.238 + m_srcGroups = address.GetGroupsMask ();
41.239 +
41.240 + if (m_srcGroups)
41.241 + {
41.242 + GroupSockets::AddSocket(this);
41.243 + }
41.244 +
41.245 + return 0;
41.246 +}
41.247 +int
41.248 +NetlinkSocket::Listen(void)
41.249 +{
41.250 + NS_LOG_FUNCTION_NOARGS ();
41.251 + m_errno = Socket::ERROR_OPNOTSUPP;
41.252 + return -1;
41.253 +}
41.254 +uint32_t
41.255 +NetlinkSocket::GetTxAvailable(void) const
41.256 +{
41.257 + NS_LOG_FUNCTION_NOARGS ();
41.258 + return 0;
41.259 +}
41.260 +uint32_t
41.261 +NetlinkSocket::GetRxAvailable(void) const
41.262 +{
41.263 + NS_LOG_FUNCTION_NOARGS ();
41.264 + // We separately maintain this state to avoid walking the queue
41.265 + // every time this might be called
41.266 + return m_rxAvailable;
41.267 +}
41.268 +int
41.269 +NetlinkSocket::ShutdownSend (void)
41.270 +{
41.271 + NS_LOG_FUNCTION_NOARGS ();
41.272 +
41.273 + m_shutdownSend = true;
41.274 +
41.275 + return 0;
41.276 +}
41.277 +
41.278 +int
41.279 +NetlinkSocket::ShutdownRecv (void)
41.280 +{
41.281 + NS_LOG_FUNCTION_NOARGS ();
41.282 +
41.283 + m_shutdownRecv = true;
41.284 +
41.285 + return 0;
41.286 +}
41.287 +
41.288 +int
41.289 +NetlinkSocket::Close (void)
41.290 +{
41.291 + NS_LOG_FUNCTION_NOARGS ();
41.292 +
41.293 + ShutdownSend();
41.294 + ShutdownRecv();
41.295 +
41.296 + return 0;
41.297 +}
41.298 +
41.299 +int
41.300 +NetlinkSocket::Connect (const Address &address)
41.301 +{
41.302 + NS_LOG_FUNCTION (this << address);
41.303 + m_errno = Socket::ERROR_OPNOTSUPP;
41.304 + return 0;
41.305 +}
41.306 +Ptr<Packet>
41.307 +NetlinkSocket::Recv (uint32_t maxSize, uint32_t flags)
41.308 +{
41.309 + NS_LOG_FUNCTION (this << maxSize<< flags);
41.310 + if (m_dataReceiveQueue.empty() )
41.311 + {
41.312 + return 0;
41.313 + }
41.314 +
41.315 + Ptr<Packet> p = m_dataReceiveQueue.front ();
41.316 + if (p->GetSize () <= maxSize)
41.317 + {
41.318 + m_dataReceiveQueue.pop ();
41.319 + m_rxAvailable -= p->GetSize ();
41.320 + }
41.321 + else
41.322 + {
41.323 + p = 0;
41.324 + }
41.325 +
41.326 + return p;
41.327 +}
41.328 +
41.329 +Ptr<Packet>
41.330 +NetlinkSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
41.331 +{
41.332 + NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
41.333 + Ptr<Packet> packet = Recv (maxSize, flags);
41.334 + if (packet != 0)
41.335 + {
41.336 + SocketAddressTag tag;
41.337 + bool found;
41.338 + found = packet->FindFirstMatchingByteTag (tag);
41.339 + NS_ASSERT (found);
41.340 + fromAddress = tag.GetAddress ();
41.341 + }
41.342 + return packet;
41.343 +}
41.344 +
41.345 +int
41.346 +NetlinkSocket::Send (Ptr<Packet> p,uint32_t flags)
41.347 +{
41.348 + NS_LOG_FUNCTION (this << p << flags);
41.349 + NetlinkSocketAddress address = NetlinkSocketAddress(m_dstPid, m_dstGroups);
41.350 +
41.351 + return SendTo(p, flags, address);
41.352 +}
41.353 +
41.354 +int
41.355 +NetlinkSocket::SendTo(Ptr<Packet> p, uint32_t flags, const Address &toAddress)
41.356 +{
41.357 + NS_LOG_FUNCTION (this << p << flags << toAddress);
41.358 + NetlinkSocketAddress ad;
41.359 +
41.360 + if (!NetlinkSocketAddress::IsMatchingType (toAddress))
41.361 + {
41.362 + NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
41.363 + m_errno = ERROR_AFNOSUPPORT;
41.364 + return -1;
41.365 + }
41.366 + ad = NetlinkSocketAddress::ConvertFrom (toAddress);
41.367 + m_dstPid = ad.GetProcessID();
41.368 + m_dstGroups = ad.GetGroupsMask();
41.369 + NS_LOG_INFO("send netlink message to pid = " << m_dstPid << ", groups = " << m_dstGroups);
41.370 +
41.371 + //Ptr<NetlinkSocket>kernel_socket = GetNetlinkSocketByAddress(ad);
41.372 + //kernel_socket->m_receivedData.push_back(p);
41.373 + //kernel_socket->NotifyDataReceived(p);
41.374 +
41.375 + //when netlink socket send packet, the first step is to find the dest netlink socket through address
41.376 + //then send the packet to it. For we partly implement the netlink-family, the dest address
41.377 + //is always the kernel(pid = 0), (Actually, there must be one static kernel netlink socket to
41.378 + //receive/handle messages), we do not setup a kernel socket to receive packet.
41.379 + //
41.380 +
41.381 + MultipartNetlinkMessage multipartnlmsg;
41.382 + uint32_t packet_len, remain_len;
41.383 +
41.384 + packet_len = p->GetSize ();
41.385 + remain_len = packet_len;
41.386 +
41.387 + while (remain_len > NetlinkMessageHeader::GetHeaderSize ())
41.388 + {
41.389 + remain_len -= p->RemoveHeader(multipartnlmsg);
41.390 + NS_ASSERT(remain_len == p->GetSize ());
41.391 +
41.392 + //actually, message to kernel contains single one netlink message
41.393 + for (uint32_t i = 0; i < multipartnlmsg.GetNMessages(); i ++)
41.394 + {
41.395 + NetlinkMessage nlmsg = multipartnlmsg.GetMessage (i);
41.396 +
41.397 + if (HandleMessage (nlmsg) < 0)
41.398 + {
41.399 + if (m_errno)
41.400 + SendAckMessage (nlmsg, -ErrnoToSimuErrno());
41.401 + }
41.402 + else if (NetlinkMessage::IsMessageFlagsAck(nlmsg.GetHeader().GetMsgFlags()))
41.403 + {
41.404 + SendAckMessage (nlmsg, 0);
41.405 + }
41.406 + }
41.407 + }
41.408 +
41.409 + NotifyDataSent (packet_len);
41.410 + NS_LOG_INFO("netlink socket kernel error " << -m_errno);
41.411 + return packet_len;
41.412 +}
41.413 +
41.414 +int
41.415 +NetlinkSocket::GetSockName (Address &address) const
41.416 +{
41.417 + NS_LOG_FUNCTION_NOARGS ();
41.418 + NetlinkSocketAddress ad;
41.419 +
41.420 + ad.SetProcessID(GetSrcPid());
41.421 + ad.SetGroupsMask(GetSrcGroups());
41.422 + address = ad;
41.423 + return 0;
41.424 +}
41.425 +
41.426 +
41.427 +
41.428 +
41.429 +
41.430 +
41.431 +
41.432 +void
41.433 +NetlinkSocket::ForwardUp (Ptr<Packet> packet, NetlinkSocketAddress &address)
41.434 +{
41.435 + NS_LOG_FUNCTION (this << packet << address);
41.436 +
41.437 + if (m_shutdownRecv)
41.438 + {
41.439 + return;
41.440 + }
41.441 + if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
41.442 + {
41.443 + SocketAddressTag tag;
41.444 + tag.SetAddress (address);
41.445 + packet->AddByteTag (tag);
41.446 + m_dataReceiveQueue.push (packet);
41.447 + m_rxAvailable += packet->GetSize ();
41.448 + NotifyDataRecv ();
41.449 + }
41.450 + else
41.451 + {
41.452 + NS_LOG_WARN ("No receive buffer space available. Drop.");
41.453 + m_dropTrace (packet);
41.454 + }
41.455 +}
41.456 +
41.457 +
41.458 +
41.459 +
41.460 +
41.461 +
41.462 +
41.463 +
41.464 +
41.465 +int32_t
41.466 +NetlinkSocket::SendMessageUnicast (const MultipartNetlinkMessage&nlmsg, uint32_t pid, int32_t nonblock)
41.467 +{
41.468 + NS_LOG_FUNCTION (this << pid << nonblock);
41.469 + //here we send message instantly
41.470 + Ptr<Packet> p = Create<Packet> ();
41.471 + p->AddHeader (nlmsg);
41.472 +
41.473 + NetlinkSocketAddress address;
41.474 + address.SetProcessID(pid);
41.475 +
41.476 + //send packet to user space
41.477 + ForwardUp(p, address);
41.478 +
41.479 + return 0;
41.480 +}
41.481 +
41.482 +int32_t
41.483 +NetlinkSocket::SendMessageBroadcast (const MultipartNetlinkMessage&nlmsg,
41.484 + uint32_t pid,
41.485 + uint32_t group,
41.486 + Ptr<Node> node)
41.487 +{
41.488 + NS_LOG_FUNCTION ("SendMessageBroadcast" << pid << group);
41.489 + //fisrt find the dest netlink socket through group value, then attach this nlmsg to its recv-queue
41.490 + for (uint32_t i = 0; i < GroupSockets::GetNSockets(); i ++)
41.491 + {
41.492 + Ptr<NetlinkSocket> nlsock = GroupSockets::GetSocket(i);
41.493 +
41.494 + if ((nlsock->GetSrcGroups()&group) &&
41.495 + (nlsock->GetSrcPid() != pid) &&
41.496 + node == nlsock->GetNode())
41.497 + {
41.498 + //here we send message instantly
41.499 + Ptr<Packet> p = Create<Packet> ();
41.500 + p->AddHeader (nlmsg);
41.501 +
41.502 + NetlinkSocketAddress address;
41.503 + address.SetProcessID(nlsock->GetSrcPid());
41.504 + address.SetGroupsMask(group);
41.505 +
41.506 + //send packet to user space
41.507 + nlsock->ForwardUp(p, address);
41.508 + }
41.509 + }
41.510 + return 0;
41.511 +}
41.512 +void
41.513 +NetlinkSocket::SendAckMessage (const NetlinkMessage&nlmsg, int32_t err)
41.514 +{
41.515 + NS_LOG_FUNCTION (this << err);
41.516 + NetlinkMessageHeader rep;
41.517 + NetlinkMessage ackmsg;
41.518 + NetlinkMessageError errmsg;
41.519 +
41.520 + rep.SetMsgPid(nlmsg.GetHeader().GetMsgPid());
41.521 + rep.SetMsgSeq(nlmsg.GetHeader().GetMsgSeq());
41.522 + rep.SetMsgType (NETLINK_MSG_ERROR);
41.523 + rep.SetMsgFlags(0);
41.524 +
41.525 + errmsg.SetError(err);
41.526 + //kernel send the whole nlmsg back if error != 0, here we just send the header back
41.527 + errmsg.SetMsg(nlmsg.GetHeader());
41.528 +
41.529 + //then send errmsg back to user space
41.530 + ackmsg.SetHeader(rep);
41.531 + ackmsg.SetErrorMessage (errmsg);
41.532 +
41.533 + SendMessageUnicast (ackmsg, rep.GetMsgPid(), 1);
41.534 +}
41.535 +
41.536 +int32_t
41.537 +NetlinkSocket::HandleMessage (const NetlinkMessage&nlmsg)
41.538 +{
41.539 + NS_LOG_FUNCTION (this);
41.540 + uint16_t type = nlmsg.GetMsgType ();
41.541 + NetlinkMessageHeader nhr = nlmsg.GetHeader();
41.542 +
41.543 + if (nhr.GetMsgLen() < NetlinkMessageHeader::GetHeaderSize ())
41.544 + {
41.545 + m_errno = ERROR_INVAL;
41.546 + return -1;
41.547 + }
41.548 +
41.549 + if (NetlinkMessage::IsMessageNetlinkControl (type))
41.550 + {
41.551 + NS_LOG_INFO("netlink control message type not parsed in kernel");
41.552 + return 0;
41.553 + }
41.554 + else if (NetlinkMessage::IsMessageNetlinkRoute (type))
41.555 + {
41.556 + return HandleNetlinkRouteMessage (nlmsg);
41.557 + }
41.558 + else
41.559 + {
41.560 + NS_LOG_INFO("netlink message type not parsed in kernel");
41.561 + m_errno = ERROR_INVAL;
41.562 + return -1;
41.563 + }
41.564 +}
41.565 +
41.566 +
41.567 +int32_t
41.568 +NetlinkSocket::HandleNetlinkRouteMessage (const NetlinkMessage&nlmsg)
41.569 +{
41.570 + NS_LOG_FUNCTION (this);
41.571 + uint8_t family;
41.572 + int16_t type;
41.573 + int32_t err;
41.574 +
41.575 + /* Only requests are handled by kernel now */
41.576 + if (!NetlinkMessage::IsMessageFlagsRequest(nlmsg.GetHeader().GetMsgFlags()))
41.577 + return 0;
41.578 +
41.579 + type = nlmsg.GetMsgType ();
41.580 +
41.581 + /* A control message: ignore them */
41.582 + if (NetlinkMessage::IsMessageNetlinkControl(type))
41.583 + {
41.584 + return 0;
41.585 + }
41.586 + else if (NetlinkMessage::IsMessageNetlinkRoute(type))
41.587 + {
41.588 + /* All the messages must have at least 1 byte length */
41.589 + if (nlmsg.GetPayloadSize () < 1)
41.590 + return 0;
41.591 +
41.592 + family = nlmsg.GetFamily();
41.593 + /*here we do not deal with different family, default for AF_NET*/
41.594 + NS_ASSERT(family == AF_INET || family == AF_UNSPEC || family == 17 || family == AF_INET6);
41.595 +
41.596 + /*for GET*** message, dump it to userspace*/
41.597 + if (NetlinkMessage::IsMessageTypeGet(type) && NetlinkMessage::IsMessageFlagsDump(nlmsg.GetHeader().GetMsgFlags()))
41.598 + {
41.599 + DumpNetlinkRouteMessage (nlmsg, type, family);
41.600 + return -1;
41.601 + }
41.602 +
41.603 + /* other types of messages*/
41.604 + return DoNetlinkRouteMessage (nlmsg, type, family);
41.605 + }
41.606 + else/* Unknown message: reply with EINVAL */
41.607 + {
41.608 + err = ERROR_INVAL;
41.609 + return -1;
41.610 + }
41.611 +}
41.612 +
41.613 +
41.614 +
41.615 +
41.616 +int32_t
41.617 +NetlinkSocket::DumpNetlinkRouteMessage (const NetlinkMessage&nlmsg, uint16_t type, uint8_t family)
41.618 +{
41.619 + NS_LOG_FUNCTION (this << type << family);
41.620 + /*the family default value was AF_INET*/
41.621 +
41.622 + NS_ASSERT(type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE || NETLINK_RTM_GETLINK);
41.623 +
41.624 + MultipartNetlinkMessage nlmsg_dump;
41.625 + NetlinkMessageHeader nhr = nlmsg.GetHeader();
41.626 + int32_t err;
41.627 +
41.628 + if (type == NETLINK_RTM_GETADDR)
41.629 + {
41.630 + nlmsg_dump = BuildInterfaceAddressDumpMessage(m_srcPid, nhr.GetMsgSeq(), family);
41.631 + }
41.632 + else if (type == NETLINK_RTM_GETLINK)
41.633 + {
41.634 + nlmsg_dump = BuildInterfaceInfoDumpMessage(m_srcPid, nhr.GetMsgSeq(), family);
41.635 + }
41.636 + else if (type == NETLINK_RTM_GETROUTE)
41.637 + {
41.638 + nlmsg_dump = BuildRouteDumpMessage(m_srcPid, nhr.GetMsgSeq(), family);
41.639 + }
41.640 + else
41.641 + {
41.642 + m_errno = ERROR_INVAL;
41.643 + return -1;
41.644 + }
41.645 +
41.646 + //then append netlink message with type NLMSG_DONE
41.647 + {
41.648 + NetlinkMessage nlmsg_done;
41.649 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, nlmsg.GetHeader().GetMsgSeq(), m_srcPid);
41.650 + nlmsg_done.SetHeader(nhr);
41.651 + //kernel append nlmsg_dump size to it, here we omit it
41.652 + nlmsg_dump.AppendMessage (nlmsg_done);
41.653 + }
41.654 +
41.655 + err = SendMessageUnicast (nlmsg_dump, m_srcPid, 1);
41.656 +
41.657 + return err;
41.658 +}
41.659 +
41.660 +
41.661 +/*here only for ADD/DEL/GET*** types*/
41.662 +int32_t
41.663 +NetlinkSocket::DoNetlinkRouteMessage (const NetlinkMessage&nlmsg, uint16_t type, uint8_t family)
41.664 +{
41.665 + /*the family default value was AF_INET*/
41.666 + NS_LOG_FUNCTION (this << type <<family);
41.667 + int32_t err;
41.668 +
41.669 + if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
41.670 + {
41.671 + err = DoInterfaceAddressMessage(nlmsg, type, family);
41.672 + }
41.673 + else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
41.674 + {
41.675 + err = DoRouteMessage(nlmsg, type, family);
41.676 + }
41.677 + else if (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK)
41.678 + {
41.679 + err = DoInterfaceInfoMessage(nlmsg, type, family);
41.680 + }
41.681 + else
41.682 + {
41.683 + NS_LOG_LOGIC ("netlink message:type( " << type << ") not processed by kns3 now." );
41.684 + m_errno = ERROR_INVAL;
41.685 + err = -1;
41.686 + }
41.687 +
41.688 + return err;
41.689 +}
41.690 +
41.691 +
41.692 +MultipartNetlinkMessage
41.693 +NetlinkSocket::BuildInterfaceAddressDumpMessage(uint32_t pid, uint32_t seq, uint8_t family)
41.694 +{
41.695 + NS_LOG_FUNCTION (this << pid << seq <<family);
41.696 + /*the family default value was AF_INET*/
41.697 + MultipartNetlinkMessage nlmsg_dump;
41.698 + Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
41.699 +
41.700 + for (uint32_t i = 0; i < ipv4->GetNInterfaces(); i ++)
41.701 + {
41.702 + if (!ipv4->IsUp (i))
41.703 + continue;
41.704 +
41.705 + Ipv4Address addri = ipv4->GetAddress (i, 0).GetLocal();
41.706 + Ipv4Mask maski = ipv4->GetAddress (i, 0).GetMask ();
41.707 + Ipv4Address bcast = ipv4->GetAddress (i, 0).GetBroadcast();
41.708 +
41.709 + //loopback and broadcast address not dumped
41.710 + if (addri.IsEqual(Ipv4Address::GetLoopback()) || addri.IsBroadcast())
41.711 + continue;
41.712 +
41.713 + //here get the address mask length
41.714 + uint32_t mask = maski.Get();
41.715 + uint8_t mask_len = 0;
41.716 + while (mask)
41.717 + {
41.718 + mask = mask << 1;
41.719 + mask_len ++;
41.720 + }
41.721 +
41.722 + //next fill the message body
41.723 + NetlinkMessage nlmsg_ifa;
41.724 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
41.725 + InterfaceAddressMessage ifamsg;
41.726 +
41.727 + ifamsg.SetInterfaceIndex(i);
41.728 + ifamsg.SetFamily(PF_INET);//default AF_INET
41.729 + ifamsg.SetLength(mask_len);
41.730 + ifamsg.SetFlags(0);
41.731 + ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.732 +
41.733 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addri));
41.734 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addri));
41.735 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
41.736 + // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL, STRING, "ns3-ifaddr"));//not used in ns3
41.737 + //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST, ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
41.738 + //XXXother attributes not used by ns3
41.739 +
41.740 + nlmsg_ifa.SetHeader(nhr);
41.741 + nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
41.742 + nlmsg_dump.AppendMessage (nlmsg_ifa);
41.743 + }
41.744 +
41.745 + // For IPv6
41.746 + Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
41.747 +
41.748 + for (uint32_t i = 0; i < ipv6->GetNInterfaces(); i ++)
41.749 + {
41.750 + if (!ipv6->IsUp (i))
41.751 + continue;
41.752 +
41.753 + for (uint32_t j = 0; j < ipv6->GetNAddresses(i); j ++)
41.754 + {
41.755 + Ipv6Address addri = ipv6->GetAddress (i, j).GetAddress();
41.756 + Ipv6Prefix prefix = ipv6->GetAddress (i, j).GetPrefix ();
41.757 +
41.758 + //here get the address mask length
41.759 + uint8_t mask_len = prefix.PrefixLen();
41.760 +
41.761 + //loopback address's prefix is wrong... FIXME
41.762 + if (addri.IsEqual(Ipv6Address::GetLoopback()))
41.763 + mask_len = 128;
41.764 +
41.765 + //next fill the message body
41.766 + NetlinkMessage nlmsg_ifa;
41.767 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
41.768 + InterfaceAddressMessage ifamsg;
41.769 +
41.770 + ifamsg.SetInterfaceIndex(i);
41.771 + ifamsg.SetFamily(AF_INET6);
41.772 + ifamsg.SetFlags(0);
41.773 +
41.774 +
41.775 + if (addri.IsLinkLocal())
41.776 + {
41.777 + ifamsg.SetLength(64);
41.778 + ifamsg.SetScope (RouteMessage::RT_SCOPE_LINK);
41.779 + }
41.780 + else
41.781 + {
41.782 + ifamsg.SetLength(mask_len);
41.783 + ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.784 + }
41.785 +
41.786 +
41.787 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addri));
41.788 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addri));
41.789 + //XXXother attributes not used by ns3
41.790 +
41.791 + nlmsg_ifa.SetHeader(nhr);
41.792 + nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
41.793 + nlmsg_dump.AppendMessage (nlmsg_ifa);
41.794 + }
41.795 +
41.796 + }
41.797 +
41.798 + return nlmsg_dump;
41.799 +}
41.800 +MultipartNetlinkMessage
41.801 +NetlinkSocket::BuildInterfaceInfoDumpMessage(uint32_t pid, uint32_t seq, uint8_t family)
41.802 +{
41.803 + NS_LOG_FUNCTION (this << pid << seq <<family);
41.804 + /*the family default value was AF_INET*/
41.805 + MultipartNetlinkMessage nlmsg_dump;
41.806 + Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
41.807 +
41.808 + for (uint32_t i = 0; i < ipv6->GetNInterfaces(); i ++)
41.809 + {
41.810 + Ptr<NetDevice> nd = ipv6->GetNetDevice (i);
41.811 +
41.812 + Address mac;
41.813 + Address bcast;
41.814 + uint32_t mtu;
41.815 + uint32_t flags = 0;
41.816 +
41.817 + if(ipv6->IsUp(i))
41.818 + flags |= IFF_UP;
41.819 +
41.820 + if(nd){
41.821 + mac = nd->GetAddress();
41.822 + bcast = nd->GetBroadcast();
41.823 + mtu = (uint32_t)nd->GetMtu();
41.824 +
41.825 + if(nd->IsBroadcast())
41.826 + flags |= IFF_BROADCAST;
41.827 + if(nd->IsMulticast())
41.828 + flags |= IFF_MULTICAST;
41.829 + if(nd->IsLinkUp())
41.830 + flags |= IFF_RUNNING;
41.831 + }
41.832 + else{
41.833 + mac = bcast = Mac48Address("00:00:00:00:00:00");
41.834 + mtu = 16436;
41.835 + flags = IFF_UP|IFF_BROADCAST|IFF_MULTICAST|IFF_RUNNING;
41.836 + }
41.837 +
41.838 + NetlinkMessage nlmsg_ifinfo;
41.839 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWLINK, NETLINK_MSG_F_MULTI, seq, pid);
41.840 + InterfaceInfoMessage ifinfomsg;
41.841 +
41.842 + ifinfomsg.SetFamily(0);//AF_UNSPEC
41.843 + ifinfomsg.SetDeviceType (0);//not clear
41.844 + ifinfomsg.SetInterfaceIndex(i);
41.845 + ifinfomsg.SetDeviceFlags(flags);//not clear
41.846 + ifinfomsg.SetChangeMask(0xffffffff);
41.847 +
41.848 + // the ns3 device have no name, here we set "ns3-device i" for test
41.849 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_IFNAME, STRING, nd->GetName ()));
41.850 + std::stringstream ss;
41.851 + ss << "ns3-device" << i;
41.852 +
41.853 + ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_IFNAME, STRING, ss.str()));
41.854 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_TXQLEN, U32, 0));//not used in ns3
41.855 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_WEIGHT, U32, 0));//not used in ns3
41.856 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_OPERSTATE, U8, 0));//not used in ns3
41.857 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINKMODE, U8, 0));//not used in ns3
41.858 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MAP, UNSPEC, 0));//not used in ns3
41.859 + ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_ADDRESS, ADDRESS, mac));
41.860 + ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_BROADCAST, ADDRESS, bcast));
41.861 + ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MTU, U32, mtu));
41.862 + ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINK, U32, i));//not used in ns3
41.863 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_QDISC, STRING, ""));//not used in ns3
41.864 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MASTER, U32, 0));//not used in ns3
41.865 + //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_STATS, UNSPEC, 0));//not used in ns3
41.866 + //XXXother attributes not used by ns3
41.867 +
41.868 + nlmsg_ifinfo.SetHeader(nhr);
41.869 + nlmsg_ifinfo.SetInterfaceInfoMessage (ifinfomsg);
41.870 + nlmsg_dump.AppendMessage (nlmsg_ifinfo);
41.871 + }
41.872 +
41.873 + return nlmsg_dump;
41.874 +}
41.875 +MultipartNetlinkMessage
41.876 +NetlinkSocket::BuildRouteDumpMessage(uint32_t pid, uint32_t seq, uint8_t family)
41.877 +{
41.878 + NS_LOG_FUNCTION (this << pid << seq <<family);
41.879 + /*the family default value was AF_INET*/
41.880 + MultipartNetlinkMessage nlmsg_dump;
41.881 +
41.882 + Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
41.883 +
41.884 +#if 0
41.885 + Ptr<Ipv4RoutingProtocol> routing = ipv4->GetRoutingProtocol ();
41.886 + for (uint32_t i = 0; i < routing->GetNRoutes(); i ++)
41.887 + {
41.888 + NetlinkMessage nlmsg_rt;
41.889 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
41.890 + RouteMessage rtmsg;
41.891 + Ipv4RoutingTableEntry route = routing->GetRoute (i);
41.892 +
41.893 + if (route.GetDest().IsEqual(Ipv4Address::GetLoopback()))//ignore loopback route
41.894 + continue;
41.895 +
41.896 + rtmsg.SetFamily(PF_INET);//AF_INET
41.897 + rtmsg.SetDstLength(32);
41.898 + rtmsg.SetSrcLength(0);
41.899 + rtmsg.SetTos(0);//not clear
41.900 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.901 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.902 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.903 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.904 +
41.905 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.906 + //ns3 use local address as the route src address
41.907 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, route.GetSource ()));
41.908 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, route.GetSource()));//not used in ns3
41.909 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
41.910 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));
41.911 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
41.912 + //XXXother attributes not used by ns3
41.913 +
41.914 + nlmsg_rt.SetHeader(nhr);
41.915 + nlmsg_rt.SetRouteMessage (rtmsg);
41.916 + nlmsg_dump.AppendMessage (nlmsg_rt);
41.917 + }
41.918 +#endif
41.919 +
41.920 + // V4 static
41.921 + Ipv4StaticRoutingHelper routingHelper;
41.922 + Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
41.923 + for (uint32_t i = 0; i < ipv4Static->GetNRoutes(); i ++)
41.924 + {
41.925 + NetlinkMessage nlmsg_rt;
41.926 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
41.927 + RouteMessage rtmsg;
41.928 + Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
41.929 +
41.930 + if (route.GetDest().IsEqual(Ipv4Address::GetLoopback()))//ignore loopback route
41.931 + continue;
41.932 +
41.933 + rtmsg.SetFamily(PF_INET);//AF_INET
41.934 + rtmsg.SetDstLength(32);
41.935 + rtmsg.SetSrcLength(0);
41.936 + rtmsg.SetTos(0);//not clear
41.937 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.938 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.939 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.940 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.941 +
41.942 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.943 + //ns3 use local address as the route src address
41.944 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, route.GetSource()));
41.945 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, route.GetSource()));//not used in ns3
41.946 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
41.947 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));
41.948 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
41.949 + //XXXother attributes not used by ns3
41.950 +
41.951 + nlmsg_rt.SetHeader(nhr);
41.952 + nlmsg_rt.SetRouteMessage (rtmsg);
41.953 + nlmsg_dump.AppendMessage (nlmsg_rt);
41.954 + }
41.955 +
41.956 + Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
41.957 +#if 0
41.958 + for (uint32_t i = 0; i < ipv6->GetNRoutes(); i ++)
41.959 + {
41.960 + NetlinkMessage nlmsg_rt;
41.961 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
41.962 + RouteMessage rtmsg;
41.963 + Ipv6Route route = ipv6->GetRoute (i);
41.964 +
41.965 + if (route.GetDest().IsEqual(Ipv6Address::GetLoopback()))//ignore loopback route
41.966 + continue;
41.967 +
41.968 + rtmsg.SetFamily(AF_INET6);//AF_INET6
41.969 + rtmsg.SetDstLength(128);
41.970 + rtmsg.SetSrcLength(0);
41.971 + rtmsg.SetTos(0);//not clear
41.972 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.973 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.974 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.975 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.976 +
41.977 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.978 + //ns3 use local address as the route src address
41.979 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
41.980 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));//not used in ns3
41.981 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
41.982 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));
41.983 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
41.984 + //XXXother attributes not used by ns3
41.985 +
41.986 + nlmsg_rt.SetHeader(nhr);
41.987 + nlmsg_rt.SetRouteMessage (rtmsg);
41.988 + nlmsg_dump.AppendMessage (nlmsg_rt);
41.989 + }
41.990 +#endif
41.991 +
41.992 + // V6 static
41.993 + Ptr<NetlinkIpv6RoutingTable> ipv6Table = m_node->GetObject<NetlinkIpv6RoutingTable> ();
41.994 + for (uint32_t i = 0; i < ipv6Table->GetNRoutes(); i ++)
41.995 + {
41.996 + NetlinkMessage nlmsg_rt;
41.997 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
41.998 + RouteMessage rtmsg;
41.999 + Ipv6RoutingTableEntry route = ipv6Table->GetRoute (i);
41.1000 +
41.1001 + if (route.GetDest().IsEqual(Ipv6Address::GetLoopback()))//ignore loopback route
41.1002 + continue;
41.1003 +
41.1004 + rtmsg.SetFamily(AF_INET6);//AF_INET6
41.1005 + rtmsg.SetDstLength(128);
41.1006 + rtmsg.SetSrcLength(0);
41.1007 + rtmsg.SetTos(0);//not clear
41.1008 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.1009 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.1010 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.1011 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.1012 +
41.1013 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.1014 + //ns3 use local address as the route src address
41.1015 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
41.1016 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));//not used in ns3
41.1017 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
41.1018 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));
41.1019 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
41.1020 + //XXXother attributes not used by ns3
41.1021 +
41.1022 + nlmsg_rt.SetHeader(nhr);
41.1023 + nlmsg_rt.SetRouteMessage (rtmsg);
41.1024 + nlmsg_dump.AppendMessage (nlmsg_rt);
41.1025 + }
41.1026 +
41.1027 + return nlmsg_dump;
41.1028 +}
41.1029 +
41.1030 +
41.1031 +int32_t
41.1032 +NetlinkSocket::DoInterfaceAddressMessage(const NetlinkMessage&nlmsg, uint16_t type, uint8_t family)
41.1033 +{
41.1034 + NS_LOG_FUNCTION (this << type << family);
41.1035 + NS_ASSERT(type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
41.1036 +
41.1037 + InterfaceAddressMessage ifamsg = nlmsg.GetInterfaceAddressMessage ();
41.1038 + Ipv4Address addri, addr_local, bcast;
41.1039 + NetlinkAttribute attr_local;
41.1040 + uint32_t index = ifamsg.GetInterfaceIndex();
41.1041 + Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
41.1042 + int flag4 = 0, flag6 = 0;
41.1043 +
41.1044 + if (type == NETLINK_RTM_NEWADDR)
41.1045 + {
41.1046 + //when adding an interface address, it should check the input arguments
41.1047 + //prefix-len and local address attribute
41.1048 + if (ifamsg.GetLength() > 32 || ifamsg.GetAttributeByType(attr_local, InterfaceAddressMessage::IF_A_LOCAL) == false)
41.1049 + {
41.1050 + m_errno = ERROR_INVAL;
41.1051 + return -1;
41.1052 + }
41.1053 + }
41.1054 +
41.1055 + //get necessary information for add/del, many attributes we not used
41.1056 + for (uint32_t i = 0; i < ifamsg.GetNNetlinkAttribute (); i ++)
41.1057 + {
41.1058 + NetlinkAttribute attr = ifamsg.GetNetlinkAttribute (i);
41.1059 +
41.1060 + uint32_t attr_type = attr.GetAttrType ();
41.1061 +
41.1062 + switch(attr_type)
41.1063 + {
41.1064 + case InterfaceAddressMessage::IF_A_ADDRESS:
41.1065 + addri = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1066 + break;
41.1067 + case InterfaceAddressMessage::IF_A_BROADCAST:
41.1068 + bcast = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1069 + break;
41.1070 + case InterfaceAddressMessage::IF_A_LOCAL:
41.1071 + addr_local = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1072 + break;
41.1073 + case InterfaceAddressMessage::IF_A_LABEL:
41.1074 + case InterfaceAddressMessage::IF_A_ANYCAST:
41.1075 + break;
41.1076 + }
41.1077 + }
41.1078 +
41.1079 + if (type == NETLINK_RTM_NEWADDR)
41.1080 + {
41.1081 + //when adding an interface address by index, if the indexed interface was not exist,
41.1082 + //create an new NetDevice with an new index and set the address
41.1083 + //otherwise set the indexed interface directly
41.1084 + if (index >= ipv4->GetNInterfaces())
41.1085 + {
41.1086 + Ptr<SimpleNetDevice> dev;
41.1087 + dev = CreateObject<SimpleNetDevice> ();
41.1088 + dev ->SetAddress (Mac48Address::Allocate ());
41.1089 + m_node->AddDevice (dev);
41.1090 +
41.1091 + uint32_t netdev_idx = ipv4->AddInterface (dev);
41.1092 + // FIXME!
41.1093 + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask());
41.1094 + ipv4->AddAddress (netdev_idx, ipv4Addr);
41.1095 + ipv4->SetUp (netdev_idx);
41.1096 + NS_LOG_INFO("Add an interface address at index "<< netdev_idx << "but not the ifamsg input" << index);
41.1097 + }
41.1098 + else
41.1099 + {
41.1100 + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask());
41.1101 + ipv4->AddAddress (index, ipv4Addr);
41.1102 + if (!ipv4->IsUp (index))
41.1103 + ipv4->SetUp (index);
41.1104 + }
41.1105 + flag4 = 1;
41.1106 + }
41.1107 + else//type == NETLINK_RTM_DELADDR
41.1108 + {
41.1109 + //when delete an interface address by index, if the indexed interface was not exist
41.1110 + //return an error EINVAL, otherwise set down the interface which has the addri
41.1111 + if (index >= ipv4->GetNInterfaces())
41.1112 + {
41.1113 + m_errno = ERROR_NODEV;
41.1114 + return -1;
41.1115 + }
41.1116 + else
41.1117 + {
41.1118 + for (uint32_t i = 0; i < ipv4->GetNInterfaces(); i ++)
41.1119 + {
41.1120 + Ipv4Address ad = ipv4->GetAddress (i, 0).GetLocal ();
41.1121 +
41.1122 + if (ad == addri && ipv4->IsUp(i))
41.1123 + {
41.1124 + ipv4->SetDown(i);
41.1125 + break;
41.1126 + }
41.1127 +
41.1128 + if ( i == ipv4->GetNInterfaces() - 1)
41.1129 + {
41.1130 + m_errno = ERROR_ADDRNOTAVAIL;
41.1131 + return -1;
41.1132 + }
41.1133 + }
41.1134 + flag4 = 1;
41.1135 + }
41.1136 + }
41.1137 +
41.1138 + //then send an broadcast message, let all user know this operation happened
41.1139 + NetlinkMessage nlmsg_broadcast = nlmsg;
41.1140 + NetlinkMessageHeader nhr;
41.1141 + nhr.SetMsgLen(nlmsg.GetHeader().GetMsgLen());
41.1142 + nhr.SetMsgType(nlmsg.GetHeader().GetMsgType());
41.1143 + nlmsg_broadcast.SetHeader(nhr);
41.1144 + if(flag4)
41.1145 + SendMessageBroadcast(nlmsg_broadcast, 0, NETLINK_RTM_GRP_IPV4_IFADDR, GetNode());
41.1146 + else if(flag6)
41.1147 + SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_IFADDR, GetNode());
41.1148 +
41.1149 + return 0;
41.1150 +}
41.1151 +
41.1152 +int32_t
41.1153 +NetlinkSocket::DoInterfaceInfoMessage(const NetlinkMessage&nlmsg, uint16_t type, uint8_t family)
41.1154 +{
41.1155 + NS_LOG_FUNCTION (this << type << family);
41.1156 + NS_ASSERT(type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK);
41.1157 + InterfaceInfoMessage ifinfomsg = nlmsg.GetInterfaceInfoMessage();
41.1158 + //XXX
41.1159 + NS_LOG_INFO("ns3 not handle these types of messages.");
41.1160 + return -1;
41.1161 +}
41.1162 +int32_t
41.1163 +NetlinkSocket::DoRouteMessage(const NetlinkMessage&nlmsg, uint16_t type, uint8_t family)
41.1164 +{
41.1165 + NS_LOG_FUNCTION (this << type << family);
41.1166 + NS_ASSERT(type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE ||type == NETLINK_RTM_GETROUTE);
41.1167 +
41.1168 + RouteMessage rtmsg = nlmsg.GetRouteMessage ();
41.1169 + Ipv4Address src,dest,gateway;
41.1170 + Ipv6Address src6,dest6,gateway6;
41.1171 + uint32_t index;
41.1172 + int attr_flags[RouteMessage::RT_A_MAX] = {0};
41.1173 + uint8_t dstlen = rtmsg.GetDstLength();
41.1174 +
41.1175 + //get necessary information for add/del, many attributes we not used
41.1176 + for (uint32_t i = 0; i < rtmsg.GetNNetlinkAttribute (); i ++)
41.1177 + {
41.1178 + NetlinkAttribute attr = rtmsg.GetNetlinkAttribute (i);
41.1179 + uint32_t attr_type = attr.GetAttrType ();
41.1180 + attr_flags[attr_type] = 1;
41.1181 +
41.1182 +
41.1183 + switch(attr_type)
41.1184 + {
41.1185 + case RouteMessage::RT_A_DST:
41.1186 + if(family == AF_INET)
41.1187 + dest = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1188 + else if(family == AF_INET6)
41.1189 + dest6 = Ipv6Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1190 + break;
41.1191 + case RouteMessage::RT_A_SRC:
41.1192 + if(family == AF_INET)
41.1193 + src = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1194 + else if(family == AF_INET6)
41.1195 + src6 = Ipv6Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1196 + break;
41.1197 + case RouteMessage::RT_A_OIF:
41.1198 + index = attr.GetAttrPayload().GetU32();
41.1199 + break;
41.1200 + case RouteMessage::RT_A_GATEWAY:
41.1201 + if(family == AF_INET)
41.1202 + gateway = Ipv4Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1203 + else if(family == AF_INET6)
41.1204 + gateway6 = Ipv6Address::ConvertFrom(attr.GetAttrPayload().GetAddress());
41.1205 + break;
41.1206 + case RouteMessage::RT_A_IIF:
41.1207 + case RouteMessage::RT_A_PRIORITY:
41.1208 + case RouteMessage::RT_A_PREFSRC:
41.1209 + case RouteMessage::RT_A_METRICS:
41.1210 + case RouteMessage::RT_A_MULTIPATH:
41.1211 + case RouteMessage::RT_A_PROTOINFO:
41.1212 + case RouteMessage::RT_A_FLOW:
41.1213 + case RouteMessage::RT_A_CACHEINFO:
41.1214 + case RouteMessage::RT_A_SESSION:
41.1215 + case RouteMessage::RT_A_MP_ALGO:
41.1216 + case RouteMessage::RT_A_TABLE:
41.1217 + NS_LOG_INFO("route attribute not used by ns3" << attr_type);
41.1218 + //not used by ns3
41.1219 + break;
41.1220 + }
41.1221 + }
41.1222 +
41.1223 + // Sigh....
41.1224 + Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
41.1225 + Ipv4StaticRoutingHelper routingHelper;
41.1226 + Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
41.1227 +
41.1228 + Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
41.1229 + Ptr<NetlinkIpv6RoutingTable> ipv6Table = m_node->GetObject<NetlinkIpv6RoutingTable> ();
41.1230 +
41.1231 + if (type == NETLINK_RTM_NEWROUTE)
41.1232 + {
41.1233 + //ns3 add a route entry only depends on 2 or 3 attribute
41.1234 + //other route msg attibute were ignored
41.1235 + if (attr_flags[RouteMessage::RT_A_DST])
41.1236 + {
41.1237 + if(family == AF_INET){
41.1238 + if(!attr_flags[RouteMessage::RT_A_OIF]){
41.1239 + // FIXME
41.1240 +#if 0
41.1241 + if(ipv4->GetInterfaceForDestination(gateway, index) == false){
41.1242 + NS_LOG_INFO("No suitable interface to add an route entry");
41.1243 + m_errno = ERROR_ADDRNOTAVAIL;
41.1244 + return -1;
41.1245 + }
41.1246 +#endif
41.1247 + }
41.1248 +
41.1249 + if(dstlen == 32){
41.1250 + if (attr_flags[RouteMessage::RT_A_GATEWAY])
41.1251 + ipv4Static->AddHostRouteTo(dest, gateway, index);
41.1252 + else
41.1253 + ipv4Static->AddHostRouteTo(dest, index);
41.1254 + }
41.1255 + else{
41.1256 + // FIXME
41.1257 + if (attr_flags[RouteMessage::RT_A_GATEWAY])
41.1258 + ipv4Static->AddNetworkRouteTo(dest, Ipv4Mask (1), gateway, index);
41.1259 + else
41.1260 + ipv4Static->AddNetworkRouteTo(dest, Ipv4Mask (1), index);
41.1261 + }
41.1262 + }
41.1263 + else if(family == AF_INET6){
41.1264 + if(!attr_flags[RouteMessage::RT_A_OIF]){
41.1265 +#if 0
41.1266 + if(ipv6->GetIfIndexForDestination(gateway6, index) == false){
41.1267 + NS_LOG_INFO("No suitable interface to add an route entry");
41.1268 + m_errno = ERROR_ADDRNOTAVAIL;
41.1269 + return -1;
41.1270 + }
41.1271 +#endif
41.1272 + }
41.1273 +
41.1274 + Ipv6Prefix pref(dstlen);
41.1275 + if (attr_flags[RouteMessage::RT_A_GATEWAY])
41.1276 + ipv6Table->AddRouteTo (dest6, pref, gateway6, index);
41.1277 + else
41.1278 + ipv6Table->AddRouteTo (dest6, pref, Ipv6Address("::"), index);
41.1279 + }
41.1280 + }
41.1281 + else
41.1282 + {
41.1283 + NS_LOG_INFO("too few attributes to add an route entry");
41.1284 + m_errno = ERROR_INVAL;
41.1285 + return -1;
41.1286 + }
41.1287 + }
41.1288 + else if (type == NETLINK_RTM_DELROUTE)
41.1289 + {
41.1290 + if (attr_flags[RouteMessage::RT_A_DST])
41.1291 + {
41.1292 + int delete_flag = 0;
41.1293 +
41.1294 + if(family == AF_INET){
41.1295 + for (uint32_t i = 0; i < ipv4Static->GetNRoutes(); i ++)
41.1296 + {
41.1297 + Ipv4RoutingTableEntry rt = ipv4Static->GetRoute(i);
41.1298 +
41.1299 + if (gateway == rt.GetGateway() && dest == rt.GetDest())
41.1300 + {
41.1301 + ipv4Static->RemoveRoute(i);
41.1302 + delete_flag = 1;
41.1303 + }
41.1304 + }
41.1305 + }
41.1306 + else if(family == AF_INET6){
41.1307 + ipv6Table->RemoveRoute(dest6);
41.1308 + delete_flag = 1;
41.1309 + }
41.1310 +
41.1311 + if (!delete_flag)
41.1312 + {
41.1313 + NS_LOG_INFO("no route entry removed by dest address" << dest);
41.1314 + m_errno = ERROR_INVAL;
41.1315 + return -1;
41.1316 + }
41.1317 + }
41.1318 + else
41.1319 + {
41.1320 + NS_LOG_INFO("too few attributes to add an route entry");
41.1321 + m_errno = ERROR_INVAL;
41.1322 + return -1;
41.1323 + }
41.1324 + }
41.1325 + else// type == NETLINK_RTM_GETROUTE
41.1326 + {
41.1327 + if (!attr_flags[RouteMessage::RT_A_DST])
41.1328 + {
41.1329 + NS_LOG_INFO("too few attributes to get an route entry");
41.1330 + m_errno = ERROR_INVAL;
41.1331 + return -1;
41.1332 + }
41.1333 +
41.1334 + int get_flag = 0;
41.1335 + if(family == AF_INET){
41.1336 + for (uint32_t i = 0; i < ipv4Static->GetNRoutes(); i ++)
41.1337 + {
41.1338 + Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
41.1339 + //find the route entry with same dest address and send unicast to user space
41.1340 + if (dest.IsEqual(route.GetDest()))
41.1341 + {
41.1342 + // Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
41.1343 + NetlinkMessage nlmsg_route;
41.1344 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, 0, nlmsg.GetHeader().GetMsgSeq(), m_srcPid);
41.1345 + RouteMessage rtmsg;
41.1346 +
41.1347 + //fill rtmsg and attributes
41.1348 + rtmsg.SetFamily(AF_INET);//AF_INET
41.1349 + rtmsg.SetDstLength(32);
41.1350 + rtmsg.SetSrcLength(0);
41.1351 + rtmsg.SetTos(0);//not clear
41.1352 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.1353 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.1354 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.1355 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.1356 +
41.1357 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.1358 + //ns3 use local address as the route src address
41.1359 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
41.1360 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));//not used in ns3
41.1361 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
41.1362 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
41.1363 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
41.1364 + //XXX..other attributes not used by ns3
41.1365 +
41.1366 + //fill an netlink message body
41.1367 + nlmsg_route.SetHeader(nhr);
41.1368 + nlmsg_route.SetRouteMessage (rtmsg);
41.1369 +
41.1370 + SendMessageUnicast (nlmsg_route, m_srcPid, 1);
41.1371 + get_flag = 1;
41.1372 + }
41.1373 + }
41.1374 + }
41.1375 + else if(family == AF_INET6){
41.1376 + for (uint32_t i = 0; i < ipv6Table->GetNRoutes(); i ++)
41.1377 + {
41.1378 + Ipv6RoutingTableEntry route = ipv6Table->GetRoute (i);
41.1379 + //find the route entry with same dest address and send unicast to user space
41.1380 + if (dest6.IsEqual(route.GetDest()))
41.1381 + {
41.1382 + NetlinkMessage nlmsg_route;
41.1383 + NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWROUTE, 0, nlmsg.GetHeader().GetMsgSeq(), m_srcPid);
41.1384 + RouteMessage rtmsg;
41.1385 +
41.1386 + //fill rtmsg and attributes
41.1387 + rtmsg.SetFamily(AF_INET6);//AF_INET6
41.1388 + rtmsg.SetDstLength(32);
41.1389 + rtmsg.SetSrcLength(0);
41.1390 + rtmsg.SetTos(0);//not clear
41.1391 + rtmsg.SetTableId(RouteMessage::RT_TABLE_MAIN);
41.1392 + rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.1393 + rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
41.1394 + rtmsg.SetFlags(RouteMessage::RT_F_CLONED);
41.1395 +
41.1396 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
41.1397 + //ns3 use local address as the route src address
41.1398 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
41.1399 + // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));//not used in ns3
41.1400 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
41.1401 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
41.1402 + rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
41.1403 + //XXX..other attributes not used by ns3
41.1404 +
41.1405 + //fill an netlink message body
41.1406 + nlmsg_route.SetHeader(nhr);
41.1407 + nlmsg_route.SetRouteMessage (rtmsg);
41.1408 +
41.1409 + SendMessageUnicast (nlmsg_route, m_srcPid, 1);
41.1410 + get_flag = 1;
41.1411 + }
41.1412 + }
41.1413 + }
41.1414 +
41.1415 + if(!get_flag)
41.1416 + {
41.1417 + NS_LOG_INFO("no route entry exist by dest address" << dest);
41.1418 + m_errno = ERROR_INVAL;
41.1419 + return -1;
41.1420 + }
41.1421 + }
41.1422 +
41.1423 + //then send an broadcast message, let all user know this operation happened
41.1424 + NetlinkMessage nlmsg_broadcast = nlmsg;
41.1425 + NetlinkMessageHeader nhr;
41.1426 + nhr.SetMsgLen(nlmsg.GetHeader().GetMsgLen());
41.1427 + nhr.SetMsgType(nlmsg.GetHeader().GetMsgType());
41.1428 + nlmsg_broadcast.SetHeader(nhr);
41.1429 +// SendMessageBroadcast(nlmsg_broadcast, 0, NETLINK_RTM_GRP_IPV4_ROUTE);
41.1430 +// SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
41.1431 + return 0;
41.1432 +}
41.1433 +
41.1434 +#if 0
41.1435 +device->SetLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
41.1436 +int32_t
41.1437 +NetlinkSocket::NotifyIfLinkMessage(Address address, uint16_t type, uint8_t family)
41.1438 +{
41.1439 +}
41.1440 +#endif
41.1441 +int32_t
41.1442 +NetlinkSocket::NotifyIfAddrMessage(Ipv6Interface* interface, Ipv6Address addr, int cmd)
41.1443 +{
41.1444 + MultipartNetlinkMessage nlmsg_multi;
41.1445 + NetlinkMessage nlmsg_ifa;
41.1446 + NetlinkMessageHeader nhr = NetlinkMessageHeader(cmd, NETLINK_MSG_F_MULTI, 0, 0);
41.1447 + InterfaceAddressMessage ifamsg;
41.1448 +
41.1449 + // FIXME!
41.1450 + Ipv6Prefix prefix = Ipv6Prefix(64);
41.1451 +
41.1452 + //loopback address not dumped
41.1453 + if (addr.IsEqual(Ipv6Address::GetLoopback()))
41.1454 + return -1;
41.1455 +
41.1456 + //here get the address mask length
41.1457 + uint8_t bytes[16];
41.1458 + prefix.GetBytes(bytes);
41.1459 + uint8_t mask_len = 0;
41.1460 + for (int j = 0; j < 16; j++){
41.1461 + while (bytes[j])
41.1462 + {
41.1463 + bytes[j] = bytes[j] << 1;
41.1464 + mask_len ++;
41.1465 + }
41.1466 + }
41.1467 +
41.1468 +
41.1469 + ifamsg.SetInterfaceIndex(interface->GetDevice()->GetIfIndex());
41.1470 + ifamsg.SetFamily(AF_INET6);
41.1471 + ifamsg.SetLength(mask_len);
41.1472 + ifamsg.SetFlags(0);
41.1473 + ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
41.1474 +
41.1475 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addr));
41.1476 + ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addr));
41.1477 + // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
41.1478 + // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL, STRING, "ns3-ifaddr"));//not used in ns3
41.1479 + //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST, ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
41.1480 + //XXXother attributes not used by ns3
41.1481 +
41.1482 + nlmsg_ifa.SetHeader(nhr);
41.1483 + nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
41.1484 +
41.1485 + NetlinkMessage nlmsg_done;
41.1486 + NetlinkMessageHeader nhr_done = NetlinkMessageHeader(NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
41.1487 + nlmsg_done.SetHeader(nhr_done);
41.1488 +
41.1489 + nlmsg_multi.AppendMessage (nlmsg_ifa);
41.1490 + nlmsg_multi.AppendMessage (nlmsg_done);
41.1491 +
41.1492 + SendMessageBroadcast(nlmsg_multi, 0, RTMGRP_IPV6_IFADDR, interface->GetDevice()->GetNode());
41.1493 +
41.1494 + return 0;
41.1495 +}
41.1496 +#if 0
41.1497 +int32_t
41.1498 +NetlinkSocket::NotifyRouteMessage(Ojbect route, uint16_t type, uint8_t family)
41.1499 +{
41.1500 + NetlinkMessage nlmsg_broadcast = nlmsg;
41.1501 + NetlinkMessageHeader nhr;
41.1502 + nhr.SetMsgLen(nlmsg.GetHeader().GetMsgLen());
41.1503 + nhr.SetMsgType(nlmsg.GetHeader().GetMsgType());
41.1504 + nlmsg_broadcast.SetHeader(nhr);
41.1505 + SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
41.1506 +}
41.1507 +#endif
41.1508 +}//namespace ns3
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/src/node/netlink-socket.h Thu Oct 01 23:37:18 2009 +0900
42.3 @@ -0,0 +1,196 @@
42.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
42.5 +/*
42.6 +* Copyright (c) 2008 Liu Jian
42.7 +*
42.8 +* This program is free software; you can redistribute it and/or modify
42.9 +* it under the terms of the GNU General Public License version 2 as
42.10 +* published by the Free Software Foundation;
42.11 +*
42.12 +* This program is distributed in the hope that it will be useful,
42.13 +* but WITHOUT ANY WARRANTY; without even the implied warranty of
42.14 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42.15 +* GNU General Public License for more details.
42.16 +*
42.17 +* You should have received a copy of the GNU General Public License
42.18 +* along with this program; if not, write to the Free Software
42.19 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42.20 +*
42.21 +* Author: Liu Jian <liujatp@gmail.com>
42.22 +*/
42.23 +#ifndef NETLINK_SOCKET_H
42.24 +#define NETLINK_SOCKET_H
42.25 +
42.26 +#include <stdint.h>
42.27 +#include <queue>
42.28 +#include "ns3/callback.h"
42.29 +#include "ns3/ptr.h"
42.30 +#include "ns3/traced-callback.h"
42.31 +#include "ns3/socket.h"
42.32 +#include "ns3/netlink-message.h"
42.33 +#include "ns3/ipv4-address.h"
42.34 +#include "ns3/ipv6-address.h"
42.35 +#include "ns3/ipv6-interface.h"
42.36 +namespace ns3 {
42.37 +
42.38 +class Node;
42.39 +class Packet;
42.40 +class NetlinkSocketAddress;
42.41 +
42.42 +/**
42.43 +* \brief A NetlinkSocket is used to transfer information
42.44 +between kernel and userspace processes .
42.45 +*
42.46 +* here we focus on NETLINK_ROUTE: Receives routing and link
42.47 +* updates and may be used to modify the routing tables
42.48 +* (both IPv4 and IPv6), IP addresses, link parame- ters, neighbor
42.49 +* setups, queueing disciplines, traffic classes and packet
42.50 +* classifiers (see rtnetlink (7)). This socket type is very similar
42.51 +* to the linux and BSD "packet" sockets.
42.52 +*
42.53 +* Here is a summary of the semantics of this class:
42.54 +* - Bind: Bind uses only the protocol and device fields of the
42.55 +* NetlinkSocketAddress.
42.56 +*
42.57 +* - Send: send the input packet to the underlying kernel space
42.58 +* with its own address. The socket must be bound.
42.59 +*
42.60 +* - Recv: receive packet from the kernel space.
42.61 +*
42.62 +* - Accept: not allowed
42.63 +* - Connect: not allowed
42.64 +*/
42.65 +class NetlinkSocket : public Socket
42.66 +{
42.67 +public:
42.68 + static TypeId GetTypeId (void);
42.69 +
42.70 + NetlinkSocket ();
42.71 + virtual ~NetlinkSocket ();
42.72 +
42.73 + void SetNode (Ptr<Node> node);
42.74 +
42.75 + virtual enum SocketErrno GetErrno (void) const;
42.76 + virtual Ptr<Node> GetNode (void) const;
42.77 + virtual int Bind (void);
42.78 + virtual int Bind (const Address & address);
42.79 + virtual int Close (void);
42.80 + virtual int ShutdownSend (void);
42.81 + virtual int ShutdownRecv (void);
42.82 + virtual int Connect(const Address &address);
42.83 + virtual int Listen(void);
42.84 + virtual uint32_t GetTxAvailable (void) const;
42.85 + virtual int Send (Ptr<Packet> p, uint32_t flags);
42.86 + virtual int SendTo(Ptr<Packet> p, uint32_t flags, const Address &toAddress);
42.87 + virtual uint32_t GetRxAvailable (void) const;
42.88 + virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
42.89 + virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,
42.90 + Address &fromAddress);
42.91 + virtual int GetSockName (Address &address) const;
42.92 +
42.93 + uint32_t GetSrcPid(void) const;
42.94 + uint32_t GetSrcGroups(void)const;
42.95 + uint32_t GetDstPid(void) const;
42.96 + uint32_t GetDstGroups(void)const;
42.97 + static int32_t NotifyIfAddrMessage(Ipv6Interface* interface, Ipv6Address addr, int cmd);
42.98 +
42.99 +private:
42.100 + int DoBind (const NetlinkSocketAddress &address);
42.101 + virtual void DoDispose (void);
42.102 + void ForwardUp (Ptr<Packet> p, NetlinkSocketAddress &address);
42.103 +
42.104 +
42.105 +
42.106 + /**
42.107 + * the functions below were for kernel parsing netlink message,set private here
42.108 + * when netlink msg sent to kernel through netlink socket, it was parsed in kernel
42.109 + * space, then, kernel add/del its route/interface/link table or dump all information
42.110 + * to user space
42.111 + */
42.112 +
42.113 + int32_t HandleMessage (const NetlinkMessage&nlmsg);
42.114 + /**
42.115 + * when kernel find the message truncated or user need an ACK response,
42.116 + * it send ACK back to user space, with the error code(0 for ACK, > 0 for error).
42.117 + */
42.118 + void SendAckMessage (const NetlinkMessage&nlmsg, int32_t errorcode);
42.119 +
42.120 + /**
42.121 + * \brief unicast an message to user
42.122 + * \param nlmsg the netlink message to transmit
42.123 + * \param pid the netlink pid of destination socket
42.124 + * \param nonbloack always true
42.125 + */
42.126 + int32_t SendMessageUnicast (const MultipartNetlinkMessage&nlmsg,
42.127 + uint32_t pid, int32_t nonblock);
42.128 + /**
42.129 + * \brief spread message to netlink group user
42.130 + * \param nlmsg the netlink message to transmit
42.131 + * \param pid the netlink pid of the kernel, always 0
42.132 + * \param group multicast group id
42.133 + */
42.134 + static int32_t SendMessageBroadcast (const MultipartNetlinkMessage&nlmsg,
42.135 + uint32_t pid, uint32_t group, Ptr<Node> node);
42.136 +
42.137 + /**
42.138 + * these functions below are for NETLINK_ROUTE protocol, it handle the netlink
42.139 + * message like linux kernel work. this implementation follows the kernel code
42.140 + * linux/rtnetlink.c, focus on "interface address, interface info and route entry",
42.141 + * now we will only simply support three types operations of NETLINK_ROUTE
42.142 + * protocol
42.143 + */
42.144 +
42.145 + /**
42.146 + * \returns 0 if messge not processed, < 0 for success or an error.
42.147 + * this function would call dumping/doing functions to
42.148 + */
42.149 + int32_t HandleNetlinkRouteMessage (const NetlinkMessage&nlmsg);
42.150 +
42.151 + /**
42.152 + * \returns 0 if dumping operation is OK, < 0 for an error.
42.153 + */
42.154 + int32_t DumpNetlinkRouteMessage (const NetlinkMessage&nlmsg,
42.155 + uint16_t type, uint8_t family);
42.156 + MultipartNetlinkMessage BuildInterfaceAddressDumpMessage (
42.157 + uint32_t pid, uint32_t seq, uint8_t family);
42.158 + MultipartNetlinkMessage BuildInterfaceInfoDumpMessage (
42.159 + uint32_t pid, uint32_t seq, uint8_t family);
42.160 + MultipartNetlinkMessage BuildRouteDumpMessage (
42.161 + uint32_t pid, uint32_t seq, uint8_t family);
42.162 +
42.163 + /**
42.164 + * \returns 0 if doing operation(ADD/DEL/GET) is OK, < 0 for an error.
42.165 + */
42.166 + int32_t DoNetlinkRouteMessage (const NetlinkMessage&nlmsg,
42.167 + uint16_t type, uint8_t family);
42.168 + int32_t DoInterfaceAddressMessage (const NetlinkMessage&nlmsg,
42.169 + uint16_t type, uint8_t family);
42.170 + int32_t DoInterfaceInfoMessage (const NetlinkMessage&nlmsg,
42.171 + uint16_t type, uint8_t family);
42.172 + int32_t DoRouteMessage (const NetlinkMessage&nlmsg,
42.173 + uint16_t type, uint8_t family);
42.174 +
42.175 + int ErrnoToSimuErrno (void);
42.176 +
42.177 + Ptr<Node> m_node;
42.178 + enum SocketErrno m_errno;
42.179 + bool m_shutdownSend;
42.180 + bool m_shutdownRecv;
42.181 +
42.182 + std::queue<Ptr<Packet> > m_dataReceiveQueue;
42.183 + uint32_t m_rxAvailable;
42.184 + TracedCallback<Ptr<const Packet> > m_dropTrace;
42.185 + // Socket options (attributes)
42.186 + uint32_t m_rcvBufSize;
42.187 +
42.188 + uint32_t m_srcPid;
42.189 + uint32_t m_srcGroups;
42.190 + uint32_t m_dstPid;
42.191 + uint32_t m_dstGroups;
42.192 + Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
42.193 +};
42.194 +
42.195 +}//namespace ns3
42.196 +
42.197 +#endif /* NETLINK_SOCKET_H */
42.198 +
42.199 +
43.1 --- a/src/node/node.cc Mon Sep 07 15:45:12 2009 +0200
43.2 +++ b/src/node/node.cc Thu Oct 01 23:37:18 2009 +0900
43.3 @@ -30,6 +30,7 @@
43.4 #include "ns3/assert.h"
43.5 #include "ns3/global-value.h"
43.6 #include "ns3/boolean.h"
43.7 +#include "ns3/socket.h"
43.8
43.9 NS_LOG_COMPONENT_DEFINE ("Node");
43.10
43.11 @@ -251,6 +252,10 @@
43.12 << ") Packet UID " << packet->GetUid ());
43.13 bool found = false;
43.14
43.15 + SocketRecvIfTag tag;
43.16 + tag.SetRecvIf (device->GetIfIndex());
43.17 + packet->AddByteTag (tag);
43.18 +
43.19 for (ProtocolHandlerList::iterator i = m_handlers.begin ();
43.20 i != m_handlers.end (); i++)
43.21 {
44.1 --- a/src/node/socket.cc Mon Sep 07 15:45:12 2009 +0200
44.2 +++ b/src/node/socket.cc Thu Oct 01 23:37:18 2009 +0900
44.3 @@ -428,4 +428,58 @@
44.4 os << (m_dontFragment?"true":"false");
44.5 }
44.6
44.7 +
44.8 +SocketRecvIfTag::SocketRecvIfTag ()
44.9 +{
44.10 +}
44.11 +
44.12 +void
44.13 +SocketRecvIfTag::SetRecvIf (uint32_t ifindex)
44.14 +{
44.15 + m_ifindex = ifindex;
44.16 +}
44.17 +
44.18 +uint32_t
44.19 +SocketRecvIfTag::GetRecvIf (void) const
44.20 +{
44.21 + return m_ifindex;
44.22 +}
44.23 +
44.24 +
44.25 +TypeId
44.26 +SocketRecvIfTag::GetTypeId (void)
44.27 +{
44.28 + static TypeId tid = TypeId ("ns3::SocketRecvIfTag")
44.29 + .SetParent<Tag> ()
44.30 + .AddConstructor<SocketRecvIfTag> ()
44.31 + ;
44.32 + return tid;
44.33 +}
44.34 +TypeId
44.35 +SocketRecvIfTag::GetInstanceTypeId (void) const
44.36 +{
44.37 + return GetTypeId ();
44.38 +}
44.39 +
44.40 +uint32_t
44.41 +SocketRecvIfTag::GetSerializedSize (void) const
44.42 +{
44.43 + return sizeof(uint32_t);
44.44 +}
44.45 +void
44.46 +SocketRecvIfTag::Serialize (TagBuffer i) const
44.47 +{
44.48 + i.WriteU32 (m_ifindex);
44.49 +}
44.50 +void
44.51 +SocketRecvIfTag::Deserialize (TagBuffer i)
44.52 +{
44.53 + m_ifindex = i.ReadU32 ();
44.54 +}
44.55 +void
44.56 +SocketRecvIfTag::Print (std::ostream &os) const
44.57 +{
44.58 + os << "RecvIf=" << (uint32_t) m_ifindex;
44.59 +}
44.60 +
44.61 }//namespace ns3
45.1 --- a/src/node/socket.h Mon Sep 07 15:45:12 2009 +0200
45.2 +++ b/src/node/socket.h Thu Oct 01 23:37:18 2009 +0900
45.3 @@ -79,6 +79,8 @@
45.4 ERROR_INVAL,
45.5 ERROR_BADF,
45.6 ERROR_NOROUTETOHOST,
45.7 + ERROR_NODEV,
45.8 + ERROR_ADDRNOTAVAIL,
45.9 SOCKET_ERRNO_LAST
45.10 };
45.11
45.12 @@ -579,6 +581,25 @@
45.13 bool m_dontFragment;
45.14 };
45.15
45.16 +class SocketRecvIfTag : public Tag
45.17 +{
45.18 +public:
45.19 + SocketRecvIfTag ();
45.20 + void SetRecvIf (uint32_t ifindex);
45.21 + uint32_t GetRecvIf (void) const;
45.22 +
45.23 + static TypeId GetTypeId (void);
45.24 + virtual TypeId GetInstanceTypeId (void) const;
45.25 + virtual uint32_t GetSerializedSize (void) const;
45.26 + virtual void Serialize (TagBuffer i) const;
45.27 + virtual void Deserialize (TagBuffer i);
45.28 + virtual void Print (std::ostream &os) const;
45.29 +
45.30 +private:
45.31 + uint8_t m_ifindex;
45.32 +};
45.33 +
45.34 +
45.35 } //namespace ns3
45.36
45.37 #endif /* SOCKET_H */
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/src/node/tcp6-socket-factory.cc Thu Oct 01 23:37:18 2009 +0900
46.3 @@ -0,0 +1,38 @@
46.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
46.5 +/*
46.6 + * Copyright (c) 2007-2008 Louis Pasteur University
46.7 + *
46.8 + * This program is free software; you can redistribute it and/or modify
46.9 + * it under the terms of the GNU General Public License version 2 as
46.10 + * published by the Free Software Foundation;
46.11 + *
46.12 + * This program is distributed in the hope that it will be useful,
46.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
46.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46.15 + * GNU General Public License for more details.
46.16 + *
46.17 + * You should have received a copy of the GNU General Public License
46.18 + * along with this program; if not, write to the Free Software
46.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46.20 + *
46.21 + * Author: David Gross <gdavid.devel@gmail.com>
46.22 + */
46.23 +
46.24 +#include "tcp6-socket-factory.h"
46.25 +#include "ns3/uinteger.h"
46.26 +#include "ns3/double.h"
46.27 +
46.28 +namespace ns3 {
46.29 +
46.30 + NS_OBJECT_ENSURE_REGISTERED (Tcp6SocketFactory);
46.31 +
46.32 + TypeId Tcp6SocketFactory::GetTypeId ()
46.33 + {
46.34 + static TypeId tid = TypeId ("ns3::Tcp6SocketFactory")
46.35 + .SetParent<SocketFactory> ()
46.36 + ;
46.37 + return tid;
46.38 + }
46.39 +
46.40 +} /* namespace ns3 */
46.41 +
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/src/node/tcp6-socket-factory.h Thu Oct 01 23:37:18 2009 +0900
47.3 @@ -0,0 +1,66 @@
47.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
47.5 +/*
47.6 + * Copyright (c) 2007-2008 Louis Pasteur University
47.7 + *
47.8 + * This program is free software; you can redistribute it and/or modify
47.9 + * it under the terms of the GNU General Public License version 2 as
47.10 + * published by the Free Software Foundation;
47.11 + *
47.12 + * This program is distributed in the hope that it will be useful,
47.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47.15 + * GNU General Public License for more details.
47.16 + *
47.17 + * You should have received a copy of the GNU General Public License
47.18 + * along with this program; if not, write to the Free Software
47.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47.20 + *
47.21 + * Author: David Gross <gdavid.devel@gmail.com>
47.22 + */
47.23 +
47.24 +#ifndef TCP6_SOCKET_FACTORY_H
47.25 +#define TCP6_SOCKET_FACTORY_H
47.26 +
47.27 +#include "socket-factory.h"
47.28 +
47.29 +namespace ns3 {
47.30 +
47.31 + class Socket;
47.32 +
47.33 + /**
47.34 + * \class Tcp6SocketFactory
47.35 + * \brief API to create TCPv6 socket instances
47.36 + *
47.37 + * This abstract class defines the API for TCPv6 sockets.
47.38 + * This class also holds the global default variables used to
47.39 + * initialize newly created sockets, such as values that are
47.40 + * set through the sysctl or proc interfaces in Linux.
47.41 +
47.42 + * All TCPv6 implementations must provide an implementation of CreateSocket
47.43 + * below, and should make use of the default values configured below.
47.44 + *
47.45 + * \see Tcp6SocketFactoryImpl
47.46 + *
47.47 + */
47.48 + class Tcp6SocketFactory : public SocketFactory
47.49 + {
47.50 + public:
47.51 + /**
47.52 + * \brief Interface ID.
47.53 + * \return type identificator
47.54 + */
47.55 + static TypeId GetTypeId ();
47.56 +
47.57 + /**
47.58 + * \brief Create a TCPv6 socket.
47.59 + * \return a pointer on a socket
47.60 + * API for creating socket instances; must be implemented by TCPv6 implementation.
47.61 + */
47.62 + virtual Ptr<Socket> CreateSocket () = 0;
47.63 +
47.64 + };
47.65 +
47.66 +} /* namespace ns3 */
47.67 +
47.68 +#endif /* TCP6_SOCKET_FACTORY_H */
47.69 +
48.1 --- a/src/node/wscript Mon Sep 07 15:45:12 2009 +0200
48.2 +++ b/src/node/wscript Thu Oct 01 23:37:18 2009 +0900
48.3 @@ -45,6 +45,14 @@
48.4 'ipv6.cc',
48.5 'ipv6-raw-socket-factory.cc',
48.6 'ipv6-routing-protocol.cc',
48.7 + 'netlink-socket.cc',
48.8 + 'netlink-socket-address.cc',
48.9 + 'netlink-socket-factory.cc',
48.10 + 'netlink-attribute.cc',
48.11 + 'netlink-message.cc',
48.12 + 'netlink-message-route.cc',
48.13 + 'netlink-ipv6-routing-table.cc',
48.14 + 'tcp6-socket-factory.cc',
48.15 ]
48.16
48.17 headers = bld.new_task_gen('ns3header')
48.18 @@ -91,4 +99,12 @@
48.19 'ipv6.h',
48.20 'ipv6-raw-socket-factory.h',
48.21 'ipv6-routing-protocol.h',
48.22 + 'netlink-socket.h',
48.23 + 'netlink-socket-address.h',
48.24 + 'netlink-socket-factory.h',
48.25 + 'netlink-attribute.h',
48.26 + 'netlink-message.h',
48.27 + 'netlink-message-route.h',
48.28 + 'netlink-ipv6-routing-table.h',
48.29 + 'tcp6-socket-factory.h',
48.30 ]
49.1 --- a/src/process-manager/libc-simu.c Mon Sep 07 15:45:12 2009 +0200
49.2 +++ b/src/process-manager/libc-simu.c Thu Oct 01 23:37:18 2009 +0900
49.3 @@ -48,11 +48,11 @@
49.4 libc.__cxa_finalize_fn = __cxa_finalize;
49.5 libc.__cxa_atexit_fn = __cxa_atexit;
49.6 libc.__gxx_personality_v0_fn = __gxx_personality_v0;
49.7 - libc.newlocale_fn = newlocale;
49.8 - libc.uselocale_fn = uselocale;
49.9 +// libc.newlocale_fn = newlocale;
49.10 +// libc.uselocale_fn = uselocale;
49.11 libc.wctob_fn = wctob;
49.12 libc.btowc_fn = btowc;
49.13 - libc.wctype_l_fn = wctype_l;
49.14 +// libc.wctype_l_fn = wctype_l;
49.15 libc.fputc_fn = simu_fputc;
49.16 libc.fputs_fn = simu_fputs;
49.17 libc.fgetc_fn = simu_fgetc;
50.1 --- a/src/process-manager/libc.c Mon Sep 07 15:45:12 2009 +0200
50.2 +++ b/src/process-manager/libc.c Thu Oct 01 23:37:18 2009 +0900
50.3 @@ -89,6 +89,7 @@
50.4 {
50.5 return g_libc.__gxx_personality_v0_fn (a,b,c,d,e);
50.6 }
50.7 +#if 0
50.8 __locale_t __newlocale (int category_mask, const char *locale, __locale_t base)
50.9 {
50.10 return g_libc.newlocale_fn (category_mask, locale, base);
50.11 @@ -99,6 +100,7 @@
50.12 return g_libc.uselocale_fn (__dataset);
50.13 }
50.14 weak_alias (__uselocale, uselocale);
50.15 +#endif
50.16 int wctob (wint_t c)
50.17 {
50.18 return g_libc.wctob_fn (c);
50.19 @@ -107,11 +109,13 @@
50.20 {
50.21 return g_libc.btowc_fn (c);
50.22 }
50.23 +#if 0
50.24 wctype_t __wctype_l (__const char *__property, __locale_t __locale)
50.25 {
50.26 return g_libc.wctype_l_fn (__property, __locale);
50.27 }
50.28 weak_alias (__wctype_l, wctype_l);
50.29 +#endif
50.30 int puts (const char *s)
50.31 {
50.32 return g_libc.fputs_fn (s, stdout);
50.33 @@ -128,10 +132,12 @@
50.34 {
50.35 return g_libc.fputc_fn (c, stream);
50.36 }
50.37 +#if 0
50.38 int _IO_putc(int c, FILE *stream)
50.39 {
50.40 return putc (c, stream);
50.41 }
50.42 +#endif
50.43 int putchar (int c)
50.44 {
50.45 return putc (c, stdout);
51.1 --- a/src/process-manager/libc.h Mon Sep 07 15:45:12 2009 +0200
51.2 +++ b/src/process-manager/libc.h Thu Oct 01 23:37:18 2009 +0900
51.3 @@ -2,6 +2,7 @@
51.4 #ifndef LIBC_H
51.5 #define LIBC_H
51.6 #define _LARGEFILE64_SOURCE 1
51.7 +#include <stdio.h>
51.8 #include <stddef.h>
51.9 #include <stdarg.h>
51.10 #include <stdint.h>
51.11 @@ -47,11 +48,11 @@
51.12 int (*__cxa_atexit_fn) (void (*func) (void *), void *arg, void *d);
51.13 int (*__gxx_personality_v0_fn) (int a, int b,
51.14 unsigned c, struct _Unwind_Exception *d, struct _Unwind_Context *e);
51.15 - __locale_t (*newlocale_fn) (int category_mask, const char *locale, __locale_t base);
51.16 - __locale_t (*uselocale_fn) (__locale_t __dataset);
51.17 +// __locale_t (*newlocale_fn) (int category_mask, const char *locale, __locale_t base);
51.18 +// __locale_t (*uselocale_fn) (__locale_t __dataset);
51.19 int (*wctob_fn) (wint_t c);
51.20 wint_t (*btowc_fn) (int c);
51.21 - wctype_t (*wctype_l_fn) (__const char *__property, __locale_t __locale);
51.22 +// wctype_t (*wctype_l_fn) (__const char *__property, __locale_t __locale);
51.23 int (*fputs_fn) (const char *, FILE *);
51.24 int (*fputc_fn) (int, FILE *);
51.25 char* (*fgets_fn) (char *, int, FILE *);
51.26 @@ -86,8 +87,8 @@
51.27 int (*strcmp_fn)(const char *s1, const char *s2);
51.28 int (*strncmp_fn) (const char *s1, const char *s2, size_t n);
51.29 size_t (*strlen_fn) (const char *s);
51.30 - const char *(*strchr_fn) (const char *s, int c);
51.31 - const char *(*strrchr_fn) (const char *s, int c);
51.32 + char *(*strchr_fn) (const char *s, int c);
51.33 + char *(*strrchr_fn) (const char *s, int c);
51.34 int (*strcasecmp_fn) (const char *s1, const char *s2);
51.35 int (*strncasecmp_fn) (const char *s1, const char *s2, size_t n);
51.36 char *(*strdup_fn) (const char *s);
52.1 --- a/src/process-manager/simu-fd.cc Mon Sep 07 15:45:12 2009 +0200
52.2 +++ b/src/process-manager/simu-fd.cc Thu Oct 01 23:37:18 2009 +0900
52.3 @@ -30,6 +30,7 @@
52.4 #include <linux/rtnetlink.h>
52.5 #include <sys/mman.h>
52.6 #include <sys/types.h>
52.7 +#include "ns3/ipv6-raw-socket-impl.h"
52.8 #include "ns3/node.h"
52.9
52.10 NS_LOG_COMPONENT_DEFINE ("SimuFd");
52.11 @@ -476,26 +477,73 @@
52.12 Ptr<Socket> sock;
52.13 Ptr<UnixSocketFd> socket;
52.14
52.15 - switch (type) {
52.16 - case SOCK_DGRAM: {
52.17 - TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
52.18 - Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.19 - sock = factory->CreateSocket ();
52.20 - socket = Create<UnixDatagramSocketFd> (sock);
52.21 - } break;
52.22 - case SOCK_RAW: {
52.23 - TypeId tid = TypeId::LookupByName ("ns3::Ipv4RawSocketFactory");
52.24 - Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.25 - sock = factory->CreateSocket ();
52.26 - sock->SetAttribute ("Protocol", UintegerValue (protocol));
52.27 - socket = Create<UnixDatagramSocketFd> (sock);
52.28 - } break;
52.29 - case SOCK_STREAM: {
52.30 - TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
52.31 - Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.32 - sock = factory->CreateSocket ();
52.33 - socket = Create<UnixStreamSocketFd> (sock);
52.34 - } break;
52.35 + if (domain == PF_INET)
52.36 + {
52.37 + switch (type) {
52.38 + case SOCK_DGRAM: {
52.39 + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
52.40 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.41 + sock = factory->CreateSocket ();
52.42 + socket = Create<UnixDatagramSocketFd> (sock);
52.43 + } break;
52.44 + case SOCK_RAW: {
52.45 + TypeId tid = TypeId::LookupByName ("ns3::Ipv4RawSocketFactory");
52.46 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.47 + sock = factory->CreateSocket ();
52.48 + sock->SetAttribute ("Protocol", UintegerValue (protocol));
52.49 + socket = Create<UnixDatagramSocketFd> (sock);
52.50 + } break;
52.51 + case SOCK_STREAM: {
52.52 + TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
52.53 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.54 + sock = factory->CreateSocket ();
52.55 + socket = Create<UnixStreamSocketFd> (sock);
52.56 + } break;
52.57 + }
52.58 + }
52.59 + else if (domain == PF_INET6)
52.60 + {
52.61 + switch (type) {
52.62 + case SOCK_DGRAM: {
52.63 + TypeId tid = TypeId::LookupByName ("ns3::Udp6SocketFactory");
52.64 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.65 + sock = factory->CreateSocket ();
52.66 + socket = Create<UnixDatagramSocketFd> (sock);
52.67 + } break;
52.68 + case SOCK_RAW: {
52.69 + TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
52.70 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.71 + sock = factory->CreateSocket ();
52.72 + sock->Bind();
52.73 + sock->SetAttribute ("Protocol", UintegerValue (protocol));
52.74 + socket = Create<UnixDatagramSocketFd> (sock);
52.75 + } break;
52.76 + case SOCK_STREAM: {
52.77 + TypeId tid = TypeId::LookupByName ("ns3::Tcp6SocketFactory");
52.78 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.79 + sock = factory->CreateSocket ();
52.80 + socket = Create<UnixStreamSocketFd> (sock);
52.81 + } break;
52.82 + }
52.83 + }
52.84 + else if (domain == PF_NETLINK)
52.85 + {
52.86 + if (type != SOCK_DGRAM && type != SOCK_RAW)
52.87 + {
52.88 + current->err = ESOCKTNOSUPPORT;
52.89 + return -1;
52.90 + }
52.91 + /*for now we only support NETLINK_ROUTE*/
52.92 + if (protocol != NETLINK_ROUTE)
52.93 + {
52.94 + current->err = EPROTONOSUPPORT;
52.95 + return -1;
52.96 + }
52.97 +
52.98 + TypeId tid= TypeId::LookupByName("ns3::NetlinkSocketFactory");
52.99 + Ptr<SocketFactory> factory = manager->GetObject<SocketFactory> (tid);
52.100 + sock = factory->CreateSocket ();
52.101 + socket = Create<UnixDatagramSocketFd> (sock);
52.102 }
52.103
52.104 current->process->openFiles.push_back (std::make_pair (fd, socket));
53.1 --- a/src/process-manager/simu-stdio.cc Mon Sep 07 15:45:12 2009 +0200
53.2 +++ b/src/process-manager/simu-stdio.cc Thu Oct 01 23:37:18 2009 +0900
53.3 @@ -298,7 +298,10 @@
53.4 NS_ASSERT (Current () != 0);
53.5 Thread *current = Current ();
53.6 char *str;
53.7 - int retval = ::vasprintf (&str, format, ap);
53.8 + std::stringstream ss;
53.9 + ss << "Node" << UtilsGetNodeId() << ": " << format;
53.10 +
53.11 + int retval = ::vasprintf (&str, ss.str().c_str(), ap);
53.12 if (retval == -1)
53.13 {
53.14 current->err = errno;
54.1 --- a/src/process-manager/unix-datagram-socket-fd.cc Mon Sep 07 15:45:12 2009 +0200
54.2 +++ b/src/process-manager/unix-datagram-socket-fd.cc Thu Oct 01 23:37:18 2009 +0900
54.3 @@ -6,7 +6,11 @@
54.4 #include "ns3/socket.h"
54.5 #include "ns3/packet.h"
54.6 #include "ns3/simulator.h"
54.7 +#include "ns3/node.h"
54.8 #include "ns3/inet-socket-address.h"
54.9 +#include "ns3/ipv6-raw-socket-impl.h"
54.10 +#include "ns3/ipv6.h"
54.11 +//#include "ns3/udp6-socket-impl.h"
54.12 #include "cmsg.h"
54.13 #include <errno.h>
54.14 #include <netinet/in.h>
54.15 @@ -130,7 +134,7 @@
54.16 }
54.17 else
54.18 {
54.19 - msg->msg_controllen = 0;
54.20 + // msg->msg_controllen = 0;
54.21 }
54.22
54.23 if (!WaitRecvDoSignal (flags & MSG_DONTWAIT))
54.24 @@ -151,6 +155,31 @@
54.25 return -1;
54.26 }
54.27 Ns3AddressToPosixAddress (from, (struct sockaddr*)msg->msg_name, &msg->msg_namelen);
54.28 +
54.29 + if(msg->msg_controllen > 0){
54.30 + Cmsg cmsg = Cmsg (msg);
54.31 + if (IsRecvPktInfo ())
54.32 + {
54.33 + struct in6_pktinfo pkt;
54.34 +
54.35 + SocketRecvIfTag tag;
54.36 + bool found;
54.37 + found = packet->FindFirstMatchingByteTag (tag);
54.38 + NS_ASSERT (found);
54.39 +
54.40 + Ptr<Node> node = current->process->manager->GetObject<Node> ();
54.41 + Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
54.42 + pkt.ipi6_ifindex = ipv6->GetInterfaceForDevice (node->GetDevice(tag.GetRecvIf ()));
54.43 + memcpy(&pkt.ipi6_addr, msg->msg_name, sizeof(pkt.ipi6_addr));
54.44 + cmsg.Add (SOL_IPV6, IPV6_PKTINFO, sizeof (struct in6_pktinfo), (const uint8_t*)&pkt);
54.45 +
54.46 + Ipv6Header hdr = Ipv6Header();
54.47 + packet->RemoveHeader (hdr);
54.48 + }
54.49 + cmsg.Finish ();
54.50 + }
54.51 +
54.52 +
54.53 // XXX: we ignore MSG_TRUNC for the return value.
54.54 NS_ASSERT (packet->GetSize () <= count);
54.55 memcpy (buf, packet->PeekData (), packet->GetSize ());
54.56 @@ -162,7 +191,42 @@
54.57 Thread *current = Current ();
54.58 NS_LOG_FUNCTION (this << current);
54.59 NS_ASSERT (current != 0);
54.60 + uint32_t old_ifindex = 0;
54.61
54.62 + // parse cmsg
54.63 + Cmsg cmsg = Cmsg ((struct msghdr *)msg);
54.64 + int level, type, len;
54.65 + uint8_t *data = NULL;
54.66 + if (cmsg.GetNext (&level, &type, &len, &data) == 0)
54.67 + {
54.68 + switch (type){
54.69 + case IPV6_PKTINFO:{
54.70 + struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)data;
54.71 + if (len != sizeof(struct in6_pktinfo))
54.72 + break;
54.73 +
54.74 + // if(m_socket.GetTypeId().IsChildOf (Ipv6RawSocketImpl::GetTypeId ()))
54.75 + if(typeid(* PeekPointer(m_socket)) == typeid(Ipv6RawSocketImpl))
54.76 + {
54.77 + NS_LOG_INFO("sendmsg: set ifindex to " << pktinfo->ipi6_ifindex);
54.78 + old_ifindex = (dynamic_cast<Ipv6RawSocketImpl *>(PeekPointer(m_socket)))->GetIfIndex();
54.79 + (dynamic_cast<Ipv6RawSocketImpl *>(PeekPointer(m_socket)))->SetIfIndex(pktinfo->ipi6_ifindex);
54.80 + }
54.81 +#ifdef FIXME
54.82 + else if(typeid(* PeekPointer(m_socket)) == typeid(Udp6SocketImpl))
54.83 + {
54.84 + NS_LOG_INFO("sendmsg: set ifindex to " << pktinfo->ipi6_ifindex);
54.85 + old_ifindex = (dynamic_cast<Udp6SocketImpl *>(PeekPointer(m_socket)))->GetIfIndex();
54.86 + (dynamic_cast<Udp6SocketImpl *>(PeekPointer(m_socket)))->SetIfIndex(pktinfo->ipi6_ifindex);
54.87 + }
54.88 +#endif
54.89 + }break;
54.90 + default: {
54.91 + NS_LOG_INFO ("cmsg: Currently not supported");
54.92 + }break;
54.93 + }
54.94 + }
54.95 + cmsg.Finish ();
54.96
54.97 ssize_t retval = 0;
54.98 for (uint32_t i = 0; i < msg->msg_iovlen; ++i)
54.99 @@ -181,6 +245,18 @@
54.100 {
54.101 result = m_socket->Send (packet);
54.102 }
54.103 +
54.104 + if(typeid(* PeekPointer(m_socket)) == typeid(Ipv6RawSocketImpl))
54.105 + {
54.106 + (dynamic_cast<Ipv6RawSocketImpl *>(PeekPointer(m_socket)))->SetIfIndex(old_ifindex);
54.107 + }
54.108 +#ifdef FIXME
54.109 + else if(typeid(* PeekPointer(m_socket)) == typeid(Udp6SocketImpl))
54.110 + {
54.111 + (dynamic_cast<Udp6SocketImpl *>(PeekPointer(m_socket)))->SetIfIndex(old_ifindex);
54.112 + }
54.113 +#endif
54.114 +
54.115 if (result == -1)
54.116 {
54.117 current->err = ErrnoToSimuErrno ();
55.1 --- a/src/process-manager/unix-socket-fd.cc Mon Sep 07 15:45:12 2009 +0200
55.2 +++ b/src/process-manager/unix-socket-fd.cc Thu Oct 01 23:37:18 2009 +0900
55.3 @@ -9,11 +9,20 @@
55.4 #include "ns3/socket.h"
55.5 #include "ns3/packet.h"
55.6 #include "ns3/inet-socket-address.h"
55.7 +#include "ns3/netlink-socket-address.h"
55.8 +#include "ns3/netlink-socket.h"
55.9 #include "ns3/uinteger.h"
55.10 #include "ns3/boolean.h"
55.11 #include "ns3/simulator.h"
55.12 +#include "ns3/ipv6-address.h"
55.13 +#include "ns3/inet6-socket-address.h"
55.14 +#include "ns3/pointer.h"
55.15 +#include "ns3/ipv6-raw-socket-impl.h"
55.16 #include <errno.h>
55.17 #include <linux/icmp.h> // need ICMP_FILTER
55.18 +#include <netinet/icmp6.h> // need ICMP6_FILTER
55.19 +#include <linux/netlink.h>
55.20 +#include <linux/rtnetlink.h>
55.21 #include <netinet/in.h>
55.22 #include <arpa/inet.h>
55.23 #include <sys/mman.h>
55.24 @@ -76,6 +85,10 @@
55.25 return EBADF;
55.26 case Socket::ERROR_NOROUTETOHOST:
55.27 return EHOSTUNREACH;
55.28 + case Socket::ERROR_NODEV:
55.29 + return ENODEV;
55.30 + case Socket::ERROR_ADDRNOTAVAIL:
55.31 + return EADDRNOTAVAIL;
55.32 case Socket::SOCKET_ERRNO_LAST:
55.33 case Socket::ERROR_NOTERROR:
55.34 default:
55.35 @@ -258,6 +271,84 @@
55.36 } break;
55.37 }
55.38 break;
55.39 + case SOL_IPV6:
55.40 + switch (optname) {
55.41 + case IPV6_RECVPKTINFO: {
55.42 + if (optlen != sizeof (int))
55.43 + {
55.44 + current->err = EINVAL;
55.45 + return -1;
55.46 + }
55.47 + int *v = (int*)optval;
55.48 + m_recvpktinfo = *v;
55.49 + } break;
55.50 + case IPV6_CHECKSUM: {
55.51 + if (optlen != sizeof (int))
55.52 + {
55.53 + current->err = EINVAL;
55.54 + return -1;
55.55 + }
55.56 + int *v = (int*)optval;
55.57 + m_sockchecksum = *v;
55.58 + } break;
55.59 + case IPV6_MULTICAST_LOOP: {
55.60 + if (optlen != sizeof (int))
55.61 + {
55.62 + current->err = EINVAL;
55.63 + return -1;
55.64 + }
55.65 + int *v = (int*)optval;
55.66 + m_multicastloop = *v;
55.67 + } break;
55.68 + case IPV6_UNICAST_HOPS: {
55.69 + if (optlen != sizeof (int))
55.70 + {
55.71 + current->err = EINVAL;
55.72 + return -1;
55.73 + }
55.74 + int *v = (int*)optval;
55.75 + m_unicasthops = *v;
55.76 + } break;
55.77 + case IPV6_MULTICAST_HOPS: {
55.78 + if (optlen != sizeof (int))
55.79 + {
55.80 + current->err = EINVAL;
55.81 + return -1;
55.82 + }
55.83 + int *v = (int*)optval;
55.84 + m_multicasthops = *v;
55.85 + } break;
55.86 + case IPV6_RECVHOPLIMIT: {
55.87 + if (optlen != sizeof (int))
55.88 + {
55.89 + current->err = EINVAL;
55.90 + return -1;
55.91 + }
55.92 + int *v = (int*)optval;
55.93 + m_recvhoplimit = *v;
55.94 + } break;
55.95 + }
55.96 + break;
55.97 + case SOL_ICMPV6:
55.98 + switch (optname) {
55.99 + case ICMP6_FILTER: {
55.100 + if (optlen != sizeof (struct icmp6_filter))
55.101 + {
55.102 + current->err = EINVAL;
55.103 + return -1;
55.104 + }
55.105 + struct icmp6_filter *v = (struct icmp6_filter*)optval;
55.106 + if(v){
55.107 + (dynamic_cast<Ipv6RawSocketImpl *>(PeekPointer(m_socket)))->SetIcmp6Filter(v);
55.108 + }
55.109 + } break;
55.110 + }
55.111 + break;
55.112 + default:{
55.113 + std::cout << "Unsupported sockopt\n";
55.114 + current->err = ENOPROTOOPT;
55.115 + return -1;
55.116 + } break;
55.117 }
55.118 return 0;
55.119 }
55.120 @@ -420,8 +511,28 @@
55.121 InetSocketAddress inet = InetSocketAddress (ipv4, port);
55.122 return inet;
55.123 }
55.124 - NS_ASSERT (false);
55.125 - return Address ();
55.126 + else if (my_addr->sa_family == AF_NETLINK )
55.127 + {
55.128 + const struct sockaddr_nl *addr = (const struct sockaddr_nl *)my_addr;
55.129 + //user space netlink socket has a nozero process id
55.130 + uint32_t pid = addr->nl_pid ? addr->nl_pid : getpid();
55.131 + NetlinkSocketAddress nladdress = NetlinkSocketAddress(pid, addr->nl_groups);
55.132 + return nladdress;
55.133 + }
55.134 + else if (my_addr->sa_family == AF_INET6)
55.135 + {
55.136 + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)my_addr;
55.137 + Ipv6Address ipv6;
55.138 + ipv6.Set ((uint8_t *)addr->sin6_addr.s6_addr);
55.139 + uint16_t port = ntohs (addr->sin6_port);
55.140 + Inet6SocketAddress inet = Inet6SocketAddress (ipv6, port);
55.141 + return inet;
55.142 + }
55.143 + else
55.144 + {
55.145 + NS_ASSERT (false);
55.146 + return Address ();
55.147 + }
55.148 }
55.149 int
55.150 UnixSocketFd::Ns3AddressToPosixAddress(const Address& nsaddr,
55.151 @@ -444,6 +555,30 @@
55.152 inet_addr->sin_addr.s_addr = htonl (ns_inetaddr.GetIpv4 ().Get ());
55.153 *addrlen = sizeof(struct sockaddr_in);
55.154 }
55.155 + else if (NetlinkSocketAddress::IsMatchingType(nsaddr))
55.156 + {
55.157 + NetlinkSocketAddress ns_nladdr = NetlinkSocketAddress::ConvertFrom(nsaddr);
55.158 + NS_ASSERT (*addrlen >= sizeof (struct sockaddr_nl));
55.159 + struct sockaddr_nl *nl_addr = (struct sockaddr_nl *)addr;
55.160 + nl_addr->nl_family = AF_NETLINK;
55.161 + nl_addr->nl_pid = ns_nladdr.GetProcessID();
55.162 + nl_addr->nl_groups = ns_nladdr.GetGroupsMask();
55.163 + *addrlen = sizeof(struct sockaddr_nl);
55.164 + return 0;
55.165 + }
55.166 + else if (Inet6SocketAddress::IsMatchingType(nsaddr))
55.167 + {
55.168 + Inet6SocketAddress ns_inet6addr = Inet6SocketAddress::ConvertFrom(nsaddr);
55.169 + if (*addrlen < sizeof (struct sockaddr_in6))
55.170 + {
55.171 + return -1;
55.172 + }
55.173 + struct sockaddr_in6 *inet6_addr = (struct sockaddr_in6 *)addr;
55.174 + inet6_addr->sin6_family = AF_INET6;
55.175 + inet6_addr->sin6_port = htons (ns_inet6addr.GetPort ());
55.176 + ns_inet6addr.GetIpv6 ().GetBytes (inet6_addr->sin6_addr.s6_addr);
55.177 + *addrlen = sizeof(struct sockaddr_in6);
55.178 + }
55.179 else
55.180 {
55.181 NS_ASSERT (false);
55.182 @@ -490,6 +625,11 @@
55.183 {
55.184 return m_recvttl == 1;
55.185 }
55.186 +bool
55.187 +UnixSocketFd::IsRecvPktInfo (void) const
55.188 +{
55.189 + return m_recvpktinfo == 1;
55.190 +}
55.191 off_t
55.192 UnixSocketFd::Lseek (off_t offset, int whence)
55.193 {
56.1 --- a/src/process-manager/unix-socket-fd.h Mon Sep 07 15:45:12 2009 +0200
56.2 +++ b/src/process-manager/unix-socket-fd.h Thu Oct 01 23:37:18 2009 +0900
56.3 @@ -49,6 +49,7 @@
56.4 Time GetSendTimeout (void);
56.5 bool IsRecvErr (void) const;
56.6 bool IsRecvTtl (void) const;
56.7 + bool IsRecvPktInfo (void) const;
56.8
56.9 Ptr<Socket> m_socket;
56.10
56.11 @@ -60,6 +61,12 @@
56.12 Time m_recvTimeout;
56.13 int m_recvttl;
56.14 int m_recverr;
56.15 + int m_recvpktinfo;
56.16 + int m_sockchecksum;
56.17 + int m_multicastloop;
56.18 + int m_unicasthops;
56.19 + int m_multicasthops;
56.20 + int m_recvhoplimit;
56.21 };
56.22
56.23 } // namespace ns3
57.1 --- a/src/process-manager/utils.cc Mon Sep 07 15:45:12 2009 +0200
57.2 +++ b/src/process-manager/utils.cc Thu Oct 01 23:37:18 2009 +0900
57.3 @@ -52,7 +52,8 @@
57.4 ::DIR *dir = ::opendir (nodeDir.c_str ());
57.5 if (dir == 0)
57.6 {
57.7 - if (errno != ENOENT)
57.8 + ::perror("simu path");
57.9 + if (errno == ENOENT)
57.10 {
57.11 NS_FATAL_ERROR ("Could not open requested file: " << nodeDir << "/" << path <<
57.12 ": directory does not exist: " << nodeDir);
58.1 --- a/wscript Mon Sep 07 15:45:12 2009 +0200
58.2 +++ b/wscript Thu Oct 01 23:37:18 2009 +0900
58.3 @@ -430,7 +430,7 @@
58.4 program.env.append_value('LINKFLAGS', '-fpie')
58.5 return program
58.6
58.7 -def create_ns3_program(bld, name, dependencies=('simulator',)):
58.8 +def create_ns3_program(bld, name, dependencies=('simulator', )):
58.9 program = bld.new_task_gen('cxx', 'program')
58.10 program.is_ns3_program = True
58.11 program.name = name
58.12 @@ -458,6 +458,12 @@
58.13 obj.find_sources_in_dirs('.')
58.14 obj.target = filename
58.15 obj.name = obj.target
58.16 +# obj.add_objects.append('ns3-visualizer')
58.17 +# modules = bld.env['NS3_ENABLED_MODULES']
58.18 +# modules.append('ns3-visualizer')
58.19 +# obj.uselib_local = 'ns3-visualizer'
58.20 +# obj.add_objects = 'ns3-visualizer'
58.21 +# obj.uselib = 'png'
58.22 elif filename.endswith(".cc"):
58.23 name = filename[:-len(".cc")]
58.24 obj = bld.create_ns3_program(name, all_modules)
58.25 @@ -465,6 +471,10 @@
58.26 obj.source = filename
58.27 obj.target = name
58.28 obj.name = obj.target
58.29 +# obj.add_objects += ' visualizer'
58.30 +# obj.uselib_local += ' visualizer'
58.31 +# obj.add_objects += ' visualizer'
58.32 +# obj.uselib_local += ' visualizer'
58.33
58.34
58.35 def build(bld):
58.36 @@ -550,6 +560,9 @@
58.37 lib.add_objects = list(env['NS3_MODULES'])
58.38 lib.uselib_local = list(env['NS3_MODULES'])
58.39
58.40 + lib.add_objects.append('ns3-visualizer')
58.41 + lib.uselib_local.append('ns3-visualizer')
58.42 +
58.43 bld.add_subdirs('bindings/python')
58.44
58.45 if Options.options.run:
59.1 --- a/wutils.py Mon Sep 07 15:45:12 2009 +0200
59.2 +++ b/wutils.py Thu Oct 01 23:37:18 2009 +0900
59.3 @@ -107,10 +107,13 @@
59.4 proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']))
59.5
59.6 pymoddir = bld.path.find_dir('bindings/python').abspath(env)
59.7 + pyvizdir = bld.path.find_dir('src/contrib').abspath()
59.8 + python_path_add = [pymoddir, pyvizdir]
59.9 +
59.10 if 'PYTHONPATH' in proc_env:
59.11 - proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir] + [proc_env['PYTHONPATH']])
59.12 + proc_env['PYTHONPATH'] = os.pathsep.join(python_path_add + [proc_env['PYTHONPATH']])
59.13 else:
59.14 - proc_env['PYTHONPATH'] = pymoddir
59.15 + proc_env['PYTHONPATH'] = os.pathsep.join(python_path_add)
59.16
59.17 return proc_env
59.18
