From ce459e3d8a5861555b46dffd1d53050b30dd606f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Mon, 29 Apr 2024 21:13:28 +0200 Subject: [PATCH] applications: Combine RemoteAddress and RemotePort attributes to a single one in UdpEchoClient Proposed by Sharan Naribole --- src/applications/helper/udp-echo-helper.cc | 7 +- src/applications/helper/udp-echo-helper.h | 1 + src/applications/model/udp-echo-client.cc | 192 ++++++++++-------- src/applications/model/udp-echo-client.h | 42 +++- .../test/udp-client-server-test.cc | 2 +- 5 files changed, 142 insertions(+), 102 deletions(-) diff --git a/src/applications/helper/udp-echo-helper.cc b/src/applications/helper/udp-echo-helper.cc index 6ab59e781..d740f3d04 100644 --- a/src/applications/helper/udp-echo-helper.cc +++ b/src/applications/helper/udp-echo-helper.cc @@ -8,6 +8,7 @@ #include "udp-echo-helper.h" +#include "ns3/address-utils.h" #include "ns3/udp-echo-client.h" #include "ns3/udp-echo-server.h" #include "ns3/uinteger.h" @@ -22,16 +23,14 @@ UdpEchoServerHelper::UdpEchoServerHelper(uint16_t port) } UdpEchoClientHelper::UdpEchoClientHelper(const Address& address, uint16_t port) - : ApplicationHelper(UdpEchoClient::GetTypeId()) + : UdpEchoClientHelper(addressUtils::ConvertToSocketAddress(address, port)) { - SetAttribute("RemoteAddress", AddressValue(address)); - SetAttribute("RemotePort", UintegerValue(port)); } UdpEchoClientHelper::UdpEchoClientHelper(const Address& address) : ApplicationHelper(UdpEchoClient::GetTypeId()) { - SetAttribute("RemoteAddress", AddressValue(address)); + SetAttribute("Remote", AddressValue(address)); } void diff --git a/src/applications/helper/udp-echo-helper.h b/src/applications/helper/udp-echo-helper.h index abd8d9567..9d0d1d99c 100644 --- a/src/applications/helper/udp-echo-helper.h +++ b/src/applications/helper/udp-echo-helper.h @@ -49,6 +49,7 @@ class UdpEchoClientHelper : public ApplicationHelper * \param port The port number of the remote udp echo server */ UdpEchoClientHelper(const Address& ip, uint16_t port); + /** * Create UdpEchoClientHelper which will make life easier for people trying * to set up simulations with echos. Use this variant with addresses that do diff --git a/src/applications/model/udp-echo-client.cc b/src/applications/model/udp-echo-client.cc index 85428d62e..2d5771216 100644 --- a/src/applications/model/udp-echo-client.cc +++ b/src/applications/model/udp-echo-client.cc @@ -5,10 +5,7 @@ */ #include "udp-echo-client.h" -#include "ns3/inet-socket-address.h" -#include "ns3/inet6-socket-address.h" -#include "ns3/ipv4-address.h" -#include "ns3/ipv6-address.h" +#include "ns3/address-utils.h" #include "ns3/log.h" #include "ns3/nstime.h" #include "ns3/packet.h" @@ -44,16 +41,35 @@ UdpEchoClient::GetTypeId() TimeValue(Seconds(1.0)), MakeTimeAccessor(&UdpEchoClient::m_interval), MakeTimeChecker()) - .AddAttribute("RemoteAddress", - "The destination Address of the outbound packets", - AddressValue(), - MakeAddressAccessor(&UdpEchoClient::m_peerAddress), - MakeAddressChecker()) + .AddAttribute( + "RemoteAddress", + "The destination Address of the outbound packets", + AddressValue(), + MakeAddressAccessor( + (void(UdpEchoClient::*)(const Address&)) & + UdpEchoClient::SetRemote, // this is needed to indicate which version of the + // function overload to use + &UdpEchoClient::GetRemote), + MakeAddressChecker(), + TypeId::DEPRECATED, + "Replaced by Remote in ns-3.44.") .AddAttribute("RemotePort", "The destination port of the outbound packets", - UintegerValue(0), - MakeUintegerAccessor(&UdpEchoClient::m_peerPort), - MakeUintegerChecker()) + UintegerValue(UdpEchoClient::DEFAULT_PORT), + MakeUintegerAccessor(&UdpEchoClient::SetPort, &UdpEchoClient::GetPort), + MakeUintegerChecker(), + TypeId::DEPRECATED, + "Replaced by Remote in ns-3.44.") + .AddAttribute( + "Remote", + "The address of the destination", + AddressValue(), + MakeAddressAccessor( + (void(UdpEchoClient::*)(const Address&)) & + UdpEchoClient::SetRemote, // this is needed to indicate which version of the + // function overload to use + &UdpEchoClient::GetRemote), + MakeAddressChecker()) .AddAttribute("Tos", "The Type of Service used to send IPv4 packets. " "All 8 bits of the TOS byte are set (including ECN bits).", @@ -86,13 +102,14 @@ UdpEchoClient::GetTypeId() } UdpEchoClient::UdpEchoClient() + : m_dataSize{0}, + m_data{nullptr}, + m_sent{0}, + m_socket{nullptr}, + m_peerPort{}, + m_sendEvent{} { NS_LOG_FUNCTION(this); - m_sent = 0; - m_socket = nullptr; - m_sendEvent = EventId(); - m_data = nullptr; - m_dataSize = 0; } UdpEchoClient::~UdpEchoClient() @@ -106,18 +123,65 @@ UdpEchoClient::~UdpEchoClient() } void -UdpEchoClient::SetRemote(Address ip, uint16_t port) +UdpEchoClient::SetRemote(const Address& ip, uint16_t port) { NS_LOG_FUNCTION(this << ip << port); - m_peerAddress = ip; - m_peerPort = port; + SetRemote(ip); + SetPort(port); } void -UdpEchoClient::SetRemote(Address addr) +UdpEchoClient::SetRemote(const Address& addr) { NS_LOG_FUNCTION(this << addr); - m_peerAddress = addr; + if (!addr.IsInvalid()) + { + m_peer = addr; + if (m_peerPort) + { + SetPort(*m_peerPort); + } + } +} + +Address +UdpEchoClient::GetRemote() const +{ + return m_peer; +} + +void +UdpEchoClient::SetPort(uint16_t port) +{ + NS_LOG_FUNCTION(this << port); + if (m_peer.IsInvalid()) + { + // save for later + m_peerPort = port; + return; + } + if (Ipv4Address::IsMatchingType(m_peer) || Ipv6Address::IsMatchingType(m_peer)) + { + m_peer = addressUtils::ConvertToSocketAddress(m_peer, port); + } +} + +uint16_t +UdpEchoClient::GetPort() const +{ + if (m_peer.IsInvalid()) + { + return m_peerPort.value_or(UdpEchoClient::DEFAULT_PORT); + } + if (InetSocketAddress::IsMatchingType(m_peer)) + { + return InetSocketAddress::ConvertFrom(m_peer).GetPort(); + } + else if (Inet6SocketAddress::IsMatchingType(m_peer)) + { + return Inet6SocketAddress::ConvertFrom(m_peer).GetPort(); + } + return UdpEchoClient::DEFAULT_PORT; } void @@ -127,53 +191,33 @@ UdpEchoClient::StartApplication() if (!m_socket) { - TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); + auto tid = TypeId::LookupByName("ns3::UdpSocketFactory"); m_socket = Socket::CreateSocket(GetNode(), tid); - NS_ABORT_MSG_IF(m_peerAddress.IsInvalid(), "'RemoteAddress' attribute not properly set"); - if (Ipv4Address::IsMatchingType(m_peerAddress)) + NS_ABORT_MSG_IF(m_peer.IsInvalid(), "Remote address not properly set"); + if (InetSocketAddress::IsMatchingType(m_peer)) { if (m_socket->Bind() == -1) { NS_FATAL_ERROR("Failed to bind socket"); } - m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. - m_socket->Connect( - InetSocketAddress(Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); } - else if (Ipv6Address::IsMatchingType(m_peerAddress)) + else if (Inet6SocketAddress::IsMatchingType(m_peer)) { if (m_socket->Bind6() == -1) { NS_FATAL_ERROR("Failed to bind socket"); } - m_socket->Connect( - Inet6SocketAddress(Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort)); - } - else if (InetSocketAddress::IsMatchingType(m_peerAddress)) - { - if (m_socket->Bind() == -1) - { - NS_FATAL_ERROR("Failed to bind socket"); - } - m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. - m_socket->Connect(m_peerAddress); - } - else if (Inet6SocketAddress::IsMatchingType(m_peerAddress)) - { - if (m_socket->Bind6() == -1) - { - NS_FATAL_ERROR("Failed to bind socket"); - } - m_socket->Connect(m_peerAddress); } else { - NS_ASSERT_MSG(false, "Incompatible address type: " << m_peerAddress); + NS_ASSERT_MSG(false, "Incompatible address type: " << m_peer); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. + m_socket->Connect(m_peer); + m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this)); + m_socket->SetAllowBroadcast(true); } - m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::HandleRead, this)); - m_socket->SetAllowBroadcast(true); ScheduleTransmit(Seconds(0.)); } @@ -339,48 +383,21 @@ UdpEchoClient::Send() // call to the trace sinks before the packet is actually sent, // so that tags added to the packet can be sent as well m_txTrace(p); - if (Ipv4Address::IsMatchingType(m_peerAddress)) - { - m_txTraceWithAddresses( - p, - localAddress, - InetSocketAddress(Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); - } - else if (Ipv6Address::IsMatchingType(m_peerAddress)) - { - m_txTraceWithAddresses( - p, - localAddress, - Inet6SocketAddress(Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort)); - } + m_txTraceWithAddresses(p, localAddress, m_peer); m_socket->Send(p); ++m_sent; - if (Ipv4Address::IsMatchingType(m_peerAddress)) + if (InetSocketAddress::IsMatchingType(m_peer)) { NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " client sent " << m_size - << " bytes to " << Ipv4Address::ConvertFrom(m_peerAddress) - << " port " << m_peerPort); + << " bytes to " << InetSocketAddress::ConvertFrom(m_peer).GetIpv4() + << " port " << InetSocketAddress::ConvertFrom(m_peer).GetPort()); } - else if (Ipv6Address::IsMatchingType(m_peerAddress)) + else if (Inet6SocketAddress::IsMatchingType(m_peer)) { NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " client sent " << m_size - << " bytes to " << Ipv6Address::ConvertFrom(m_peerAddress) - << " port " << m_peerPort); - } - else if (InetSocketAddress::IsMatchingType(m_peerAddress)) - { - NS_LOG_INFO( - "At time " << Simulator::Now().As(Time::S) << " client sent " << m_size << " bytes to " - << InetSocketAddress::ConvertFrom(m_peerAddress).GetIpv4() << " port " - << InetSocketAddress::ConvertFrom(m_peerAddress).GetPort()); - } - else if (Inet6SocketAddress::IsMatchingType(m_peerAddress)) - { - NS_LOG_INFO( - "At time " << Simulator::Now().As(Time::S) << " client sent " << m_size << " bytes to " - << Inet6SocketAddress::ConvertFrom(m_peerAddress).GetIpv6() << " port " - << Inet6SocketAddress::ConvertFrom(m_peerAddress).GetPort()); + << " bytes to " << Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6() + << " port " << Inet6SocketAddress::ConvertFrom(m_peer).GetPort()); } if (m_sent < m_count || m_count == 0) @@ -393,10 +410,8 @@ void UdpEchoClient::HandleRead(Ptr socket) { NS_LOG_FUNCTION(this << socket); - Ptr packet; Address from; - Address localAddress; - while ((packet = socket->RecvFrom(from))) + while (auto packet = socket->RecvFrom(from)) { if (InetSocketAddress::IsMatchingType(from)) { @@ -412,6 +427,7 @@ UdpEchoClient::HandleRead(Ptr socket) << Inet6SocketAddress::ConvertFrom(from).GetIpv6() << " port " << Inet6SocketAddress::ConvertFrom(from).GetPort()); } + Address localAddress; socket->GetSockName(localAddress); m_rxTrace(packet); m_rxTraceWithAddresses(packet, from, localAddress); diff --git a/src/applications/model/udp-echo-client.h b/src/applications/model/udp-echo-client.h index 2ac58a078..9f2b1537c 100644 --- a/src/applications/model/udp-echo-client.h +++ b/src/applications/model/udp-echo-client.h @@ -8,11 +8,14 @@ #define UDP_ECHO_CLIENT_H #include "ns3/application.h" +#include "ns3/deprecated.h" #include "ns3/event-id.h" #include "ns3/ipv4-address.h" #include "ns3/ptr.h" #include "ns3/traced-callback.h" +#include + namespace ns3 { @@ -35,20 +38,23 @@ class UdpEchoClient : public Application static TypeId GetTypeId(); UdpEchoClient(); - ~UdpEchoClient() override; + static constexpr uint16_t DEFAULT_PORT{0}; //!< default port + /** * \brief set the remote address and port * \param ip remote IP address * \param port remote port */ - void SetRemote(Address ip, uint16_t port); + NS_DEPRECATED_3_44("Use SetRemote without port parameter instead") + void SetRemote(const Address& ip, uint16_t port); + /** * \brief set the remote address * \param addr remote address */ - void SetRemote(Address addr); + void SetRemote(const Address& addr); /** * Set the data size of the packet (the number of bytes that are sent as data @@ -123,6 +129,24 @@ class UdpEchoClient : public Application void StartApplication() override; void StopApplication() override; + /** + * \brief Set the remote port (temporary function until deprecated attributes are removed) + * \param port remote port + */ + void SetPort(uint16_t port); + + /** + * \brief Get the remote port (temporary function until deprecated attributes are removed) + * \return the remote port + */ + uint16_t GetPort() const; + + /** + * \brief Get the remote address (temporary function until deprecated attributes are removed) + * \return the remote address + */ + Address GetRemote() const; + /** * \brief Schedule the next packet transmission * \param dt time interval between packets. @@ -149,12 +173,12 @@ class UdpEchoClient : public Application uint32_t m_dataSize; //!< packet payload size (must be equal to m_size) uint8_t* m_data; //!< packet payload data - uint32_t m_sent; //!< Counter for sent packets - Ptr m_socket; //!< Socket - Address m_peerAddress; //!< Remote peer address - uint16_t m_peerPort; //!< Remote peer port - uint8_t m_tos; //!< The packets Type of Service - EventId m_sendEvent; //!< Event to send the next packet + uint32_t m_sent; //!< Counter for sent packets + Ptr m_socket; //!< Socket + Address m_peer; //!< Remote peer address + std::optional m_peerPort; //!< Remote peer port (deprecated) // NS_DEPRECATED_3_44 + uint8_t m_tos; //!< The packets Type of Service + EventId m_sendEvent; //!< Event to send the next packet /// Callbacks for tracing the packet Tx events TracedCallback> m_txTrace; diff --git a/src/applications/test/udp-client-server-test.cc b/src/applications/test/udp-client-server-test.cc index c8ee33a81..67a1b842d 100644 --- a/src/applications/test/udp-client-server-test.cc +++ b/src/applications/test/udp-client-server-test.cc @@ -314,7 +314,7 @@ UdpEchoClientSetFillTestCase::DoRun() ApplicationContainer serverApps = echoServer.Install(nodes.Get(1)); serverApps.Start(Seconds(1.0)); serverApps.Stop(Seconds(10.0)); - UdpEchoClientHelper echoClient(interfaces.GetAddress(1), port); + UdpEchoClientHelper echoClient(InetSocketAddress(interfaces.GetAddress(1), port)); echoClient.SetAttribute("MaxPackets", UintegerValue(1)); echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0))); echoClient.SetAttribute("PacketSize", UintegerValue(1024));