apply MTU/FrameSize treatment to point-to-point
This commit is contained in:
@@ -14,7 +14,7 @@ def register_types(module):
|
||||
## csma-net-device.h: ns3::CsmaNetDevice [class]
|
||||
module.add_class('CsmaNetDevice', parent=root_module['ns3::NetDevice'])
|
||||
## csma-net-device.h: ns3::CsmaNetDevice::EncapsulationMode [enumeration]
|
||||
module.add_enum('EncapsulationMode', ['ETHERNET_V1', 'IP_ARP', 'RAW', 'LLC'], outer_class=root_module['ns3::CsmaNetDevice'])
|
||||
module.add_enum('EncapsulationMode', ['ILLEGAL', 'DIX', 'LLC'], outer_class=root_module['ns3::CsmaNetDevice'])
|
||||
|
||||
## Register a nested module for the namespace internal
|
||||
|
||||
@@ -256,21 +256,12 @@ def register_Ns3CsmaNetDevice_methods(root_module, cls):
|
||||
cls.add_method('SetAddress',
|
||||
'void',
|
||||
[param('ns3::Mac48Address', 'addr')])
|
||||
## csma-net-device.h: void ns3::CsmaNetDevice::SetMaxPayloadLength(uint16_t maxPayloadLength) [member function]
|
||||
cls.add_method('SetMaxPayloadLength',
|
||||
## csma-net-device.h: void ns3::CsmaNetDevice::SetFrameSize(uint16_t frameSize) [member function]
|
||||
cls.add_method('SetFrameSize',
|
||||
'void',
|
||||
[param('uint16_t', 'maxPayloadLength')])
|
||||
## csma-net-device.h: uint16_t ns3::CsmaNetDevice::GetMaxPayloadLength() const [member function]
|
||||
cls.add_method('GetMaxPayloadLength',
|
||||
'uint16_t',
|
||||
[],
|
||||
is_const=True)
|
||||
## csma-net-device.h: void ns3::CsmaNetDevice::SetMacMtu(uint16_t mtu) [member function]
|
||||
cls.add_method('SetMacMtu',
|
||||
'void',
|
||||
[param('uint16_t', 'mtu')])
|
||||
## csma-net-device.h: uint16_t ns3::CsmaNetDevice::GetMacMtu() const [member function]
|
||||
cls.add_method('GetMacMtu',
|
||||
[param('uint16_t', 'frameSize')])
|
||||
## csma-net-device.h: uint16_t ns3::CsmaNetDevice::GetFrameSize() const [member function]
|
||||
cls.add_method('GetFrameSize',
|
||||
'uint16_t',
|
||||
[],
|
||||
is_const=True)
|
||||
|
||||
@@ -313,6 +313,10 @@ def register_Ns3NetDeviceContainer_methods(root_module, cls):
|
||||
cls.add_constructor([param('ns3::NetDeviceContainer const &', 'arg0')])
|
||||
## net-device-container.h: ns3::NetDeviceContainer::NetDeviceContainer() [constructor]
|
||||
cls.add_constructor([])
|
||||
## net-device-container.h: ns3::NetDeviceContainer::NetDeviceContainer(ns3::Ptr<ns3::NetDevice> dev) [constructor]
|
||||
cls.add_constructor([param('ns3::Ptr< ns3::NetDevice >', 'dev')])
|
||||
## net-device-container.h: ns3::NetDeviceContainer::NetDeviceContainer(ns3::NetDeviceContainer const & a, ns3::NetDeviceContainer const & b) [constructor]
|
||||
cls.add_constructor([param('ns3::NetDeviceContainer const &', 'a'), param('ns3::NetDeviceContainer const &', 'b')])
|
||||
## net-device-container.h: __gnu_cxx::__normal_iterator<const ns3::Ptr<ns3::NetDevice>*,std::vector<ns3::Ptr<ns3::NetDevice>, std::allocator<ns3::Ptr<ns3::NetDevice> > > > ns3::NetDeviceContainer::Begin() const [member function]
|
||||
cls.add_method('Begin',
|
||||
'__gnu_cxx::__normal_iterator< const ns3::Ptr< ns3::NetDevice >, std::vector< ns3::Ptr< ns3::NetDevice > > >',
|
||||
|
||||
@@ -50,7 +50,7 @@ CsmaNetDevice::GetTypeId (void)
|
||||
Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
|
||||
MakeMac48AddressAccessor (&CsmaNetDevice::m_address),
|
||||
MakeMac48AddressChecker ())
|
||||
.AddAttribute ("FrameLength",
|
||||
.AddAttribute ("FrameSize",
|
||||
"The maximum size of a packet sent over this device.",
|
||||
UintegerValue (DEFAULT_FRAME_SIZE),
|
||||
MakeUintegerAccessor (&CsmaNetDevice::SetFrameSize,
|
||||
|
||||
@@ -685,26 +685,6 @@ private:
|
||||
|
||||
static const uint16_t DEFAULT_FRAME_SIZE = 1518;
|
||||
static const uint16_t ETHERNET_OVERHEAD = 18;
|
||||
static const uint16_t DEFAULT_MTU = (DEFAULT_FRAME_SIZE - ETHERNET_OVERHEAD);
|
||||
|
||||
/**
|
||||
* There are two MTU types that are used in this driver. The MAC-level
|
||||
* MTU corresponds to the amount of data (payload) an upper layer can
|
||||
* send across the link. The PHY-level MTU corresponds to the Type/Length
|
||||
* field in the 802.3 header and corresponds to the maximum amount of data
|
||||
* the underlying packet can accept. These are not the same thing. For
|
||||
* example, if you choose "Llc" as your encapsulation mode, the MAC-level
|
||||
* MTU will be reduced by the eight bytes with respect to the PHY-level
|
||||
* MTU which are consumed by the LLC/SNAP header.
|
||||
*
|
||||
* This method checks the current enacpuslation mode (and any other
|
||||
* relevent information) and determines if the provided frame size
|
||||
* and mtu are consistent.
|
||||
*
|
||||
* \param frameSize The proposed new frame size
|
||||
* \param mtu The proposed new MTU
|
||||
*/
|
||||
bool CheckMtuConsistency (uint16_t frameSize, uint16_t mtu);
|
||||
|
||||
/**
|
||||
* The frame size/packet size. This corresponds to the maximum
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ns3/llc-snap-header.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "point-to-point-net-device.h"
|
||||
#include "point-to-point-channel.h"
|
||||
@@ -45,6 +46,12 @@ PointToPointNetDevice::GetTypeId (void)
|
||||
Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
|
||||
MakeMac48AddressAccessor (&PointToPointNetDevice::m_address),
|
||||
MakeMac48AddressChecker ())
|
||||
.AddAttribute ("FrameSize",
|
||||
"The maximum size of a packet sent over this device.",
|
||||
UintegerValue (DEFAULT_FRAME_SIZE),
|
||||
MakeUintegerAccessor (&PointToPointNetDevice::SetFrameSize,
|
||||
&PointToPointNetDevice::GetFrameSize),
|
||||
MakeUintegerChecker<uint16_t> ())
|
||||
.AddAttribute ("DataRate",
|
||||
"The default data rate for point to point links",
|
||||
DataRateValue (DataRate ("32768b/s")),
|
||||
@@ -83,10 +90,19 @@ PointToPointNetDevice::PointToPointNetDevice ()
|
||||
m_txMachineState (READY),
|
||||
m_channel (0),
|
||||
m_name (""),
|
||||
m_linkUp (false),
|
||||
m_mtu (0xffff)
|
||||
m_linkUp (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
//
|
||||
// A quick sanity check to ensure consistent constants.
|
||||
//
|
||||
PppHeader ppp;
|
||||
NS_ASSERT_MSG (PPP_OVERHEAD == ppp.GetSerializedSize (),
|
||||
"PointToPointNetDevice::PointToPointNetDevice(): PPP_OVERHEAD inconsistent");
|
||||
|
||||
m_frameSize = DEFAULT_FRAME_SIZE;
|
||||
m_mtu = MtuFromFrameSize (m_frameSize);
|
||||
}
|
||||
|
||||
PointToPointNetDevice::~PointToPointNetDevice ()
|
||||
@@ -313,19 +329,6 @@ PointToPointNetDevice::GetAddress (void) const
|
||||
return m_address;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::SetMtu (const uint16_t mtu)
|
||||
{
|
||||
m_mtu = mtu;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PointToPointNetDevice::GetMtu (void) const
|
||||
{
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::IsLinkUp (void) const
|
||||
{
|
||||
@@ -501,4 +504,65 @@ PointToPointNetDevice::GetRemote (void) const
|
||||
return Address ();
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PointToPointNetDevice::MtuFromFrameSize (uint16_t frameSize)
|
||||
{
|
||||
NS_LOG_FUNCTION (frameSize);
|
||||
|
||||
PppHeader ppp;
|
||||
|
||||
NS_ASSERT_MSG ((uint32_t)frameSize >= ppp.GetSerializedSize (),
|
||||
"PointToPointNetDevice::MtuFromFrameSize(): Given frame size too small to support PPP");
|
||||
return frameSize - ppp.GetSerializedSize ();
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PointToPointNetDevice::FrameSizeFromMtu (uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION (mtu);
|
||||
|
||||
PppHeader ppp;
|
||||
return mtu + ppp.GetSerializedSize ();
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::SetFrameSize (uint16_t frameSize)
|
||||
{
|
||||
NS_LOG_FUNCTION (frameSize);
|
||||
|
||||
m_frameSize = frameSize;
|
||||
m_mtu = MtuFromFrameSize (frameSize);
|
||||
|
||||
NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
|
||||
NS_LOG_LOGIC ("m_mtu = " << m_mtu);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PointToPointNetDevice::GetFrameSize (void) const
|
||||
{
|
||||
return m_frameSize;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::SetMtu (uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION (mtu);
|
||||
|
||||
m_frameSize = FrameSizeFromMtu (mtu);
|
||||
m_mtu = mtu;
|
||||
|
||||
NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
|
||||
NS_LOG_LOGIC ("m_mtu = " << m_mtu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
PointToPointNetDevice::GetMtu (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -139,6 +139,93 @@ public:
|
||||
*/
|
||||
void SetAddress (Mac48Address addr);
|
||||
|
||||
/**
|
||||
* Set The max frame size of packets sent over this device.
|
||||
*
|
||||
* Okay, that was easy to say, but the details are a bit thorny. We have a MAC-level MTU that is the payload that higher
|
||||
* level protocols see. We have a PHY-level MTU which is the maximum number of bytes we can send over the link
|
||||
* (cf. 1500 bytes for Ethernet). We also have a frame size which is some total number of bytes in a packet which could
|
||||
* or could not include any framing and overhead. There can be a lot of inconsistency in definitions of these terms. For
|
||||
* example, RFC 1042 asserts that the terms maximum transmission unit and maximum packet size are equivalent. RFC 791,
|
||||
* however, defines MTU as the maximum sized IP datagram that can be sent. Packet size and frame size are sometimes
|
||||
* used interchangeably.
|
||||
*
|
||||
* So, some careful definitions are in order to avoid confusion:
|
||||
*
|
||||
* In real serial channel (HDLC, for example), the wire idles (sends all ones) until the channel begins sending a packet.
|
||||
* A frame on the wire starts with a flag character (01111110). This is followed by what is usually called the packet:
|
||||
* address, control, payload, and a Frame Check Sequence (FCS). This is followed by another flag character. If the flag
|
||||
* characters are used, then bit stuffing must be used to prevent flag characters from appearing in the packet and confusing
|
||||
* the link. Som to be strictly and pedantically correct the frame size is then necessarily larger than the packet size on
|
||||
* a real link. But, this isn't a real link, it's a simulation of a device similar to a point-to-point device, and we have
|
||||
* no good reason to add framing bits and therefore to do bit-stuffing. So, in the case of the point-to-point device, the
|
||||
* frame size is equal to the packet size. Since these two values are defined to be equal, there is no danger in assuming
|
||||
* they are identical. We define packet size to be equal to frame size and this excludes the flag characters. We define a
|
||||
* single (MAC-level) MTU that coresponds to the payload size of the packet, which is the IP-centric view of the term as
|
||||
* seen in RFC 791.
|
||||
*
|
||||
* To make this concrete, consider PPP framing on a synchronous link. In this framing scheme, a real serial frame on the
|
||||
* wire starts with a flag character, address and control characters, then a 16-bit PPP protocol ID (0x21 = IP). Then we
|
||||
* would see the actual payload we are supposed to send, presumably an IP datagram. At then we see the FCS and finally
|
||||
* another flag character to end the frame. We ignore the flag bits on this device since it they are not needed. We
|
||||
* aren't really using HDLC to send frames across the link, so we don't need the address and control bits either. In fact,
|
||||
* to encapsulate using unframed PPP all we need to do is prepend the two-byte protocol ID.
|
||||
*
|
||||
* Typically the limiting factor in frame size is due to hardware limitations in the underlying HDLC controller receive
|
||||
* FIFO buffer size. This number can vary widely. For example, the Motorola MC92460 has a 64 KByte maximum frame size;
|
||||
* the Intel IXP4XX series has a 16 KByte size. Older USARTs have a maximum frame size around 2KBytes, and typical PPP
|
||||
* links on the Internet have their MTU set to 1500 bytes since this is what will typically be used on Ethernet segments
|
||||
* and will avoid path MTU issues. We choose to make the default MTU 1500 bytes which then fixes the maximum frame size
|
||||
* as described below.
|
||||
*
|
||||
* So, there are really two related variables at work here. There is the maximum frame size that can be sent over the
|
||||
* link and there is the MTU.
|
||||
*
|
||||
* So, what do we do since these values must always be consistent in the driver? We want to actually allow a user to change
|
||||
* these variables, but we want the results (even at intermediate stages of her ultimate change) to be consistent. We
|
||||
* certainly don't want to require that users must understand the details of PPP encapsulation in order to set these
|
||||
* variables.
|
||||
*
|
||||
* Consider the following situation: A user wants to set the maximum frame size to 16 KBytes. This user shouldn't have to
|
||||
* concern herself that the PPP encapsulation will consume six bytes. She should not have to figure out that the MTU needs
|
||||
* to be set to 16K - 2 bytes to make things consistent.
|
||||
*
|
||||
* Similarly, a user who is interested in setting the MTU to 1500 bytes should not be forced to understand that the frame
|
||||
* size will need to be set to 1502 bytes.
|
||||
*
|
||||
* We could play games trying to figure out what the user wants to do, but that is typically a bad plan and programmers
|
||||
* have a long and distinguished history of guessing wrong. We'll avoid all of that and just define a flexible behavior
|
||||
* that can be worked to get what you want. Here it is:
|
||||
*
|
||||
* - If the user is changing the MTU, she is interested in getting that part of the system set, so the frame size
|
||||
* will be changed to make it consistent;
|
||||
*
|
||||
* - If the user is changing the frame size, he is interested in getting that part of the system set, so the MTU
|
||||
* will be changed to make it consistent;
|
||||
*
|
||||
* - You cannot define the MTU and frame size separately -- they are always tied together by the overhead of the PPP
|
||||
* encapsulation. This is not a restriction. Consider what this means. Perhaps you want to set the frame size to some
|
||||
* large number and the MTU to some small number. The largest packet you can send is going to be limited by the MTU, so it
|
||||
* is not possible to send a frame larger than the MTU plus overhead. Having the ability to set a larger frame size is not
|
||||
* useful.
|
||||
*
|
||||
* So, if a user calls SetFrameSize, we assume that the maximum frame size is the interesting thing for that user and
|
||||
* we just adjust the MTU to a new "correct value" based on the current encapsulation mode. If a user calls SetMtu, we
|
||||
* assume that the MTU is the interesting property for that user, and we adjust the frame size to a new "correct value"
|
||||
* for the current encapsulation mode. If a user calls SetEncapsulationMode, then we take the MTU as the free variable
|
||||
* and set its value to match the current frame size.
|
||||
*
|
||||
* \param frameSize The max frame size of packets sent over this device.
|
||||
*/
|
||||
void SetFrameSize (uint16_t frameSize);
|
||||
|
||||
/**
|
||||
* Get The max frame size of packets sent over this device.
|
||||
*
|
||||
* \returns The max frame size of packets sent over this device.
|
||||
*/
|
||||
uint16_t GetFrameSize (void) const;
|
||||
|
||||
//
|
||||
// Pure virtual methods inherited from NetDevice we must implement.
|
||||
//
|
||||
@@ -195,11 +282,24 @@ private:
|
||||
Ptr<Queue> GetQueue(void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Calculate the value for the MTU that would result from
|
||||
* setting the frame size to the given value.
|
||||
*/
|
||||
uint16_t MtuFromFrameSize (uint16_t frameSize);
|
||||
|
||||
/**
|
||||
* Calculate the value for the frame size that would be required
|
||||
* to be able to set the MTU to the given value.
|
||||
*/
|
||||
uint16_t FrameSizeFromMtu (uint16_t mtu);
|
||||
|
||||
/**
|
||||
* \returns the address of the remote device connected to this device
|
||||
* through the point to point channel.
|
||||
*/
|
||||
Address GetRemote (void) const;
|
||||
|
||||
/**
|
||||
* Adds the necessary headers and trailers to a packet of data in order to
|
||||
* respect the protocol implemented by the agent.
|
||||
@@ -314,7 +414,25 @@ private:
|
||||
std::string m_name;
|
||||
bool m_linkUp;
|
||||
Callback<void> m_linkChangeCallback;
|
||||
uint16_t m_mtu;
|
||||
|
||||
static const uint16_t DEFAULT_MTU = 1500;
|
||||
static const uint16_t PPP_OVERHEAD = 2;
|
||||
static const uint16_t DEFAULT_FRAME_SIZE = DEFAULT_MTU + PPP_OVERHEAD;
|
||||
|
||||
/**
|
||||
* The frame size/packet size. This corresponds to the maximum
|
||||
* number of bytes that can be transmitted as a packet without framing.
|
||||
* This corresponds to the 1518 byte packet size often seen on Ethernet.
|
||||
*/
|
||||
uint32_t m_frameSize;
|
||||
|
||||
/**
|
||||
* The Maxmimum Transmission Unit. This corresponds to the maximum
|
||||
* number of bytes that can be transmitted as seen from higher layers.
|
||||
* This corresponds to the 1500 byte MTU size often seen on IP over
|
||||
* Ethernet.
|
||||
*/
|
||||
uint32_t m_mtu;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
Reference in New Issue
Block a user