--- a/bindings/python/ns3_module_csma.py Fri Sep 05 11:57:56 2008 -0700
+++ b/bindings/python/ns3_module_csma.py Fri Sep 05 15:18:20 2008 -0700
@@ -14,7 +14,7 @@
## 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 @@
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)
--- a/bindings/python/ns3_module_helper.py Fri Sep 05 11:57:56 2008 -0700
+++ b/bindings/python/ns3_module_helper.py Fri Sep 05 15:18:20 2008 -0700
@@ -313,6 +313,10 @@
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 > > >',
--- a/src/devices/csma/csma-net-device.cc Fri Sep 05 11:57:56 2008 -0700
+++ b/src/devices/csma/csma-net-device.cc Fri Sep 05 15:18:20 2008 -0700
@@ -50,7 +50,7 @@
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,
--- a/src/devices/csma/csma-net-device.h Fri Sep 05 11:57:56 2008 -0700
+++ b/src/devices/csma/csma-net-device.h Fri Sep 05 15:18:20 2008 -0700
@@ -685,26 +685,6 @@
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
--- a/src/devices/point-to-point/point-to-point-net-device.cc Fri Sep 05 11:57:56 2008 -0700
+++ b/src/devices/point-to-point/point-to-point-net-device.cc Fri Sep 05 15:18:20 2008 -0700
@@ -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 @@
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 @@
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 ()
@@ -314,19 +330,6 @@
}
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
{
return m_linkUp;
@@ -501,4 +504,65 @@
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
--- a/src/devices/point-to-point/point-to-point-net-device.h Fri Sep 05 11:57:56 2008 -0700
+++ b/src/devices/point-to-point/point-to-point-net-device.h Fri Sep 05 15:18:20 2008 -0700
@@ -139,6 +139,93 @@
*/
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.
//
@@ -196,10 +283,23 @@
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 @@
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