ns-3-simu_zebra_ipv6-2nd

changeset 4775:fc2c29a13125

After support for TD/NINA on zebra-0.95
author tazaki@vmlinux-zak
date Thu Oct 01 23:37:18 2009 +0900 (2 years ago)
parents 86acc8e9b3e6
children bd7211da3ecd
files .hgignore bindings/python/ns3_module_contrib.py bindings/python/wscript src/contrib/wscript src/helper/internet-stack-helper.cc src/helper/ipv6-interface-container.cc src/helper/netlink-socket-helper.cc src/helper/netlink-socket-helper.h src/helper/node-container.cc src/helper/node-container.h src/helper/wscript src/internet-stack/ipv6-l3-protocol.cc src/internet-stack/ipv6-l3-protocol.h src/internet-stack/ipv6-raw-socket-impl.cc src/internet-stack/ipv6-raw-socket-impl.h src/internet-stack/tcp6-l4-protocol.cc src/internet-stack/tcp6-l4-protocol.h src/internet-stack/tcp6-socket-factory-impl.cc src/internet-stack/tcp6-socket-factory-impl.h src/internet-stack/tcp6-socket-impl.cc src/internet-stack/tcp6-socket-impl.h src/internet-stack/wscript src/mobility/oneway-mobility-model.cc src/mobility/oneway-mobility-model.h src/mobility/wscript src/node/ipv6-address.cc src/node/ipv6-address.h src/node/netlink-attribute.cc src/node/netlink-attribute.h src/node/netlink-ipv6-routing-table.cc src/node/netlink-ipv6-routing-table.h src/node/netlink-message-route.cc src/node/netlink-message-route.h src/node/netlink-message.cc src/node/netlink-message.h src/node/netlink-socket-address.cc src/node/netlink-socket-address.h src/node/netlink-socket-factory.cc src/node/netlink-socket-factory.h src/node/netlink-socket-test.cc src/node/netlink-socket.cc src/node/netlink-socket.h src/node/node.cc src/node/socket.cc src/node/socket.h src/node/tcp6-socket-factory.cc src/node/tcp6-socket-factory.h src/node/wscript src/process-manager/libc-simu.c src/process-manager/libc.c src/process-manager/libc.h src/process-manager/simu-fd.cc src/process-manager/simu-stdio.cc src/process-manager/unix-datagram-socket-fd.cc src/process-manager/unix-socket-fd.cc src/process-manager/unix-socket-fd.h src/process-manager/utils.cc wscript wutils.py
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