diff --git a/bindings/python/ns3_module_core.py b/bindings/python/ns3_module_core.py index 5f2250b16..92599fd5c 100644 --- a/bindings/python/ns3_module_core.py +++ b/bindings/python/ns3_module_core.py @@ -2025,6 +2025,10 @@ def register_functions(root_module): module.add_function('MakeStringChecker', 'ns3::Ptr< ns3::AttributeChecker const >', []) + ## type-id.h: extern ns3::Ptr ns3::MakeTypeIdChecker() [free function] + module.add_function('MakeTypeIdChecker', + 'ns3::Ptr< ns3::AttributeChecker const >', + []) ## ptr.h: extern ns3::Ptr ns3::Create() [free function] module.add_function('Create', 'ns3::Ptr< ns3::PointerValue >', @@ -2039,10 +2043,6 @@ def register_functions(root_module): module.add_function('LogComponentEnableAll', 'void', [param('ns3::LogLevel', 'level')]) - ## type-id.h: extern ns3::Ptr ns3::MakeTypeIdChecker() [free function] - module.add_function('MakeTypeIdChecker', - 'ns3::Ptr< ns3::AttributeChecker const >', - []) ## object-factory.h: extern ns3::Ptr ns3::MakeObjectFactoryChecker() [free function] module.add_function('MakeObjectFactoryChecker', 'ns3::Ptr< ns3::AttributeChecker const >', diff --git a/bindings/python/ns3_module_internet_stack.py b/bindings/python/ns3_module_internet_stack.py index 439307348..687d37841 100644 --- a/bindings/python/ns3_module_internet_stack.py +++ b/bindings/python/ns3_module_internet_stack.py @@ -3,6 +3,20 @@ from pybindgen import Module, FileCodeSink, param, retval, cppclass def register_types(module): root_module = module.get_root() + ## icmpv4.h: ns3::Icmpv4DestinationUnreachable [class] + module.add_class('Icmpv4DestinationUnreachable', parent=root_module['ns3::Header']) + ## icmpv4.h: ns3::Icmpv4DestinationUnreachable [enumeration] + module.add_enum('', ['NET_UNREACHABLE', 'HOST_UNREACHABLE', 'PROTOCOL_UNREACHABLE', 'PORT_UNREACHABLE', 'FRAG_NEEDED', 'SOURCE_ROUTE_FAILED'], outer_class=root_module['ns3::Icmpv4DestinationUnreachable']) + ## icmpv4.h: ns3::Icmpv4Echo [class] + module.add_class('Icmpv4Echo', parent=root_module['ns3::Header']) + ## icmpv4.h: ns3::Icmpv4Header [class] + module.add_class('Icmpv4Header', parent=root_module['ns3::Header']) + ## icmpv4.h: ns3::Icmpv4Header [enumeration] + module.add_enum('', ['ECHO_REPLY', 'DEST_UNREACH', 'ECHO', 'TIME_EXCEEDED'], outer_class=root_module['ns3::Icmpv4Header']) + ## icmpv4.h: ns3::Icmpv4TimeExceeded [class] + module.add_class('Icmpv4TimeExceeded', parent=root_module['ns3::Header']) + ## icmpv4.h: ns3::Icmpv4TimeExceeded [enumeration] + module.add_enum('', ['TIME_TO_LIVE', 'FRAGMENT_REASSEMBLY'], outer_class=root_module['ns3::Icmpv4TimeExceeded']) ## tcp-header.h: ns3::TcpHeader [class] module.add_class('TcpHeader', parent=root_module['ns3::Header']) ## tcp-header.h: ns3::TcpHeader::Flags_t [enumeration] @@ -57,6 +71,10 @@ def register_types_ns3_olsr(module): def register_methods(root_module): + register_Ns3Icmpv4DestinationUnreachable_methods(root_module, root_module['ns3::Icmpv4DestinationUnreachable']) + register_Ns3Icmpv4Echo_methods(root_module, root_module['ns3::Icmpv4Echo']) + register_Ns3Icmpv4Header_methods(root_module, root_module['ns3::Icmpv4Header']) + register_Ns3Icmpv4TimeExceeded_methods(root_module, root_module['ns3::Icmpv4TimeExceeded']) register_Ns3TcpHeader_methods(root_module, root_module['ns3::TcpHeader']) register_Ns3UdpHeader_methods(root_module, root_module['ns3::UdpHeader']) register_Ns3Ipv4Interface_methods(root_module, root_module['ns3::Ipv4Interface']) @@ -64,6 +82,248 @@ def register_methods(root_module): register_Ns3Ipv4StaticRouting_methods(root_module, root_module['ns3::Ipv4StaticRouting']) return +def register_Ns3Icmpv4DestinationUnreachable_methods(root_module, cls): + ## icmpv4.h: ns3::Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable(ns3::Icmpv4DestinationUnreachable const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Icmpv4DestinationUnreachable const &', 'arg0')]) + ## icmpv4.h: static ns3::TypeId ns3::Icmpv4DestinationUnreachable::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## icmpv4.h: ns3::Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable() [constructor] + cls.add_constructor([]) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetNextHopMtu(uint16_t mtu) [member function] + cls.add_method('SetNextHopMtu', + 'void', + [param('uint16_t', 'mtu')]) + ## icmpv4.h: uint16_t ns3::Icmpv4DestinationUnreachable::GetNextHopMtu() const [member function] + cls.add_method('GetNextHopMtu', + 'uint16_t', + [], + is_const=True) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetData(ns3::Ptr data) [member function] + cls.add_method('SetData', + 'void', + [param('ns3::Ptr< ns3::Packet const >', 'data')]) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::SetHeader(ns3::Ipv4Header header) [member function] + cls.add_method('SetHeader', + 'void', + [param('ns3::Ipv4Header', 'header')]) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::GetData(uint8_t * payload) const [member function] + cls.add_method('GetData', + 'void', + [param('uint8_t *', 'payload')], + is_const=True) + ## icmpv4.h: ns3::Ipv4Header ns3::Icmpv4DestinationUnreachable::GetHeader() const [member function] + cls.add_method('GetHeader', + 'ns3::Ipv4Header', + [], + is_const=True) + ## icmpv4.h: ns3::TypeId ns3::Icmpv4DestinationUnreachable::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, visibility='private', is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4DestinationUnreachable::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, visibility='private', is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, visibility='private', is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4DestinationUnreachable::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + visibility='private', is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4DestinationUnreachable::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, visibility='private', is_virtual=True) + return + +def register_Ns3Icmpv4Echo_methods(root_module, cls): + ## icmpv4.h: ns3::Icmpv4Echo::Icmpv4Echo(ns3::Icmpv4Echo const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Icmpv4Echo const &', 'arg0')]) + ## icmpv4.h: void ns3::Icmpv4Echo::SetIdentifier(uint16_t id) [member function] + cls.add_method('SetIdentifier', + 'void', + [param('uint16_t', 'id')]) + ## icmpv4.h: void ns3::Icmpv4Echo::SetSequenceNumber(uint16_t seq) [member function] + cls.add_method('SetSequenceNumber', + 'void', + [param('uint16_t', 'seq')]) + ## icmpv4.h: void ns3::Icmpv4Echo::SetData(ns3::Ptr data) [member function] + cls.add_method('SetData', + 'void', + [param('ns3::Ptr< ns3::Packet const >', 'data')]) + ## icmpv4.h: uint16_t ns3::Icmpv4Echo::GetIdentifier() const [member function] + cls.add_method('GetIdentifier', + 'uint16_t', + [], + is_const=True) + ## icmpv4.h: uint16_t ns3::Icmpv4Echo::GetSequenceNumber() const [member function] + cls.add_method('GetSequenceNumber', + 'uint16_t', + [], + is_const=True) + ## icmpv4.h: ns3::Ptr ns3::Icmpv4Echo::GetData() const [member function] + cls.add_method('GetData', + 'ns3::Ptr< ns3::Packet const >', + [], + is_const=True) + ## icmpv4.h: static ns3::TypeId ns3::Icmpv4Echo::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## icmpv4.h: ns3::Icmpv4Echo::Icmpv4Echo() [constructor] + cls.add_constructor([]) + ## icmpv4.h: ns3::TypeId ns3::Icmpv4Echo::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4Echo::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4Echo::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4Echo::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4Echo::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + return + +def register_Ns3Icmpv4Header_methods(root_module, cls): + ## icmpv4.h: ns3::Icmpv4Header::Icmpv4Header(ns3::Icmpv4Header const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Icmpv4Header const &', 'arg0')]) + ## icmpv4.h: void ns3::Icmpv4Header::EnableChecksum() [member function] + cls.add_method('EnableChecksum', + 'void', + []) + ## icmpv4.h: void ns3::Icmpv4Header::SetType(uint8_t type) [member function] + cls.add_method('SetType', + 'void', + [param('uint8_t', 'type')]) + ## icmpv4.h: void ns3::Icmpv4Header::SetCode(uint8_t code) [member function] + cls.add_method('SetCode', + 'void', + [param('uint8_t', 'code')]) + ## icmpv4.h: uint8_t ns3::Icmpv4Header::GetType() const [member function] + cls.add_method('GetType', + 'uint8_t', + [], + is_const=True) + ## icmpv4.h: uint8_t ns3::Icmpv4Header::GetCode() const [member function] + cls.add_method('GetCode', + 'uint8_t', + [], + is_const=True) + ## icmpv4.h: static ns3::TypeId ns3::Icmpv4Header::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## icmpv4.h: ns3::Icmpv4Header::Icmpv4Header() [constructor] + cls.add_constructor([]) + ## icmpv4.h: ns3::TypeId ns3::Icmpv4Header::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4Header::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4Header::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4Header::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4Header::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + return + +def register_Ns3Icmpv4TimeExceeded_methods(root_module, cls): + ## icmpv4.h: ns3::Icmpv4TimeExceeded::Icmpv4TimeExceeded(ns3::Icmpv4TimeExceeded const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Icmpv4TimeExceeded const &', 'arg0')]) + ## icmpv4.h: void ns3::Icmpv4TimeExceeded::SetData(ns3::Ptr data) [member function] + cls.add_method('SetData', + 'void', + [param('ns3::Ptr< ns3::Packet const >', 'data')]) + ## icmpv4.h: void ns3::Icmpv4TimeExceeded::SetHeader(ns3::Ipv4Header header) [member function] + cls.add_method('SetHeader', + 'void', + [param('ns3::Ipv4Header', 'header')]) + ## icmpv4.h: void ns3::Icmpv4TimeExceeded::GetData(uint8_t * payload) const [member function] + cls.add_method('GetData', + 'void', + [param('uint8_t *', 'payload')], + is_const=True) + ## icmpv4.h: ns3::Ipv4Header ns3::Icmpv4TimeExceeded::GetHeader() const [member function] + cls.add_method('GetHeader', + 'ns3::Ipv4Header', + [], + is_const=True) + ## icmpv4.h: static ns3::TypeId ns3::Icmpv4TimeExceeded::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## icmpv4.h: ns3::Icmpv4TimeExceeded::Icmpv4TimeExceeded() [constructor] + cls.add_constructor([]) + ## icmpv4.h: ns3::TypeId ns3::Icmpv4TimeExceeded::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4TimeExceeded::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4TimeExceeded::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## icmpv4.h: uint32_t ns3::Icmpv4TimeExceeded::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## icmpv4.h: void ns3::Icmpv4TimeExceeded::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + return + def register_Ns3TcpHeader_methods(root_module, cls): ## tcp-header.h: ns3::TcpHeader::TcpHeader(ns3::TcpHeader const & arg0) [copy constructor] cls.add_constructor([param('ns3::TcpHeader const &', 'arg0')]) @@ -354,6 +614,14 @@ def register_Ns3Ipv4L3Protocol_methods(root_module, cls): cls.add_method('SetNode', 'void', [param('ns3::Ptr< ns3::Node >', 'node')]) + ## ipv4-l3-protocol.h: ns3::Ptr ns3::Ipv4L3Protocol::CreateRawSocket() [member function] + cls.add_method('CreateRawSocket', + 'ns3::Ptr< ns3::Socket >', + []) + ## ipv4-l3-protocol.h: void ns3::Ipv4L3Protocol::DeleteRawSocket(ns3::Ptr socket) [member function] + cls.add_method('DeleteRawSocket', + 'void', + [param('ns3::Ptr< ns3::Socket >', 'socket')]) ## ipv4-l3-protocol.h: void ns3::Ipv4L3Protocol::Insert(ns3::Ptr protocol) [member function] cls.add_method('Insert', 'void', diff --git a/bindings/python/ns3_module_node.py b/bindings/python/ns3_module_node.py index 805e8747e..61c624b2d 100644 --- a/bindings/python/ns3_module_node.py +++ b/bindings/python/ns3_module_node.py @@ -67,6 +67,8 @@ def register_types(module): module.add_class('SocketFactory', parent=root_module['ns3::Object']) ## socket.h: ns3::SocketIpTtlTag [class] module.add_class('SocketIpTtlTag', parent=root_module['ns3::Tag']) + ## socket.h: ns3::SocketSetDontFragmentTag [class] + module.add_class('SocketSetDontFragmentTag', parent=root_module['ns3::Tag']) ## tcp-socket.h: ns3::TcpSocket [class] module.add_class('TcpSocket', parent=root_module['ns3::Socket']) ## tcp-socket-factory.h: ns3::TcpSocketFactory [class] @@ -91,6 +93,8 @@ def register_types(module): module.add_class('EthernetTrailer', parent=root_module['ns3::Trailer']) ## ipv4.h: ns3::Ipv4 [class] module.add_class('Ipv4', parent=root_module['ns3::Object']) + ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory [class] + module.add_class('Ipv4RawSocketFactory', parent=root_module['ns3::SocketFactory']) ## ipv4.h: ns3::Ipv4RoutingProtocol [class] module.add_class('Ipv4RoutingProtocol', parent=root_module['ns3::Object']) ## net-device.h: ns3::NetDevice [class] @@ -172,6 +176,7 @@ def register_methods(root_module): register_Ns3SocketAddressTag_methods(root_module, root_module['ns3::SocketAddressTag']) register_Ns3SocketFactory_methods(root_module, root_module['ns3::SocketFactory']) register_Ns3SocketIpTtlTag_methods(root_module, root_module['ns3::SocketIpTtlTag']) + register_Ns3SocketSetDontFragmentTag_methods(root_module, root_module['ns3::SocketSetDontFragmentTag']) register_Ns3TcpSocket_methods(root_module, root_module['ns3::TcpSocket']) register_Ns3TcpSocketFactory_methods(root_module, root_module['ns3::TcpSocketFactory']) register_Ns3UdpSocket_methods(root_module, root_module['ns3::UdpSocket']) @@ -184,6 +189,7 @@ def register_methods(root_module): register_Ns3EthernetHeader_methods(root_module, root_module['ns3::EthernetHeader']) register_Ns3EthernetTrailer_methods(root_module, root_module['ns3::EthernetTrailer']) register_Ns3Ipv4_methods(root_module, root_module['ns3::Ipv4']) + register_Ns3Ipv4RawSocketFactory_methods(root_module, root_module['ns3::Ipv4RawSocketFactory']) register_Ns3Ipv4RoutingProtocol_methods(root_module, root_module['ns3::Ipv4RoutingProtocol']) register_Ns3NetDevice_methods(root_module, root_module['ns3::NetDevice']) register_Ns3Node_methods(root_module, root_module['ns3::Node']) @@ -1507,6 +1513,56 @@ def register_Ns3SocketIpTtlTag_methods(root_module, cls): is_const=True, is_virtual=True) return +def register_Ns3SocketSetDontFragmentTag_methods(root_module, cls): + ## socket.h: ns3::SocketSetDontFragmentTag::SocketSetDontFragmentTag(ns3::SocketSetDontFragmentTag const & arg0) [copy constructor] + cls.add_constructor([param('ns3::SocketSetDontFragmentTag const &', 'arg0')]) + ## socket.h: ns3::SocketSetDontFragmentTag::SocketSetDontFragmentTag() [constructor] + cls.add_constructor([]) + ## socket.h: void ns3::SocketSetDontFragmentTag::Enable() [member function] + cls.add_method('Enable', + 'void', + []) + ## socket.h: void ns3::SocketSetDontFragmentTag::Disable() [member function] + cls.add_method('Disable', + 'void', + []) + ## socket.h: bool ns3::SocketSetDontFragmentTag::IsEnabled() const [member function] + cls.add_method('IsEnabled', + 'bool', + [], + is_const=True) + ## socket.h: static ns3::TypeId ns3::SocketSetDontFragmentTag::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## socket.h: ns3::TypeId ns3::SocketSetDontFragmentTag::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## socket.h: uint32_t ns3::SocketSetDontFragmentTag::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## socket.h: void ns3::SocketSetDontFragmentTag::Serialize(ns3::TagBuffer i) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::TagBuffer', 'i')], + is_const=True, is_virtual=True) + ## socket.h: void ns3::SocketSetDontFragmentTag::Deserialize(ns3::TagBuffer i) [member function] + cls.add_method('Deserialize', + 'void', + [param('ns3::TagBuffer', 'i')], + is_virtual=True) + ## socket.h: void ns3::SocketSetDontFragmentTag::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + return + def register_Ns3TcpSocket_methods(root_module, cls): ## tcp-socket.h: ns3::TcpSocket::TcpSocket(ns3::TcpSocket const & arg0) [copy constructor] cls.add_constructor([param('ns3::TcpSocket const &', 'arg0')]) @@ -1661,6 +1717,16 @@ def register_Ns3UdpSocket_methods(root_module, cls): 'uint32_t', [], is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True) + ## udp-socket.h: void ns3::UdpSocket::SetMtuDiscover(bool discover) [member function] + cls.add_method('SetMtuDiscover', + 'void', + [param('bool', 'discover')], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## udp-socket.h: bool ns3::UdpSocket::GetMtuDiscover() const [member function] + cls.add_method('GetMtuDiscover', + 'bool', + [], + is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True) return def register_Ns3UdpSocketFactory_methods(root_module, cls): @@ -2167,6 +2233,18 @@ def register_Ns3Ipv4_methods(root_module, cls): is_virtual=True) return +def register_Ns3Ipv4RawSocketFactory_methods(root_module, cls): + ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory::Ipv4RawSocketFactory(ns3::Ipv4RawSocketFactory const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Ipv4RawSocketFactory const &', 'arg0')]) + ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory::Ipv4RawSocketFactory() [constructor] + cls.add_constructor([]) + ## ipv4-raw-socket-factory.h: static ns3::TypeId ns3::Ipv4RawSocketFactory::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + return + def register_Ns3Ipv4RoutingProtocol_methods(root_module, cls): ## ipv4.h: ns3::Ipv4RoutingProtocol::IF_INDEX_ANY [variable] cls.add_static_attribute('IF_INDEX_ANY', 'uint32_t const', is_const=True) diff --git a/src/internet-stack/arp-ipv4-interface.cc b/src/internet-stack/arp-ipv4-interface.cc index 457079bd4..90fc2a019 100644 --- a/src/internet-stack/arp-ipv4-interface.cc +++ b/src/internet-stack/arp-ipv4-interface.cc @@ -65,7 +65,6 @@ void ArpIpv4Interface::DoDispose (void) { NS_LOG_FUNCTION (this); - m_node = 0; m_device = 0; m_cache = 0; Ipv4Interface::DoDispose (); @@ -107,6 +106,17 @@ ArpIpv4Interface::SendTo (Ptr p, Ipv4Address dest) NS_LOG_FUNCTION (this << p << dest); NS_ASSERT (GetDevice () != 0); + if (dest == GetAddress ()) + { + Ptr ipv4 = m_node->GetObject (); + + ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, + GetDevice ()->GetBroadcast (), + GetDevice ()->GetBroadcast (), + NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here + ); + return; + } if (m_device->NeedsArp ()) { NS_LOG_LOGIC ("Needs ARP"); diff --git a/src/internet-stack/icmpv4-l4-protocol.cc b/src/internet-stack/icmpv4-l4-protocol.cc new file mode 100644 index 000000000..751024695 --- /dev/null +++ b/src/internet-stack/icmpv4-l4-protocol.cc @@ -0,0 +1,223 @@ +#include "icmpv4-l4-protocol.h" +#include "ipv4-interface.h" +#include "ipv4-l3-protocol.h" +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/packet.h" +#include "ns3/boolean.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("Icmpv4L4Protocol"); + +NS_OBJECT_ENSURE_REGISTERED (Icmpv4L4Protocol); + + // see rfc 792 +enum { + ICMP_PROTOCOL = 1 +}; + +TypeId +Icmpv4L4Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol") + .SetParent () + .AddConstructor () + .AddAttribute ("CalcChecksum", + "Control whether the icmp header checksum is calculated and stored in outgoing icmpv4 headers", + BooleanValue (false), + MakeBooleanAccessor (&Icmpv4L4Protocol::m_calcChecksum), + MakeBooleanChecker ()) + ; + return tid; +} + +Icmpv4L4Protocol::Icmpv4L4Protocol () + : m_node (0) +{} +Icmpv4L4Protocol::~Icmpv4L4Protocol () +{ + NS_ASSERT (m_node == 0); +} + +void +Icmpv4L4Protocol::SetNode (Ptr node) +{ + m_node = node; +} + +uint16_t +Icmpv4L4Protocol::GetStaticProtocolNumber (void) +{ + return ICMP_PROTOCOL; +} + +int +Icmpv4L4Protocol::GetProtocolNumber (void) const +{ + return ICMP_PROTOCOL; +} +void +Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address dest, uint8_t type, uint8_t code) +{ + Ptr ipv4 = m_node->GetObject (); + uint32_t i; + if (!ipv4->GetIfIndexForDestination (dest, i)) + { + NS_LOG_WARN ("drop icmp message"); + return; + } + Ipv4Address source = ipv4->GetAddress (i); + SendMessage (packet, source, dest, type, code); +} + +void +Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code) +{ + Ptr ipv4 = m_node->GetObject (); + Icmpv4Header icmp; + icmp.SetType (type); + icmp.SetCode (code); + if (m_calcChecksum) + { + icmp.EnableChecksum (); + } + packet->AddHeader (icmp); + ipv4->Send (packet, source, dest, ICMP_PROTOCOL); +} +void +Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header, + Ptr orgData, + uint16_t nextHopMtu) +{ + NS_LOG_FUNCTION (this << header << *orgData << nextHopMtu); + SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::FRAG_NEEDED, nextHopMtu); +} +void +Icmpv4L4Protocol::SendDestUnreachPort (Ipv4Header header, + Ptr orgData) +{ + NS_LOG_FUNCTION (this << header << *orgData); + SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::PORT_UNREACHABLE, 0); +} +void +Icmpv4L4Protocol::SendDestUnreach (Ipv4Header header, Ptr orgData, + uint8_t code, uint16_t nextHopMtu) +{ + NS_LOG_FUNCTION (this << header << *orgData << (uint32_t) code << nextHopMtu); + Ptr p = Create (); + Icmpv4DestinationUnreachable unreach; + unreach.SetNextHopMtu (nextHopMtu); + unreach.SetHeader (header); + unreach.SetData (orgData); + p->AddHeader (unreach); + SendMessage (p, header.GetSource (), Icmpv4Header::DEST_UNREACH, code); +} + +void +Icmpv4L4Protocol::SendTimeExceededTtl (Ipv4Header header, Ptr orgData) +{ + NS_LOG_FUNCTION (this << header << *orgData); + Ptr p = Create (); + Icmpv4TimeExceeded time; + time.SetHeader (header); + time.SetData (orgData); + p->AddHeader (time); + SendMessage (p, header.GetSource (), Icmpv4Header::TIME_EXCEEDED, Icmpv4TimeExceeded::TIME_TO_LIVE); +} + +void +Icmpv4L4Protocol::HandleEcho (Ptr p, + Icmpv4Header header, + Ipv4Address source, + Ipv4Address destination) +{ + NS_LOG_FUNCTION (this << p << header << source << destination); + + Ptr reply = Create (); + Icmpv4Echo echo; + p->RemoveHeader (echo); + reply->AddHeader (echo); + SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0); +} +void +Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp, + uint32_t info, Ipv4Header ipHeader, + const uint8_t payload[8]) +{ + Ptr ipv4 = m_node->GetObject (); + Ptr l4 = ipv4->GetProtocol (ipHeader.GetProtocol ()); + if (l4 != 0) + { + l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (), + info, ipHeader.GetSource (), ipHeader.GetDestination (), payload); + } +} +void +Icmpv4L4Protocol::HandleDestUnreach (Ptr p, + Icmpv4Header icmp, + Ipv4Address source, + Ipv4Address destination) +{ + NS_LOG_FUNCTION (this << p << icmp << source << destination); + + Icmpv4DestinationUnreachable unreach; + p->PeekHeader (unreach); + uint8_t payload[8]; + unreach.GetData (payload); + Ipv4Header ipHeader = unreach.GetHeader (); + Forward (source, icmp, unreach.GetNextHopMtu (), ipHeader, payload); +} +void +Icmpv4L4Protocol::HandleTimeExceeded (Ptr p, + Icmpv4Header icmp, + Ipv4Address source, + Ipv4Address destination) +{ + NS_LOG_FUNCTION (this << p << icmp << source << destination); + + Icmpv4TimeExceeded time; + p->PeekHeader (time); + uint8_t payload[8]; + time.GetData (payload); + Ipv4Header ipHeader = time.GetHeader (); + // info field is zero for TimeExceeded on linux + Forward (source, icmp, 0, ipHeader, payload); +} + +enum Ipv4L4Protocol::RxStatus +Icmpv4L4Protocol::Receive(Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface) +{ + NS_LOG_FUNCTION (this << p << source << destination << incomingInterface); + + Icmpv4Header icmp; + p->RemoveHeader (icmp); + switch (icmp.GetType ()) { + case Icmpv4Header::ECHO: + HandleEcho (p, icmp, source, destination); + break; + case Icmpv4Header::DEST_UNREACH: + HandleDestUnreach (p, icmp, source, destination); + break; + case Icmpv4Header::TIME_EXCEEDED: + HandleTimeExceeded (p, icmp, source, destination); + break; + default: + NS_LOG_DEBUG (icmp << " " << *p); + break; + } + return Ipv4L4Protocol::RX_OK; +} +void +Icmpv4L4Protocol::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_node = 0; + Ipv4L4Protocol::DoDispose (); +} + +} // namespace ns3 diff --git a/src/internet-stack/icmpv4-l4-protocol.h b/src/internet-stack/icmpv4-l4-protocol.h new file mode 100644 index 000000000..71310f84d --- /dev/null +++ b/src/internet-stack/icmpv4-l4-protocol.h @@ -0,0 +1,62 @@ +#ifndef ICMPV4_L4_PROTOCOL_H +#define ICMPV4_L4_PROTOCOL_H + +#include "ipv4-l4-protocol.h" +#include "icmpv4.h" +#include "ns3/ipv4-address.h" + +namespace ns3 { + +class Node; +class Ipv4Interface; + +class Icmpv4L4Protocol : public Ipv4L4Protocol +{ +public: + static TypeId GetTypeId (void); + Icmpv4L4Protocol (); + virtual ~Icmpv4L4Protocol (); + + void SetNode (Ptr node); + + static uint16_t GetStaticProtocolNumber (void); + virtual int GetProtocolNumber (void) const; + virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr p, + const Ipv4Address &source, + const Ipv4Address &destination, + Ptr incomingInterface); + + void SendDestUnreachFragNeeded (Ipv4Header header, Ptr orgData, uint16_t nextHopMtu); + void SendTimeExceededTtl (Ipv4Header header, Ptr orgData); + void SendDestUnreachPort (Ipv4Header header, Ptr orgData); + +private: + void HandleEcho (Ptr p, + Icmpv4Header header, + Ipv4Address source, + Ipv4Address destination); + void HandleDestUnreach (Ptr p, + Icmpv4Header header, + Ipv4Address source, + Ipv4Address destination); + void HandleTimeExceeded (Ptr p, + Icmpv4Header icmp, + Ipv4Address source, + Ipv4Address destination); + void SendDestUnreach (Ipv4Header header, Ptr orgData, + uint8_t code, uint16_t nextHopMtu); + void SendMessage (Ptr packet, Ipv4Address dest, uint8_t type, uint8_t code); + void SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code); + void Forward (Ipv4Address source, Icmpv4Header icmp, + uint32_t info, Ipv4Header ipHeader, + const uint8_t payload[8]); + + virtual void DoDispose (void); + + Ptr m_node; + bool m_calcChecksum; +}; + +} // namespace ns3 + +#endif /* ICMPV4_L4_PROTOCOL_H */ diff --git a/src/internet-stack/icmpv4.cc b/src/internet-stack/icmpv4.cc new file mode 100644 index 000000000..b0b2cfec9 --- /dev/null +++ b/src/internet-stack/icmpv4.cc @@ -0,0 +1,387 @@ +#include "icmpv4.h" +#include "ns3/packet.h" + +namespace ns3 { + +/******************************************************** + * Icmpv4Header + ********************************************************/ + +TypeId +Icmpv4Header::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Icmpv4Header") + .SetParent
() + .AddConstructor () + ; + return tid; +} +Icmpv4Header::Icmpv4Header () + : m_type (0), + m_code (0), + m_calcChecksum (false) +{} +Icmpv4Header::~Icmpv4Header () +{} +void +Icmpv4Header::EnableChecksum (void) +{ + m_calcChecksum = true; +} +TypeId +Icmpv4Header::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +Icmpv4Header::GetSerializedSize (void) const +{ + return 4; +} +void +Icmpv4Header::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + i.WriteU8 (m_type); + i.WriteU8 (m_code); + i.WriteHtonU16 (0); + if (m_calcChecksum) + { + i = start; + uint16_t checksum = i.CalculateIpChecksum (i.GetSize ()); + i = start; + i.Next (2); + i.WriteU16 (checksum); + } + +} +uint32_t +Icmpv4Header::Deserialize (Buffer::Iterator start) +{ + m_type = start.ReadU8 (); + m_code = start.ReadU8 (); + uint16_t checksum; + checksum = start.ReadNtohU16 (); + return 4; +} +void +Icmpv4Header::Print (std::ostream &os) const +{ + os << "type=" << (uint32_t)m_type << ", code=" << (uint32_t)m_code; +} + +void +Icmpv4Header::SetType (uint8_t type) +{ + m_type = type; +} +void +Icmpv4Header::SetCode (uint8_t code) +{ + m_code = code; +} +uint8_t +Icmpv4Header::GetType (void) const +{ + return m_type; +} +uint8_t +Icmpv4Header::GetCode (void) const +{ + return m_code; +} + +/******************************************************** + * Icmpv4Echo + ********************************************************/ + +void +Icmpv4Echo::SetIdentifier (uint16_t id) +{ + m_identifier = id; +} +void +Icmpv4Echo::SetSequenceNumber (uint16_t seq) +{ + m_sequence = seq; +} +void +Icmpv4Echo::SetData (Ptr data) +{ + m_data = data->Copy (); +} +uint16_t +Icmpv4Echo::GetIdentifier (void) const +{ + return m_identifier; +} +uint16_t +Icmpv4Echo::GetSequenceNumber (void) const +{ + return m_sequence; +} +Ptr +Icmpv4Echo::GetData (void) const +{ + return m_data->Copy (); +} + + +TypeId +Icmpv4Echo::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Icmpv4Echo") + .SetParent
() + .AddConstructor () + ; + return tid; +} +Icmpv4Echo::Icmpv4Echo () + : m_identifier (0), + m_sequence (0), + m_data (0) +{} +Icmpv4Echo::~Icmpv4Echo () +{} +TypeId +Icmpv4Echo::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +Icmpv4Echo::GetSerializedSize (void) const +{ + return 4 + m_data->GetSize (); +} +void +Icmpv4Echo::Serialize (Buffer::Iterator start) const +{ + start.WriteHtonU16 (m_identifier); + start.WriteHtonU16 (m_sequence); + start.Write (m_data->PeekData (), m_data->GetSize ()); +} +uint32_t +Icmpv4Echo::Deserialize (Buffer::Iterator start) +{ + m_identifier = start.ReadNtohU16 (); + m_sequence = start.ReadNtohU16 (); + NS_ASSERT (start.GetSize () >= 4); + uint32_t size = start.GetSize () - 4; + uint8_t *buffer = new uint8_t[size] (); + start.Read (buffer, size); + m_data = Create (buffer, size); + delete[] buffer; + return start.GetSize (); +} +void +Icmpv4Echo::Print (std::ostream &os) const +{ + os << "identifier=" << m_identifier << ", sequence=" << m_sequence; +} + + +/******************************************************** + * Icmpv4DestinationUnreachable + ********************************************************/ + +TypeId +Icmpv4DestinationUnreachable::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Icmpv4DestinationUnreachable") + .SetParent
() + .AddConstructor () + ; + return tid; +} +Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable () +{ + // make sure that thing is initialized to get initialized bytes + // when the ip payload's size is smaller than 8 bytes. + for (uint8_t j = 0; j < 8; j++) + { + m_data[j] = 0; + } +} + +void +Icmpv4DestinationUnreachable::SetNextHopMtu (uint16_t mtu) +{ + m_nextHopMtu = mtu; +} +uint16_t +Icmpv4DestinationUnreachable::GetNextHopMtu (void) const +{ + return m_nextHopMtu; +} + +void +Icmpv4DestinationUnreachable::SetData (Ptr data) +{ + data->CopyData (m_data, 8); +} +void +Icmpv4DestinationUnreachable::SetHeader (Ipv4Header header) +{ + m_header = header; +} +void +Icmpv4DestinationUnreachable::GetData (uint8_t payload[8]) const +{ + memcpy (payload, m_data, 8); +} +Ipv4Header +Icmpv4DestinationUnreachable::GetHeader (void) const +{ + return m_header; +} + + +Icmpv4DestinationUnreachable::~Icmpv4DestinationUnreachable () +{} +TypeId +Icmpv4DestinationUnreachable::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +Icmpv4DestinationUnreachable::GetSerializedSize (void) const +{ + return 4 + m_header.GetSerializedSize () + 8; +} +void +Icmpv4DestinationUnreachable::Serialize (Buffer::Iterator start) const +{ + start.WriteU16 (0); + start.WriteHtonU16 (m_nextHopMtu); + uint32_t size = m_header.GetSerializedSize (); + m_header.Serialize (start); + start.Next (size); + start.Write (m_data, 8); +} + +uint32_t +Icmpv4DestinationUnreachable::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + i.Next (2); + m_nextHopMtu = i.ReadNtohU16 (); + uint32_t read = m_header.Deserialize (i); + i.Next (read); + for (uint8_t j = 0; j < 8; j++) + { + m_data[j] = i.ReadU8 (); + } + return i.GetDistanceFrom (start); +} +void +Icmpv4DestinationUnreachable::Print (std::ostream &os) const +{ + m_header.Print (os); + os << " org data="; + for (uint8_t i = 0; i < 8; i++) + { + os << (uint32_t) m_data[i]; + if (i != 8) + { + os << " "; + } + } +} + +/******************************************************** + * Icmpv4TimeExceeded + ********************************************************/ + +TypeId +Icmpv4TimeExceeded::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Icmpv4TimeExceeded") + .SetParent
() + .AddConstructor () + ; + return tid; +} +Icmpv4TimeExceeded::Icmpv4TimeExceeded () +{ + // make sure that thing is initialized to get initialized bytes + // when the ip payload's size is smaller than 8 bytes. + for (uint8_t j = 0; j < 8; j++) + { + m_data[j] = 0; + } +} + + +void +Icmpv4TimeExceeded::SetData (Ptr data) +{ + data->CopyData (m_data, 8); +} +void +Icmpv4TimeExceeded::SetHeader (Ipv4Header header) +{ + m_header = header; +} +void +Icmpv4TimeExceeded::GetData (uint8_t payload[8]) const +{ + memcpy (payload, m_data, 8); +} +Ipv4Header +Icmpv4TimeExceeded::GetHeader (void) const +{ + return m_header; +} + + +Icmpv4TimeExceeded::~Icmpv4TimeExceeded () +{} +TypeId +Icmpv4TimeExceeded::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +Icmpv4TimeExceeded::GetSerializedSize (void) const +{ + return 4 + m_header.GetSerializedSize () + 8; +} +void +Icmpv4TimeExceeded::Serialize (Buffer::Iterator start) const +{ + start.WriteU32 (0); + uint32_t size = m_header.GetSerializedSize (); + m_header.Serialize (start); + start.Next (size); + start.Write (m_data, 8); +} + +uint32_t +Icmpv4TimeExceeded::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + i.Next (4); + uint32_t read = m_header.Deserialize (i); + i.Next (read); + for (uint8_t j = 0; j < 8; j++) + { + m_data[j] = i.ReadU8 (); + } + return i.GetDistanceFrom (start); +} +void +Icmpv4TimeExceeded::Print (std::ostream &os) const +{ + m_header.Print (os); + os << " org data="; + for (uint8_t i = 0; i < 8; i++) + { + os << (uint32_t) m_data[i]; + if (i != 8) + { + os << " "; + } + } +} + +} // namespace ns3 diff --git a/src/internet-stack/icmpv4.h b/src/internet-stack/icmpv4.h new file mode 100644 index 000000000..f8d224e51 --- /dev/null +++ b/src/internet-stack/icmpv4.h @@ -0,0 +1,137 @@ +#ifndef ICMPV4_H +#define ICMPV4_H + +#include "ns3/header.h" +#include "ns3/ptr.h" +#include "ns3/ipv4-header.h" +#include + +namespace ns3 { + +class Packet; + +class Icmpv4Header : public Header +{ +public: + enum { + ECHO_REPLY = 0, + DEST_UNREACH = 3, + ECHO = 8, + TIME_EXCEEDED = 11 + }; + + void EnableChecksum (void); + void SetType (uint8_t type); + void SetCode (uint8_t code); + + uint8_t GetType (void) const; + uint8_t GetCode (void) const; + + static TypeId GetTypeId (void); + Icmpv4Header (); + virtual ~Icmpv4Header (); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; + +private: + uint8_t m_type; + uint8_t m_code; + bool m_calcChecksum; +}; + +class Icmpv4Echo : public Header +{ +public: + void SetIdentifier (uint16_t id); + void SetSequenceNumber (uint16_t seq); + void SetData (Ptr data); + uint16_t GetIdentifier (void) const; + uint16_t GetSequenceNumber (void) const; + Ptr GetData (void) const; + + + static TypeId GetTypeId (void); + Icmpv4Echo (); + virtual ~Icmpv4Echo (); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; +private: + uint16_t m_identifier; + uint16_t m_sequence; + Ptr m_data; +}; + +class Icmpv4DestinationUnreachable : public Header +{ +public: + enum { + NET_UNREACHABLE = 0, + HOST_UNREACHABLE = 1, + PROTOCOL_UNREACHABLE = 2, + PORT_UNREACHABLE = 3, + FRAG_NEEDED = 4, + SOURCE_ROUTE_FAILED = 5 + }; + static TypeId GetTypeId (void); + Icmpv4DestinationUnreachable (); + virtual ~Icmpv4DestinationUnreachable (); + + void SetNextHopMtu (uint16_t mtu); + uint16_t GetNextHopMtu (void) const; + + void SetData (Ptr data); + void SetHeader (Ipv4Header header); + + void GetData (uint8_t payload[8]) const; + Ipv4Header GetHeader (void) const; + +private: + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; +private: + uint16_t m_nextHopMtu; + Ipv4Header m_header; + uint8_t m_data[8]; +}; + + +class Icmpv4TimeExceeded : public Header +{ +public: + enum { + TIME_TO_LIVE = 0, + FRAGMENT_REASSEMBLY = 1 + }; + + void SetData (Ptr data); + void SetHeader (Ipv4Header header); + + void GetData (uint8_t payload[8]) const; + Ipv4Header GetHeader (void) const; + + static TypeId GetTypeId (void); + Icmpv4TimeExceeded (); + virtual ~Icmpv4TimeExceeded (); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + virtual void Print (std::ostream &os) const; + +private: + Ipv4Header m_header; + uint8_t m_data[8]; +}; + +} // namespace ns3 + +#endif /* ICMPV4_H */ diff --git a/src/internet-stack/internet-stack.cc b/src/internet-stack/internet-stack.cc index 83520a3c0..280f7bd6f 100644 --- a/src/internet-stack/internet-stack.cc +++ b/src/internet-stack/internet-stack.cc @@ -30,6 +30,8 @@ #include "udp-socket-factory-impl.h" #include "tcp-socket-factory-impl.h" #include "ipv4-impl.h" +#include "ipv4-raw-socket-factory-impl.h" +#include "icmpv4-l4-protocol.h" #ifdef NETWORK_SIMULATION_CRADLE #include "nsc-tcp-socket-factory-impl.h" #include "nsc-tcp-l4-protocol.h" @@ -57,13 +59,26 @@ AddUdpStack(Ptr node) node->AggregateObject (udpFactory); } +static void +AddIcmpStack (Ptr node) +{ + Ptr ipv4 = node->GetObject (); + Ptr icmp = CreateObject (); + icmp->SetNode (node); + ipv4->Insert (icmp); + Ptr rawFactory = CreateObject (); + node->AggregateObject (rawFactory); +} + static void AddTcpStack(Ptr node) { Ptr ipv4 = node->GetObject (); Ptr tcp = CreateObject (); tcp->SetNode (node); + ipv4->Insert (tcp); + Ptr tcpFactory = CreateObject (); tcpFactory->SetTcp (tcp); node->AggregateObject (tcpFactory); @@ -85,6 +100,7 @@ AddInternetStack (Ptr node) { AddArpStack (node); AddIpv4Stack (node); + AddIcmpStack (node); AddUdpStack (node); AddTcpStack (node); } @@ -109,7 +125,7 @@ AddNscInternetStack (Ptr node, const std::string &soname) { AddArpStack (node); AddIpv4Stack (node); - + AddIcmpStack (node); AddUdpStack (node); AddNscStack (node, soname); } diff --git a/src/internet-stack/ipv4-end-point-demux.cc b/src/internet-stack/ipv4-end-point-demux.cc index 54ed3fbbe..2c2ab838e 100644 --- a/src/internet-stack/ipv4-end-point-demux.cc +++ b/src/internet-stack/ipv4-end-point-demux.cc @@ -287,6 +287,47 @@ Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, return retval1; // might be empty if no matches } +Ipv4EndPoint * +Ipv4EndPointDemux::SimpleLookup (Ipv4Address daddr, + uint16_t dport, + Ipv4Address saddr, + uint16_t sport) +{ + // this code is a copy/paste version of an old BSD ip stack lookup + // function. + uint32_t genericity = 3; + Ipv4EndPoint *generic = 0; + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + if ((*i)->GetLocalPort () != dport) + { + continue; + } + if ((*i)->GetLocalAddress () == daddr && + (*i)->GetPeerPort () == sport && + (*i)->GetPeerAddress () == saddr) + { + /* this is an exact match. */ + return *i; + } + uint32_t tmp = 0; + if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ()) + { + tmp ++; + } + if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ()) + { + tmp ++; + } + if (tmp < genericity) + { + generic = (*i); + genericity = tmp; + } + } + return generic; +} + uint16_t Ipv4EndPointDemux::AllocateEphemeralPort (void) { diff --git a/src/internet-stack/ipv4-end-point-demux.h b/src/internet-stack/ipv4-end-point-demux.h index 58a417264..02a225799 100644 --- a/src/internet-stack/ipv4-end-point-demux.h +++ b/src/internet-stack/ipv4-end-point-demux.h @@ -57,6 +57,11 @@ public: uint16_t sport, Ptr incomingInterface); + Ipv4EndPoint *SimpleLookup (Ipv4Address daddr, + uint16_t dport, + Ipv4Address saddr, + uint16_t sport); + Ipv4EndPoint *Allocate (void); Ipv4EndPoint *Allocate (Ipv4Address address); Ipv4EndPoint *Allocate (uint16_t port); diff --git a/src/internet-stack/ipv4-end-point.cc b/src/internet-stack/ipv4-end-point.cc index 18b7d9930..7b0649fc3 100644 --- a/src/internet-stack/ipv4-end-point.cc +++ b/src/internet-stack/ipv4-end-point.cc @@ -20,6 +20,9 @@ #include "ipv4-end-point.h" #include "ns3/packet.h" +#include "ns3/log.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4EndPoint"); namespace ns3 { @@ -76,6 +79,11 @@ Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, uint16_t> c { m_rxCallback = callback; } +void +Ipv4EndPoint::SetIcmpCallback (Callback callback) +{ + m_icmpCallback = callback; +} void Ipv4EndPoint::SetDestroyCallback (Callback callback) @@ -92,6 +100,17 @@ Ipv4EndPoint::ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport) } } - +void +Ipv4EndPoint::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, + uint32_t icmpInfo) +{ + NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType << + (uint32_t)icmpCode << icmpInfo); + if (!m_icmpCallback.IsNull ()) + { + m_icmpCallback (icmpSource,icmpTtl,icmpType,icmpCode,icmpInfo); + } +} }; // namespace ns3 diff --git a/src/internet-stack/ipv4-end-point.h b/src/internet-stack/ipv4-end-point.h index 99666f73f..f3ef159ad 100644 --- a/src/internet-stack/ipv4-end-point.h +++ b/src/internet-stack/ipv4-end-point.h @@ -54,10 +54,19 @@ public: void SetPeer (Ipv4Address address, uint16_t port); + // Called from socket implementations to get notified about important events. void SetRxCallback (Callback, Ipv4Address, uint16_t> callback); + void SetIcmpCallback (Callback callback); void SetDestroyCallback (Callback callback); + // Called from an L4Protocol implementation to notify an endpoint of a + // packet reception. void ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport); + // Called from an L4Protocol implementation to notify an endpoint of + // an icmp message reception. + void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, + uint32_t icmpInfo); private: Ipv4Address m_localAddr; @@ -65,6 +74,7 @@ private: Ipv4Address m_peerAddr; uint16_t m_peerPort; Callback, Ipv4Address, uint16_t> m_rxCallback; + Callback m_icmpCallback; Callback m_destroyCallback; }; diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index d4defa7b9..b35269128 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -35,9 +35,11 @@ #include "ipv4-l3-protocol.h" #include "ipv4-l4-protocol.h" +#include "icmpv4-l4-protocol.h" #include "ipv4-interface.h" #include "ipv4-loopback-interface.h" #include "arp-ipv4-interface.h" +#include "ipv4-raw-socket-impl.h" NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol"); @@ -120,6 +122,30 @@ Ipv4L3Protocol::SetNode (Ptr node) SetupLoopback (); } +Ptr +Ipv4L3Protocol::CreateRawSocket (void) +{ + NS_LOG_FUNCTION (this); + Ptr socket = CreateObject (); + socket->SetNode (m_node); + m_sockets.push_back (socket); + return socket; +} +void +Ipv4L3Protocol::DeleteRawSocket (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); + for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i) + { + if ((*i) == socket) + { + m_sockets.erase (i); + return; + } + } + return; +} + void Ipv4L3Protocol::DoDispose (void) { @@ -514,6 +540,12 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr return; } + for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i) + { + Ptr socket = *i; + socket->ForwardUp (packet, ipHeader, device); + } + if (Forwarding (index, packet, ipHeader, device)) { return; @@ -522,6 +554,25 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr ForwardUp (packet, ipHeader, ipv4Interface); } +Ptr +Ipv4L3Protocol::GetIcmp (void) const +{ + Ptr prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ()); + if (prot != 0) + { + return prot->GetObject (); + } + else + { + return 0; + } +} + +bool +Ipv4L3Protocol::IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const +{ + return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask); +} void Ipv4L3Protocol::Send (Ptr packet, @@ -542,16 +593,29 @@ Ipv4L3Protocol::Send (Ptr packet, ipHeader.SetDestination (destination); ipHeader.SetProtocol (protocol); ipHeader.SetPayloadSize (packet->GetSize ()); - ipHeader.SetTtl (m_defaultTtl); - ipHeader.SetMayFragment (); ipHeader.SetIdentification (m_identification); m_identification ++; + SocketSetDontFragmentTag dfTag; + bool found = packet->FindFirstMatchingTag (dfTag); + if (found) + { + if (dfTag.IsEnabled ()) + { + ipHeader.SetDontFragment (); + } + else + { + ipHeader.SetMayFragment (); + } + } + + // Set TTL to 1 if it is a broadcast packet of any type. Otherwise, // possibly override the default TTL if the packet is tagged SocketIpTtlTag tag; - bool found = packet->FindFirstMatchingTag (tag); + found = packet->FindFirstMatchingTag (tag); if (destination.IsBroadcast ()) { @@ -564,6 +628,7 @@ Ipv4L3Protocol::Send (Ptr packet, } else { + ipHeader.SetTtl (m_defaultTtl); uint32_t ifaceIndex = 0; for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) @@ -585,10 +650,28 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr outInterface = *ifaceIter; Ptr packetCopy = packet->Copy (); - NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ()); packetCopy->AddHeader (ipHeader); - m_txTrace (packetCopy, ifaceIndex); - outInterface->Send (packetCopy, destination); + if (packetCopy->GetSize () > outInterface->GetMtu () && + ipHeader.IsDontFragment () && + IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ())) + { + Ptr icmp = GetIcmp (); + NS_ASSERT (icmp != 0); + icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ()); + m_dropTrace (packetCopy); + } + else if (packet->GetSize () > outInterface->GetMtu () && + !ipHeader.IsDontFragment ()) + { + NS_LOG_LOGIC ("Too big: need fragmentation but no frag support."); + m_dropTrace (packet); + } + else + { + NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ()); + m_txTrace (packetCopy, ifaceIndex); + outInterface->Send (packetCopy, destination); + } } } else @@ -625,17 +708,38 @@ Ipv4L3Protocol::SendRealOut (bool found, NS_LOG_LOGIC ("Send via interface " << route.GetInterface ()); Ptr outInterface = GetInterface (route.GetInterface ()); - NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ()); - m_txTrace (packet, route.GetInterface ()); - if (route.IsGateway ()) + if (packet->GetSize () > outInterface->GetMtu () && + ipHeader.IsDontFragment () && + IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ())) { - NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ()); - outInterface->Send (packet, route.GetGateway ()); - } - else + NS_LOG_LOGIC ("Too big: need fragmentation but not allowed"); + Ptr icmp = GetIcmp (); + NS_ASSERT (icmp != 0); + Ptr copyNoHeader = packet->Copy (); + Ipv4Header tmp; + copyNoHeader->RemoveHeader (tmp); + icmp->SendDestUnreachFragNeeded (ipHeader, copyNoHeader, outInterface->GetMtu ()); + m_dropTrace (packet); + } + else if (packet->GetSize () > outInterface->GetMtu () && + !ipHeader.IsDontFragment ()) { - NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); - outInterface->Send (packet, ipHeader.GetDestination ()); + NS_LOG_LOGIC ("Too big: need fragmentation but no frag support."); + m_dropTrace (packet); + } + else + { + m_txTrace (packet, route.GetInterface ()); + if (route.IsGateway ()) + { + NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ()); + outInterface->Send (packet, route.GetGateway ()); + } + else + { + NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); + outInterface->Send (packet, ipHeader.GetDestination ()); + } } } @@ -685,17 +789,6 @@ Ipv4L3Protocol::Forwarding ( NS_LOG_LOGIC ("For me (Ipv4Addr any address)"); return false; } - - if (ipHeader.GetTtl () == 1) - { - // Should send ttl expired here - // XXX - NS_LOG_LOGIC ("Not for me (TTL expired). Drop"); - m_dropTrace (packet); - return true; - } - ipHeader.SetTtl (ipHeader.GetTtl () - 1); - // // If this is a to a multicast address and this node is a member of the // indicated group we need to return false so the multicast is forwarded up. @@ -710,18 +803,39 @@ Ipv4L3Protocol::Forwarding ( // We forward with a packet copy, since forwarding may change // the packet, affecting our local delivery NS_LOG_LOGIC ("Forwarding (multicast)."); - Lookup (ifIndex, ipHeader, packet->Copy (), - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); + DoForward (ifIndex, packet->Copy (), ipHeader); return false; } - } - NS_LOG_LOGIC ("Not for me, forwarding."); - Lookup (ifIndex, ipHeader, packet, - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); - + } + + DoForward (ifIndex, packet, ipHeader); return true; } +void +Ipv4L3Protocol::DoForward (uint32_t ifIndex, + Ptr packet, + Ipv4Header ipHeader) +{ + NS_LOG_FUNCTION (this << ifIndex << packet << ipHeader); + + ipHeader.SetTtl (ipHeader.GetTtl () - 1); + if (ipHeader.GetTtl () == 0) + { + if (IsUnicast (ipHeader.GetDestination (), GetInterface (ifIndex)->GetNetworkMask ())) + { + Ptr icmp = GetIcmp (); + icmp->SendTimeExceededTtl (ipHeader, packet); + } + m_dropTrace (packet); + return; + } + NS_LOG_LOGIC ("Not for me, forwarding."); + Lookup (ifIndex, ipHeader, packet, + MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); +} + + void Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, Ptr incomingInterface) @@ -729,7 +843,26 @@ Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, NS_LOG_FUNCTION (this << p << &ip); Ptr protocol = GetProtocol (ip.GetProtocol ()); - protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); + if (protocol != 0) + { + // we need to make a copy in the unlikely event we hit the + // RX_ENDPOINT_UNREACH codepath + Ptr copy = p->Copy (); + enum Ipv4L4Protocol::RxStatus status = + protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); + switch (status) { + case Ipv4L4Protocol::RX_OK: + // fall through + case Ipv4L4Protocol::RX_CSUM_FAILED: + break; + case Ipv4L4Protocol::RX_ENDPOINT_UNREACH: + if (IsUnicast (ip.GetDestination (), incomingInterface->GetNetworkMask ())) + { + GetIcmp ()->SendDestUnreachPort (ip, copy); + } + break; + } + } } void diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index c5d59297d..6218eb8d4 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -40,7 +40,11 @@ class Ipv4Address; class Ipv4Header; class Ipv4Route; class Node; +class Socket; +class Ipv4RawSocketImpl; class Ipv4L4Protocol; +class Ipv4L4Protocol; +class Icmpv4L4Protocol; /** @@ -60,6 +64,9 @@ public: void SetNode (Ptr node); + Ptr CreateRawSocket (void); + void DeleteRawSocket (Ptr socket); + /** * \param protocol a template for the protocol to add to this L4 Demux. * \returns the L4Protocol effectively added. @@ -201,6 +208,8 @@ protected: virtual void DoDispose (void); private: + Ipv4L3Protocol(const Ipv4L3Protocol &); + Ipv4L3Protocol &operator = (const Ipv4L3Protocol &); void Lookup (uint32_t ifIndex, Ipv4Header const &ipHeader, Ptr packet, @@ -217,15 +226,19 @@ private: void ForwardUp (Ptr p, Ipv4Header const&ip, Ptr incomingInterface); uint32_t AddIpv4Interface (Ptr interface); void SetupLoopback (void); - Ipv4L3Protocol(const Ipv4L3Protocol &); - Ipv4L3Protocol &operator = (const Ipv4L3Protocol &); + Ptr GetIcmp (void) const; + bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const; + void DoForward (uint32_t ifIndex, + Ptr packet, + Ipv4Header ipHeader); + typedef std::list > Ipv4InterfaceList; - typedef std::list > - Ipv4MulticastGroupList; + typedef std::list > Ipv4MulticastGroupList; typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; - + typedef std::list > SocketList; typedef std::list > L4List_t; + L4List_t m_protocols; Ipv4InterfaceList m_interfaces; uint32_t m_nInterfaces; @@ -241,6 +254,8 @@ private: Ptr m_staticRouting; Ipv4MulticastGroupList m_multicastGroups; + + SocketList m_sockets; }; } // Namespace ns3 diff --git a/src/internet-stack/ipv4-l4-protocol.cc b/src/internet-stack/ipv4-l4-protocol.cc index 83e56b0f9..628f451fe 100644 --- a/src/internet-stack/ipv4-l4-protocol.cc +++ b/src/internet-stack/ipv4-l4-protocol.cc @@ -44,4 +44,11 @@ Ipv4L4Protocol::GetTypeId (void) Ipv4L4Protocol::~Ipv4L4Protocol () {} +void +Ipv4L4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, + Ipv4Address payloadSource,Ipv4Address payloadDestination, + const uint8_t payload[8]) +{} + }//namespace ns3 diff --git a/src/internet-stack/ipv4-l4-protocol.h b/src/internet-stack/ipv4-l4-protocol.h index bb348bcd9..ffdc6042e 100644 --- a/src/internet-stack/ipv4-l4-protocol.h +++ b/src/internet-stack/ipv4-l4-protocol.h @@ -25,12 +25,13 @@ #define IPV4_L4_PROTOCOL_H #include "ns3/object.h" -#include "ipv4-interface.h" +#include "ns3/ipv4-header.h" namespace ns3 { class Packet; class Ipv4Address; +class Ipv4Interface; /** * \brief L4 Protocol abstract base class @@ -41,6 +42,12 @@ class Ipv4Address; class Ipv4L4Protocol : public Object { public: + enum RxStatus { + RX_OK, + RX_CSUM_FAILED, + RX_ENDPOINT_UNREACH + }; + static TypeId GetTypeId (void); virtual ~Ipv4L4Protocol (); @@ -59,10 +66,29 @@ public: * Called from lower-level layers to send the packet up * in the stack. */ - virtual void Receive(Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface) = 0; + virtual enum RxStatus Receive(Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface) = 0; + + /** + * \param icmpSouce the source address of the icmp message + * \param icmpTtl the ttl of the icmp message + * \param icmpType the 'type' field of the icmp message + * \param icmpCode the 'code' field of the icmp message + * \param icmpInfo extra information dependent on the icmp message + * generated by Icmpv4L4Protocol + * \param payloadSource the source address of the packet which triggered + * the icmp message + * \param payloadDestination the destination address of the packet which + * triggered the icmp message. + * \param payload the first 8 bytes of the udp header of the packet + * which triggered the icmp message. + */ + virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, + Ipv4Address payloadSource, Ipv4Address payloadDestination, + const uint8_t payload[8]); }; } // Namespace ns3 diff --git a/src/internet-stack/ipv4-raw-socket-factory-impl.cc b/src/internet-stack/ipv4-raw-socket-factory-impl.cc new file mode 100644 index 000000000..244ce7ee1 --- /dev/null +++ b/src/internet-stack/ipv4-raw-socket-factory-impl.cc @@ -0,0 +1,16 @@ +#include "ipv4-raw-socket-factory-impl.h" +#include "ipv4-l3-protocol.h" +#include "ns3/socket.h" + +namespace ns3 { + + +Ptr +Ipv4RawSocketFactoryImpl::CreateSocket (void) +{ + Ptr ipv4 = GetObject (); + Ptr socket = ipv4->CreateRawSocket (); + return socket; +} + +} // namespace ns3 diff --git a/src/internet-stack/ipv4-raw-socket-factory-impl.h b/src/internet-stack/ipv4-raw-socket-factory-impl.h new file mode 100644 index 000000000..89f526258 --- /dev/null +++ b/src/internet-stack/ipv4-raw-socket-factory-impl.h @@ -0,0 +1,17 @@ +#ifndef IPV4_RAW_SOCKET_FACTORY_IMPL_H +#define IPV4_RAW_SOCKET_FACTORY_IMPL_H + +#include "ns3/ipv4-raw-socket-factory.h" + +namespace ns3 { + +class Ipv4RawSocketFactoryImpl : public Ipv4RawSocketFactory +{ +public: + virtual Ptr CreateSocket (void); +}; + + +} // namespace ns3 + +#endif /* IPV4_RAW_SOCKET_FACTORY_IMPL_H */ diff --git a/src/internet-stack/ipv4-raw-socket-impl.cc b/src/internet-stack/ipv4-raw-socket-impl.cc new file mode 100644 index 000000000..e99f2addd --- /dev/null +++ b/src/internet-stack/ipv4-raw-socket-impl.cc @@ -0,0 +1,269 @@ +#include "ipv4-raw-socket-impl.h" +#include "ipv4-l3-protocol.h" +#include "icmpv4.h" +#include "ns3/inet-socket-address.h" +#include "ns3/node.h" +#include "ns3/packet.h" +#include "ns3/uinteger.h" +#include "ns3/log.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4RawSocketImpl"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketImpl); + +TypeId +Ipv4RawSocketImpl::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4RawSocketImpl") + .SetParent () + .AddAttribute ("Protocol", "Protocol number to match.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv4RawSocketImpl::m_protocol), + MakeUintegerChecker ()) + .AddAttribute ("IcmpFilter", + "Any icmp header whose type field matches a bit in this filter is dropped.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv4RawSocketImpl::m_icmpFilter), + MakeUintegerChecker ()) + ; + return tid; +} + +Ipv4RawSocketImpl::Ipv4RawSocketImpl () +{ + NS_LOG_FUNCTION (this); + m_err = Socket::ERROR_NOTERROR; + m_node = 0; + m_src = Ipv4Address::GetAny (); + m_dst = Ipv4Address::GetAny (); + m_protocol = 0; + m_shutdownSend = false; + m_shutdownRecv = false; +} + +void +Ipv4RawSocketImpl::SetNode (Ptr node) +{ + m_node = node; +} + +void +Ipv4RawSocketImpl::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_node = 0; + Socket::DoDispose (); +} + +enum Socket::SocketErrno +Ipv4RawSocketImpl::GetErrno (void) const +{ + NS_LOG_FUNCTION (this); + return m_err; +} +Ptr +Ipv4RawSocketImpl::GetNode (void) const +{ + NS_LOG_FUNCTION (this); + return m_node; +} +int +Ipv4RawSocketImpl::Bind (const Address &address) +{ + NS_LOG_FUNCTION (this << address); + if (!InetSocketAddress::IsMatchingType (address)) + { + m_err = Socket::ERROR_INVAL; + return -1; + } + InetSocketAddress ad = InetSocketAddress::ConvertFrom (address); + m_src = ad.GetIpv4 (); + return 0; +} +int +Ipv4RawSocketImpl::Bind (void) +{ + NS_LOG_FUNCTION (this); + m_src = Ipv4Address::GetAny (); + return 0; +} +int +Ipv4RawSocketImpl::GetSockName (Address &address) const +{ + address = InetSocketAddress (m_src, 0); + return 0; +} +int +Ipv4RawSocketImpl::Close (void) +{ + NS_LOG_FUNCTION (this); + Ptr ipv4 = m_node->GetObject (); + if (ipv4 != 0) + { + ipv4->DeleteRawSocket (this); + } + return 0; +} +int +Ipv4RawSocketImpl::ShutdownSend (void) +{ + NS_LOG_FUNCTION (this); + m_shutdownSend = true; + return 0; +} +int +Ipv4RawSocketImpl::ShutdownRecv (void) +{ + NS_LOG_FUNCTION (this); + m_shutdownRecv = true; + return 0; +} +int +Ipv4RawSocketImpl::Connect (const Address &address) +{ + NS_LOG_FUNCTION (this << address); + if (!InetSocketAddress::IsMatchingType (address)) + { + m_err = Socket::ERROR_INVAL; + return -1; + } + InetSocketAddress ad = InetSocketAddress::ConvertFrom (address); + m_dst = ad.GetIpv4 (); + return 0; +} +int +Ipv4RawSocketImpl::Listen (void) +{ + NS_LOG_FUNCTION (this); + m_err = Socket::ERROR_OPNOTSUPP; + return -1; +} +uint32_t +Ipv4RawSocketImpl::GetTxAvailable (void) const +{ + NS_LOG_FUNCTION (this); + return 0xffffffff; +} +int +Ipv4RawSocketImpl::Send (Ptr p, uint32_t flags) +{ + NS_LOG_FUNCTION (this << p << flags); + InetSocketAddress to = InetSocketAddress (m_dst, m_protocol); + return SendTo (p, flags, to); +} +int +Ipv4RawSocketImpl::SendTo (Ptr p, uint32_t flags, + const Address &toAddress) +{ + NS_LOG_FUNCTION (this << p << flags << toAddress); + if (!InetSocketAddress::IsMatchingType (toAddress)) + { + m_err = Socket::ERROR_INVAL; + return -1; + } + if (m_shutdownSend) + { + return 0; + } + InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress); + Ptr ipv4 = m_node->GetObject (); + Ipv4Address dst = ad.GetIpv4 (); + uint32_t localIfIndex; + if (ipv4->GetIfIndexForDestination(dst, localIfIndex)) + { + ipv4->Send (p, ipv4->GetAddress (localIfIndex), dst, m_protocol); + } + else + { + NS_LOG_DEBUG ("dropped because no outgoing route."); + } + return 0; +} +uint32_t +Ipv4RawSocketImpl::GetRxAvailable (void) const +{ + NS_LOG_FUNCTION (this); + uint32_t rx = 0; + for (std::list::const_iterator i = m_recv.begin (); i != m_recv.end (); ++i) + { + rx += (i->packet)->GetSize (); + } + return rx; +} +Ptr +Ipv4RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags) +{ + NS_LOG_FUNCTION (this << maxSize << flags); + Address tmp; + return RecvFrom (maxSize, flags, tmp); +} +Ptr +Ipv4RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress) +{ + NS_LOG_FUNCTION (this << maxSize << flags << fromAddress); + if (m_recv.empty ()) + { + return 0; + } + struct Data data = m_recv.front (); + m_recv.pop_front (); + if (data.packet->GetSize () > maxSize) + { + Ptr first = data.packet->CreateFragment (0, maxSize); + data.packet->RemoveAtStart (maxSize); + m_recv.push_front (data); + return first; + } + InetSocketAddress inet = InetSocketAddress (data.fromIp, data.fromProtocol); + fromAddress = inet; + return data.packet; +} + +void +Ipv4RawSocketImpl::SetProtocol (uint16_t protocol) +{ + NS_LOG_FUNCTION (this << protocol); + m_protocol = protocol; +} + +bool +Ipv4RawSocketImpl::ForwardUp (Ptr p, Ipv4Header ipHeader, Ptr device) +{ + NS_LOG_FUNCTION (this << *p << ipHeader << device); + if (m_shutdownRecv) + { + return false; + } + if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) && + (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) && + ipHeader.GetProtocol () == m_protocol) + { + Ptr copy = p->Copy (); + if (m_protocol == 1) + { + Icmpv4Header icmpHeader; + copy->PeekHeader (icmpHeader); + uint8_t type = icmpHeader.GetType (); + if (type < 32 && + ((1 << type) & m_icmpFilter)) + { + // filter out icmp packet. + return false; + } + } + copy->AddHeader (ipHeader); + struct Data data; + data.packet = copy; + data.fromIp = ipHeader.GetSource (); + data.fromProtocol = ipHeader.GetProtocol (); + m_recv.push_back (data); + NotifyDataRecv (); + return true; + } + return false; +} + +} // namespace ns3 diff --git a/src/internet-stack/ipv4-raw-socket-impl.h b/src/internet-stack/ipv4-raw-socket-impl.h new file mode 100644 index 000000000..8e9e86af8 --- /dev/null +++ b/src/internet-stack/ipv4-raw-socket-impl.h @@ -0,0 +1,65 @@ +#ifndef IPV4_RAW_SOCKET_IMPL_H +#define IPV4_RAW_SOCKET_IMPL_H + +#include "ns3/socket.h" +#include "ns3/ipv4-header.h" +#include + +namespace ns3 { + +class NetDevice; +class Node; + +class Ipv4RawSocketImpl : public Socket +{ +public: + static TypeId GetTypeId (void); + + Ipv4RawSocketImpl (); + + void SetNode (Ptr node); + + virtual enum Socket::SocketErrno GetErrno (void) const; + virtual Ptr GetNode (void) const; + virtual int Bind (const Address &address); + virtual int Bind (); + virtual int GetSockName (Address &address) const; + virtual int Close (void); + virtual int ShutdownSend (void); + virtual int ShutdownRecv (void); + virtual int Connect (const Address &address); + virtual int Listen (void); + virtual uint32_t GetTxAvailable (void) const; + virtual int Send (Ptr p, uint32_t flags); + virtual int SendTo (Ptr p, uint32_t flags, + const Address &toAddress); + virtual uint32_t GetRxAvailable (void) const; + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, + Address &fromAddress); + + void SetProtocol (uint16_t protocol); + bool ForwardUp (Ptr p, Ipv4Header ipHeader, Ptr device); +private: + virtual void DoDispose (void); + + struct Data { + Ptr packet; + Ipv4Address fromIp; + uint16_t fromProtocol; + }; + + enum Socket::SocketErrno m_err; + Ptr m_node; + Ipv4Address m_src; + Ipv4Address m_dst; + uint16_t m_protocol; + std::list m_recv; + bool m_shutdownSend; + bool m_shutdownRecv; + uint32_t m_icmpFilter; +}; + +} // namespace ns3 + +#endif /* IPV4_RAW_SOCKET_IMPL_H */ diff --git a/src/internet-stack/nsc-tcp-l4-protocol.cc b/src/internet-stack/nsc-tcp-l4-protocol.cc index 401ef1e8f..5be47abaa 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.cc +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc @@ -220,7 +220,7 @@ NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) // NSC m_endPoints->DeAllocate (endPoint); } -void +Ipv4L4Protocol::RxStatus NscTcpL4Protocol::Receive (Ptr packet, Ipv4Address const &source, Ipv4Address const &destination, @@ -251,6 +251,7 @@ NscTcpL4Protocol::Receive (Ptr packet, // deliver complete packet to the NSC network stack m_nscStack->if_receive_packet(0, data, packetSize); wakeup (); + return Ipv4L4Protocol::RX_OK; } void NscTcpL4Protocol::SoftInterrupt (void) diff --git a/src/internet-stack/nsc-tcp-l4-protocol.h b/src/internet-stack/nsc-tcp-l4-protocol.h index 212a62755..a9ca47345 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.h +++ b/src/internet-stack/nsc-tcp-l4-protocol.h @@ -80,10 +80,10 @@ public: * \param destination The destinations Ipv4Address * \param incomingInterface The Ipv4Interface it was received on */ - virtual void Receive (Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface); + virtual Ipv4L4Protocol::RxStatus Receive (Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface); // NSC callbacks. // NSC invokes these hooks to interact with the simulator. diff --git a/src/internet-stack/tcp-l4-protocol.cc b/src/internet-stack/tcp-l4-protocol.cc index 9b0d56a1f..501bb4d7d 100644 --- a/src/internet-stack/tcp-l4-protocol.cc +++ b/src/internet-stack/tcp-l4-protocol.cc @@ -431,7 +431,7 @@ TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) m_endPoints->DeAllocate (endPoint); } -void +enum Ipv4L4Protocol::RxStatus TcpL4Protocol::Receive (Ptr packet, Ipv4Address const &source, Ipv4Address const &destination, @@ -457,7 +457,7 @@ TcpL4Protocol::Receive (Ptr packet, if(!tcpHeader.IsChecksumOk ()) { NS_LOG_INFO("Bad checksum, dropping packet!"); - return; + return Ipv4L4Protocol::RX_CSUM_FAILED; } NS_LOG_LOGIC ("TcpL4Protocol "< packet, source.Print (oss); oss<<" source port: "<ForwardUp (packet, source, tcpHeader.GetSourcePort ()); + return Ipv4L4Protocol::RX_OK; } void diff --git a/src/internet-stack/tcp-l4-protocol.h b/src/internet-stack/tcp-l4-protocol.h index b567aaf6a..864df9d55 100644 --- a/src/internet-stack/tcp-l4-protocol.h +++ b/src/internet-stack/tcp-l4-protocol.h @@ -101,10 +101,10 @@ public: * \param destination The destinations Ipv4Address * \param incomingInterface The Ipv4Interface it was received on */ - virtual void Receive (Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface); + virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface); protected: virtual void DoDispose (void); diff --git a/src/internet-stack/udp-l4-protocol.cc b/src/internet-stack/udp-l4-protocol.cc index 080813b2c..9d5480bb9 100644 --- a/src/internet-stack/udp-l4-protocol.cc +++ b/src/internet-stack/udp-l4-protocol.cc @@ -146,6 +146,33 @@ UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) } void +UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, + Ipv4Address payloadSource,Ipv4Address payloadDestination, + const uint8_t payload[8]) +{ + NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo + << payloadSource << payloadDestination); + uint16_t src, dst; + src = payload[0] << 8; + src |= payload[1]; + dst = payload[2] << 8; + dst |= payload[3]; + + Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst); + if (endPoint != 0) + { + endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo); + } + else + { + NS_LOG_DEBUG ("no endpoint found source=" << payloadSource << + ", destination="<Lookup (destination, udpHeader.GetDestinationPort (), source, udpHeader.GetSourcePort (), interface); + if (endPoints.empty ()) + { + return Ipv4L4Protocol::RX_ENDPOINT_UNREACH; + } for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); endPoint != endPoints.end (); endPoint++) { (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ()); } + return Ipv4L4Protocol::RX_OK; } void diff --git a/src/internet-stack/udp-l4-protocol.h b/src/internet-stack/udp-l4-protocol.h index c92f83a61..55d967c67 100644 --- a/src/internet-stack/udp-l4-protocol.h +++ b/src/internet-stack/udp-l4-protocol.h @@ -84,10 +84,15 @@ public: * \param interface the interface from which the packet is coming. */ // inherited from Ipv4L4Protocol - virtual void Receive(Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, + virtual enum Ipv4L4Protocol::RxStatus Receive(Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, Ptr interface); + + virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, + Ipv4Address payloadSource,Ipv4Address payloadDestination, + const uint8_t payload[8]); protected: virtual void DoDispose (void); private: diff --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index 3feb6b3f5..4922e5912 100644 --- a/src/internet-stack/udp-socket-impl.cc +++ b/src/internet-stack/udp-socket-impl.cc @@ -25,8 +25,6 @@ #include "ns3/ipv4.h" #include "ns3/udp-socket-factory.h" #include "ns3/trace-source-accessor.h" -#include "ns3/uinteger.h" -#include "ns3/boolean.h" #include "udp-socket-impl.h" #include "udp-l4-protocol.h" #include "ipv4-end-point.h" @@ -47,6 +45,10 @@ UdpSocketImpl::GetTypeId (void) .AddConstructor () .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow", MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace)) + .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.", + CallbackValue (), + MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback), + MakeCallbackChecker ()) ; return tid; } @@ -134,6 +136,7 @@ UdpSocketImpl::FinishBind (void) return -1; } m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr (this))); + m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr (this))); m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr (this))); return 0; } @@ -328,6 +331,22 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) tag.SetTtl (m_ipTtl); p->AddTag (tag); } + { + SocketSetDontFragmentTag tag; + bool found = p->FindFirstMatchingTag (tag); + if (!found) + { + if (m_mtuDiscover) + { + tag.Enable (); + } + else + { + tag.Disable (); + } + p->AddTag (tag); + } + } // // If dest is sent to the limited broadcast address (all ones), // convert it to send a copy of the packet out of every interface @@ -405,6 +424,7 @@ UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) NS_LOG_FUNCTION (this << maxSize << flags); if (m_deliveryQueue.empty() ) { + m_errno = ERROR_AGAIN; return 0; } Ptr p = m_deliveryQueue.front (); @@ -483,6 +503,19 @@ UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) } } +void +UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, + uint32_t icmpInfo) +{ + NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType << + (uint32_t)icmpCode << icmpInfo); + if (!m_icmpCallback.IsNull ()) + { + m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo); + } +} + void UdpSocketImpl::SetRcvBufSize (uint32_t size) @@ -520,6 +553,18 @@ UdpSocketImpl::GetIpMulticastTtl (void) const return m_ipMulticastTtl; } +void +UdpSocketImpl::SetMtuDiscover (bool discover) +{ + m_mtuDiscover = discover; +} +bool +UdpSocketImpl::GetMtuDiscover (void) const +{ + return m_mtuDiscover; +} + + } //namespace ns3 diff --git a/src/internet-stack/udp-socket-impl.h b/src/internet-stack/udp-socket-impl.h index 03fae2e56..65fa0c9b3 100644 --- a/src/internet-stack/udp-socket-impl.h +++ b/src/internet-stack/udp-socket-impl.h @@ -28,6 +28,7 @@ #include "ns3/ptr.h" #include "ns3/ipv4-address.h" #include "ns3/udp-socket.h" +#include "icmpv4.h" namespace ns3 { @@ -83,6 +84,9 @@ private: virtual uint32_t GetIpTtl (void) const; virtual void SetIpMulticastTtl (uint32_t ipTtl); virtual uint32_t GetIpMulticastTtl (void) const; + virtual void SetMtuDiscover (bool discover); + virtual bool GetMtuDiscover (void) const; + friend class UdpSocketFactory; // invoked by Udp class @@ -92,6 +96,9 @@ private: int DoSend (Ptr p); int DoSendTo (Ptr p, const Address &daddr); int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); + void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, + uint8_t icmpType, uint8_t icmpCode, + uint32_t icmpInfo); Ipv4EndPoint *m_endPoint; Ptr m_node; @@ -114,7 +121,8 @@ private: uint32_t m_rcvBufSize; uint32_t m_ipTtl; uint32_t m_ipMulticastTtl; - + bool m_mtuDiscover; + Callback m_icmpCallback; }; }//namespace ns3 diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index 077a35859..c7f64f766 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -148,6 +148,10 @@ def build(bld): 'pending-data.cc', 'sequence-number.cc', 'rtt-estimator.cc', + 'ipv4-raw-socket-factory-impl.cc', + 'ipv4-raw-socket-impl.cc', + 'icmpv4.cc', + 'icmpv4-l4-protocol.cc', ] headers = bld.create_obj('ns3header') @@ -160,6 +164,7 @@ def build(bld): 'ipv4-interface.h', 'ipv4-l3-protocol.h', 'ipv4-static-routing.h', + 'icmpv4.h', ] if bld.env()['NSC_ENABLED']: diff --git a/src/node/ipv4-raw-socket-factory.cc b/src/node/ipv4-raw-socket-factory.cc new file mode 100644 index 000000000..433b1313c --- /dev/null +++ b/src/node/ipv4-raw-socket-factory.cc @@ -0,0 +1,35 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "ipv4-raw-socket-factory.h" +#include "ns3/uinteger.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketFactory); + +TypeId Ipv4RawSocketFactory::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4RawSocketFactory") + .SetParent () + ; + return tid; +} + +} // namespace ns3 diff --git a/src/node/ipv4-raw-socket-factory.h b/src/node/ipv4-raw-socket-factory.h new file mode 100644 index 000000000..65b43aeb5 --- /dev/null +++ b/src/node/ipv4-raw-socket-factory.h @@ -0,0 +1,46 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef IPV4_RAW_SOCKET_FACTORY_H +#define IPV4_RAW_SOCKET_FACTORY_H + +#include "socket-factory.h" + +namespace ns3 { + +class Socket; + +/** + * \ingroup socket + * + * \brief API to create RAW socket instances + * + * This abstract class defines the API for RAW socket factory. + * + */ +class Ipv4RawSocketFactory : public SocketFactory +{ +public: + static TypeId GetTypeId (void); + +}; + +} // namespace ns3 + +#endif /* IPV4_RAW_SOCKET_FACTORY_H */ diff --git a/src/node/socket.cc b/src/node/socket.cc index c7f9511e5..4ceac3962 100644 --- a/src/node/socket.cc +++ b/src/node/socket.cc @@ -362,4 +362,57 @@ SocketIpTtlTag::Print (std::ostream &os) const } +SocketSetDontFragmentTag::SocketSetDontFragmentTag () +{} +void +SocketSetDontFragmentTag::Enable (void) +{ + m_dontFragment = true; +} +void +SocketSetDontFragmentTag::Disable (void) +{ + m_dontFragment = false; +} +bool +SocketSetDontFragmentTag::IsEnabled (void) const +{ + return m_dontFragment; +} + +TypeId +SocketSetDontFragmentTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::SocketSetDontFragmentTag") + .SetParent () + .AddConstructor () + ; + return tid; +} +TypeId +SocketSetDontFragmentTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +SocketSetDontFragmentTag::GetSerializedSize (void) const +{ + return 1; +} +void +SocketSetDontFragmentTag::Serialize (TagBuffer i) const +{ + i.WriteU8 (m_dontFragment?1:0); +} +void +SocketSetDontFragmentTag::Deserialize (TagBuffer i) +{ + m_dontFragment = (i.ReadU8 () == 1)?true:false; +} +void +SocketSetDontFragmentTag::Print (std::ostream &os) const +{ + os << (m_dontFragment?"true":"false"); +} + }//namespace ns3 diff --git a/src/node/socket.h b/src/node/socket.h index 6287895a4..22fd59e86 100644 --- a/src/node/socket.h +++ b/src/node/socket.h @@ -336,9 +336,9 @@ public: * not preserved. * * The flags argument is formed by or'ing one or more of the values: - * MSG_OOB process out-of-band data - * MSG_PEEK peek at incoming message - * These flags are _unsupported_ as of ns-3.1. + * MSG_OOB process out-of-band data + * MSG_PEEK peek at incoming message + * None of these flags are supported for now. * * Some variants of Recv() are supported as additional API, * including RecvFrom(), overloaded Recv() without arguments, @@ -555,6 +555,29 @@ private: uint8_t m_ttl; }; + +/** + * \brief indicated whether packets should be sent out with + * the DF flag set. + */ +class SocketSetDontFragmentTag : public Tag +{ +public: + SocketSetDontFragmentTag (); + void Enable (void); + void Disable (void); + bool IsEnabled (void) const; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; +private: + bool m_dontFragment; +}; + } //namespace ns3 #endif /* SOCKET_H */ diff --git a/src/node/udp-socket.cc b/src/node/udp-socket.cc index 8fc5ea8b1..25ceacae6 100644 --- a/src/node/udp-socket.cc +++ b/src/node/udp-socket.cc @@ -21,6 +21,7 @@ #include "ns3/object.h" #include "ns3/log.h" #include "ns3/uinteger.h" +#include "ns3/boolean.h" #include "ns3/trace-source-accessor.h" #include "udp-socket.h" @@ -53,6 +54,11 @@ UdpSocket::GetTypeId (void) MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl, &UdpSocket::SetIpMulticastTtl), MakeUintegerChecker ()) + .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.", + BooleanValue (false), + MakeBooleanAccessor (&UdpSocket::SetMtuDiscover, + &UdpSocket::GetMtuDiscover), + MakeBooleanChecker ()) ; return tid; } diff --git a/src/node/udp-socket.h b/src/node/udp-socket.h index afe17774e..4d44549ed 100644 --- a/src/node/udp-socket.h +++ b/src/node/udp-socket.h @@ -58,7 +58,8 @@ private: virtual uint32_t GetIpTtl (void) const = 0; virtual void SetIpMulticastTtl (uint32_t ipTtl) = 0; virtual uint32_t GetIpMulticastTtl (void) const = 0; - + virtual void SetMtuDiscover (bool discover) = 0; + virtual bool GetMtuDiscover (void) const = 0; }; } //namespace ns3 diff --git a/src/node/wscript b/src/node/wscript index 1856970ff..9bb6927f7 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -34,6 +34,7 @@ def build(bld): 'application.cc', 'simple-channel.cc', 'simple-net-device.cc', + 'ipv4-raw-socket-factory.cc', ] headers = bld.create_obj('ns3header') @@ -69,4 +70,5 @@ def build(bld): 'application.h', 'simple-channel.h', 'simple-net-device.h', + 'ipv4-raw-socket-factory.h', ]