1.1 --- a/examples/udp-echo.cc Sun Aug 03 21:55:49 2008 -0700
1.2 +++ b/examples/udp-echo.cc Mon Aug 04 17:32:32 2008 -0700
1.3 @@ -89,6 +89,7 @@
1.4 CsmaHelper csma;
1.5 csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
1.6 csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
1.7 + csma.SetDeviceAttribute ("MTU", UintegerValue (1400));
1.8 NetDeviceContainer d = csma.Install (n);
1.9
1.10 Ipv4AddressHelper ipv4;
2.1 --- a/src/devices/csma/csma-net-device.cc Sun Aug 03 21:55:49 2008 -0700
2.2 +++ b/src/devices/csma/csma-net-device.cc Mon Aug 04 17:32:32 2008 -0700
2.3 @@ -52,18 +52,20 @@
2.4 MakeMac48AddressChecker ())
2.5 .AddAttribute ("PayloadLength",
2.6 "The max PHY-level payload length of packets sent over this device.",
2.7 - UintegerValue (DEFAULT_FRAME_LENGTH),
2.8 - MakeUintegerAccessor (&CsmaNetDevice::m_maxPayloadLength),
2.9 + UintegerValue (DEFAULT_PAYLOAD_LENGTH),
2.10 + MakeUintegerAccessor (&CsmaNetDevice::SetMaxPayloadLength,
2.11 + &CsmaNetDevice::GetMaxPayloadLength),
2.12 MakeUintegerChecker<uint16_t> ())
2.13 .AddAttribute ("MTU",
2.14 "The MAC-level MTU (client payload) of packets sent over this device.",
2.15 UintegerValue (DEFAULT_MTU),
2.16 - MakeUintegerAccessor (&CsmaNetDevice::m_mtu),
2.17 + MakeUintegerAccessor (&CsmaNetDevice::SetMacMtu,
2.18 + &CsmaNetDevice::GetMacMtu),
2.19 MakeUintegerChecker<uint16_t> ())
2.20 .AddAttribute ("EncapsulationMode",
2.21 "The link-layer encapsulation type to use.",
2.22 EnumValue (LLC),
2.23 - MakeEnumAccessor (&CsmaNetDevice::m_encapMode),
2.24 + MakeEnumAccessor (&CsmaNetDevice::SetEncapsulationMode),
2.25 MakeEnumChecker (ETHERNET_V1, "EthernetV1",
2.26 IP_ARP, "IpArp",
2.27 RAW, "Raw",
2.28 @@ -106,6 +108,14 @@
2.29 m_txMachineState = READY;
2.30 m_tInterframeGap = Seconds (0);
2.31 m_channel = 0;
2.32 +
2.33 + m_encapMode = LLC;
2.34 + m_maxPayloadLength = DEFAULT_PAYLOAD_LENGTH;
2.35 + m_mtu = MacMtuFromPayload (m_maxPayloadLength);
2.36 +
2.37 + NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
2.38 + NS_LOG_LOGIC ("m_maxPayloadLength = " << m_maxPayloadLength);
2.39 + NS_LOG_LOGIC ("m_mtu = " << m_mtu);
2.40 }
2.41
2.42 CsmaNetDevice::~CsmaNetDevice()
2.43 @@ -123,6 +133,133 @@
2.44 NetDevice::DoDispose ();
2.45 }
2.46
2.47 + uint16_t
2.48 +CsmaNetDevice::MacMtuFromPayload (uint16_t payloadLength)
2.49 +{
2.50 + NS_LOG_FUNCTION (payloadLength);
2.51 +
2.52 + switch (m_encapMode)
2.53 + {
2.54 + case RAW:
2.55 + case IP_ARP:
2.56 + case ETHERNET_V1:
2.57 + return payloadLength;
2.58 + case LLC:
2.59 + {
2.60 + LlcSnapHeader llc;
2.61 +
2.62 + NS_ASSERT_MSG (payloadLength >= llc.GetSerializedSize (), "CsmaNetDevice::MacMtuFromPayload(): "
2.63 + "Given payload too small to support LLC mode");
2.64 + return payloadLength - llc.GetSerializedSize ();
2.65 + }
2.66 + }
2.67 +
2.68 + NS_ASSERT_MSG (false, "CsmaNetDevice::MacMtuFromPayload(): Unexpected encapsulation mode");
2.69 + return 0;
2.70 +}
2.71 +
2.72 + uint16_t
2.73 +CsmaNetDevice::PayloadFromMacMtu (uint16_t mtu)
2.74 +{
2.75 + NS_LOG_FUNCTION (mtu);
2.76 +
2.77 + switch (m_encapMode)
2.78 + {
2.79 + case RAW:
2.80 + case IP_ARP:
2.81 + case ETHERNET_V1:
2.82 + return mtu;
2.83 + case LLC:
2.84 + {
2.85 + LlcSnapHeader llc;
2.86 + return mtu + llc.GetSerializedSize ();
2.87 + }
2.88 + }
2.89 +
2.90 + NS_ASSERT_MSG (false, "CsmaNetDevice::PayloadFromMacMtu(): Unexpected encapsulation mode");
2.91 + return 0;
2.92 +}
2.93 +
2.94 + void
2.95 +CsmaNetDevice::SetEncapsulationMode (enum EncapsulationMode mode)
2.96 +{
2.97 + NS_LOG_FUNCTION (mode);
2.98 +
2.99 + m_encapMode = mode;
2.100 + m_mtu = MacMtuFromPayload (m_maxPayloadLength);
2.101 +
2.102 + NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
2.103 + NS_LOG_LOGIC ("m_maxPayloadLength = " << m_maxPayloadLength);
2.104 + NS_LOG_LOGIC ("m_mtu = " << m_mtu);
2.105 +}
2.106 +
2.107 + CsmaNetDevice::EncapsulationMode
2.108 +CsmaNetDevice::GetEncapsulationMode (void)
2.109 +{
2.110 + NS_LOG_FUNCTION_NOARGS ();
2.111 + return m_encapMode;
2.112 +}
2.113 +
2.114 + void
2.115 +CsmaNetDevice::SetMacMtu (uint16_t mtu)
2.116 +{
2.117 + NS_LOG_FUNCTION (mtu);
2.118 +
2.119 + m_maxPayloadLength = PayloadFromMacMtu (mtu);
2.120 + m_mtu = mtu;
2.121 +
2.122 + NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
2.123 + NS_LOG_LOGIC ("m_maxPayloadLength = " << m_maxPayloadLength);
2.124 + NS_LOG_LOGIC ("m_mtu = " << m_mtu);
2.125 +}
2.126 +
2.127 + uint16_t
2.128 +CsmaNetDevice::GetMacMtu (void) const
2.129 +{
2.130 + NS_LOG_FUNCTION_NOARGS ();
2.131 + return m_mtu;
2.132 +}
2.133 +
2.134 +//
2.135 +// The SetMtu method in the net device base class always refers to the MAC-level MTU by definition.
2.136 +//
2.137 + bool
2.138 +CsmaNetDevice::SetMtu (const uint16_t mtu)
2.139 +{
2.140 + NS_LOG_FUNCTION (mtu);
2.141 + SetMacMtu (mtu);
2.142 + return true;
2.143 +}
2.144 +
2.145 +//
2.146 +// The GetMtu method in the net device base class always refers to the MAC-level MTU by definition.
2.147 +//
2.148 + uint16_t
2.149 +CsmaNetDevice::GetMtu (void) const
2.150 +{
2.151 + NS_LOG_FUNCTION_NOARGS ();
2.152 + return GetMacMtu ();
2.153 +}
2.154 +
2.155 + void
2.156 +CsmaNetDevice::SetMaxPayloadLength (uint16_t maxPayloadLength)
2.157 +{
2.158 + NS_LOG_FUNCTION (maxPayloadLength);
2.159 +
2.160 + m_maxPayloadLength = maxPayloadLength;
2.161 + m_mtu = MacMtuFromPayload (maxPayloadLength);
2.162 +
2.163 + NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
2.164 + NS_LOG_LOGIC ("m_maxPayloadLength = " << m_maxPayloadLength);
2.165 + NS_LOG_LOGIC ("m_mtu = " << m_mtu);
2.166 +}
2.167 +
2.168 + uint16_t
2.169 +CsmaNetDevice::GetMaxPayloadLength (void) const
2.170 +{
2.171 + return m_maxPayloadLength;
2.172 +}
2.173 +
2.174 void
2.175 CsmaNetDevice::SetAddress (Mac48Address self)
2.176 {
2.177 @@ -193,6 +330,7 @@
2.178 EthernetTrailer trailer;
2.179
2.180 NS_LOG_LOGIC ("p->GetSize () = " << p->GetSize ());
2.181 + NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
2.182 NS_LOG_LOGIC ("m_mtu = " << m_mtu);
2.183 NS_LOG_LOGIC ("m_maxPayloadLength = " << m_maxPayloadLength);
2.184
2.185 @@ -238,8 +376,7 @@
2.186 }
2.187 break;
2.188 case RAW:
2.189 - NS_LOG_LOGIC ("Encapsulating packet as RAW");
2.190 - NS_ASSERT (false);
2.191 + NS_ASSERT_MSG (false, "CsmaNetDevice::AddHeader(): RAW packet encapsulation not supported");
2.192 break;
2.193 }
2.194
2.195 @@ -680,21 +817,6 @@
2.196 }
2.197
2.198 bool
2.199 -CsmaNetDevice::SetMtu (const uint16_t mtu)
2.200 -{
2.201 - NS_LOG_FUNCTION (mtu);
2.202 - m_mtu = mtu;
2.203 - return true;
2.204 -}
2.205 -
2.206 - uint16_t
2.207 -CsmaNetDevice::GetMtu (void) const
2.208 -{
2.209 - NS_LOG_FUNCTION_NOARGS ();
2.210 - return m_mtu;
2.211 -}
2.212 -
2.213 - bool
2.214 CsmaNetDevice::IsLinkUp (void) const
2.215 {
2.216 NS_LOG_FUNCTION_NOARGS ();
3.1 --- a/src/devices/csma/csma-net-device.h Sun Aug 03 21:55:49 2008 -0700
3.2 +++ b/src/devices/csma/csma-net-device.h Mon Aug 04 17:32:32 2008 -0700
3.3 @@ -65,11 +65,12 @@
3.4 {
3.5 public:
3.6 static TypeId GetTypeId (void);
3.7 +
3.8 /**
3.9 * Enumeration of the types of packets supported in the class.
3.10 *
3.11 */
3.12 - enum CsmaEncapsulationMode {
3.13 + enum EncapsulationMode {
3.14 ETHERNET_V1, /**< Version one ethernet packet, length field */
3.15 IP_ARP, /**< Ethernet packet encapsulates IP/ARP packet */
3.16 RAW, /**< Packet that contains no headers */
3.17 @@ -197,17 +198,108 @@
3.18 */
3.19 void SetAddress (Mac48Address addr);
3.20
3.21 -//
3.22 -// The following methods are inherited from NetDevice base class.
3.23 -//
3.24 + /**
3.25 + * Set The max PHY-level payload length of packets sent over this device.
3.26 + *
3.27 + * Okay, that was easy to say, but the details are a bit thorny. We have a MAC-level that is the payload that higher
3.28 + * level protocols see. We have a PHY-level MTU which is the maximum number of bytes we can send over the link
3.29 + * (cf. 1500 bytes for Ethernet). The value that determines the relationship between these two values is the link
3.30 + * encapsulation mode. The link encapsulation defines the number of bytes of overhead that are required for the particular
3.31 + * MAC protocol used. For example, if the LLC/SNAP encapsulation is used, eight bytes of LLC/SNAP header are consumed and
3.32 + * therefore the MAC-level MTU must be set and reported as eight bytes less than the PHY-level MTU (which we call the
3.33 + * payload length to try and avoid confusion).
3.34 + *
3.35 + * So, what do we do since there must be three values which must always be consistent in the driver? Which values to we
3.36 + * allow to be changed and how do we ensure the other two are consistent? We want to actually enable a user to change
3.37 + * these two payload lengths in flexible ways, but we want the results (even at intermediate stages) to be consistent.
3.38 + * We certainly don't want to require that users must understand the various requirements of an enapsulation mode in order
3.39 + * to set these variables.
3.40 + *
3.41 + * Consider the following situation: A user wants to set the physical layer MTU to 1400 bytes instead of 1500. This
3.42 + * user shouldn't have to concern herself that the current encapuslation mode is LLC and this will consume eight bytes.
3.43 + * She should not have to also set the MAC MTU to 1392 bytes, and she should certainly not have to do this before setting
3.44 + * the PHY MTU.
3.45 + *
3.46 + * A user who is interested in setting the MAC-level MTU to 1400 bytes should not be forced to understand that in certain
3.47 + * cases the PHY-level MTU must be set to eight bytes more than what he wants in certain cases and zero bytes in others.
3.48 + *
3.49 + * Now, consider a user who is only interested in changing the encapsulation mode from LLC/SNAP to ETHERNET_V1. This
3.50 + * is going to change the relationship between the MAC MTU and the PHY MTU. We've may have to come up with a new value
3.51 + * for at least one of the MTUs? Which one?
3.52 + *
3.53 + * We could play games trying to figure out what the user wants to do, but that is typically a bad plan. So we're going
3.54 + * to just define a flexible behavior. Here it is:
3.55 + *
3.56 + * - If the user is changing the encapsulation mode, the PHY MTU will remain fixed and the MAC MTU will change, if required,
3.57 + * to make the three values consistent;
3.58 + *
3.59 + * - If the user is changing the MAC MTU, she is interested in getting that part of the system set, so the PHY MTU
3.60 + * will be changed to make the three values consistent;
3.61 + *
3.62 + * - If the user is changing the PHY MTU, he is interested in getting that part of the system set, so the MAC MTU
3.63 + * will be changed to make the three values consistent.
3.64 + *
3.65 + * So, if a user calls SetMaxPayloadLength, we assume that the PHY-level MTU is the interesting thing for that user and
3.66 + * we just adjust the MAC-level MTU to "the correct value" based on the current encapsulation mode. If a user calls
3.67 + * SetMacMtu, we assume that the MAC-level MTU is the interesting property for that user, and we adjust the PHY-level MTU
3.68 + * to "the correct value" for the current encapsulation mode. If a user calls SetEncapsulationMode, then we take the
3.69 + * MAC-level MTU as the free variable and set its value to match the current PHY-level MTU.
3.70 + *
3.71 + * \param mayPayloadLength The max PHY-level payload length of packets sent over this device.
3.72 + */
3.73 + void SetMaxPayloadLength (uint16_t maxPayloadLength);
3.74 +
3.75 + /**
3.76 + * Get The max PHY-level payload length of packets sent over this device.
3.77 + *
3.78 + * \returns The max PHY-level payload length of packets sent over this device.
3.79 + */
3.80 + uint16_t GetMaxPayloadLength (void) const;
3.81 +
3.82 + /**
3.83 + * Set The MAC-level MTU (client payload) of packets sent over this device.
3.84 + *
3.85 + * \param mtu The MAC-level MTU (client payload) of packets sent over this device.
3.86 + *
3.87 + * \see SetMaxPayloadLength
3.88 + */
3.89 + void SetMacMtu (uint16_t mtu);
3.90 +
3.91 + /**
3.92 + * Get The MAC-level MTU (client payload) of packets sent over this device.
3.93 + *
3.94 + * \returns The MAC-level MTU (client payload) of packets sent over this device.
3.95 + */
3.96 + uint16_t GetMacMtu (void) const;
3.97 +
3.98 +
3.99 + /**
3.100 + * Set the encapsulation mode of this device.
3.101 + *
3.102 + * \param mode The encapsulation mode of this device.
3.103 + *
3.104 + * \see SetMaxPayloadLength
3.105 + */
3.106 + void SetEncapsulationMode (CsmaNetDevice::EncapsulationMode mode);
3.107 +
3.108 + /**
3.109 + * Get the encapsulation mode of this device.
3.110 + *
3.111 + * \returns The encapsulation mode of this device.
3.112 + */
3.113 + CsmaNetDevice::EncapsulationMode GetEncapsulationMode (void);
3.114 +
3.115 + //
3.116 + // The following methods are inherited from NetDevice base class.
3.117 + //
3.118 virtual void SetName (const std::string name);
3.119 virtual std::string GetName (void) const;
3.120 virtual void SetIfIndex (const uint32_t index);
3.121 virtual uint32_t GetIfIndex (void) const;
3.122 virtual Ptr<Channel> GetChannel (void) const;
3.123 - virtual Address GetAddress (void) const;
3.124 virtual bool SetMtu (const uint16_t mtu);
3.125 virtual uint16_t GetMtu (void) const;
3.126 + virtual Address GetAddress (void) const;
3.127 virtual bool IsLinkUp (void) const;
3.128 virtual void SetLinkChangeCallback (Callback<void> callback);
3.129 virtual bool IsBroadcast (void) const;
3.130 @@ -333,9 +425,6 @@
3.131
3.132 private:
3.133
3.134 - static const uint16_t DEFAULT_FRAME_LENGTH = 1500;
3.135 - static const uint16_t DEFAULT_MTU = 1492;
3.136 -
3.137 /**
3.138 * Operator = is declared but not implemented. This disables the assigment
3.139 * operator for CsmaNetDevice objects.
3.140 @@ -355,6 +444,18 @@
3.141 void Init (bool sendEnable, bool receiveEnable);
3.142
3.143 /**
3.144 + * Calculate the value for the MAC-level MTU that would result from
3.145 + * setting the PHY-level MTU to the given value.
3.146 + */
3.147 + uint16_t MacMtuFromPayload (uint16_t payloadLength);
3.148 +
3.149 + /**
3.150 + * Calculate the value for the PHY-level MTU that would be required
3.151 + * to be able to set the MAC-level MTU to the given value.
3.152 + */
3.153 + uint16_t PayloadFromMacMtu (uint16_t mtu);
3.154 +
3.155 + /**
3.156 * Start Sending a Packet Down the Wire.
3.157 *
3.158 * The TransmitStart method is the method that is used internally in
3.159 @@ -460,7 +561,7 @@
3.160 * function and that should be processed by the ProcessHeader
3.161 * function.
3.162 */
3.163 - CsmaEncapsulationMode m_encapMode;
3.164 + EncapsulationMode m_encapMode;
3.165
3.166 /**
3.167 * The data rate that the Net Device uses to simulate packet transmission
3.168 @@ -568,6 +669,28 @@
3.169 */
3.170 Callback<void> m_linkChangeCallback;
3.171
3.172 + static const uint16_t DEFAULT_PAYLOAD_LENGTH = 1500;
3.173 + static const uint16_t DEFAULT_MTU = 1492;
3.174 +
3.175 + /**
3.176 + * There are two MTU types that are used in this driver. The MAC-level
3.177 + * MTU corresponds to the amount of data (payload) an upper layer can
3.178 + * send across the link. The PHY-level MTU corresponds to the Type/Length
3.179 + * field in the 802.3 header and corresponds to the maximum amount of data
3.180 + * the underlying packet can accept. These are not the same thing. For
3.181 + * example, if you choose "Llc" as your encapsulation mode, the MAC-level
3.182 + * MTU will be reduced by the eight bytes with respect to the PHY-level
3.183 + * MTU which are consumed by the LLC/SNAP header.
3.184 + *
3.185 + * This method checks the current enacpuslation mode (and any other
3.186 + * relevent information) and determines if the provided payloadLength
3.187 + * (PHY-level MTU) and mtu (MAC-level MTU) are consistent.
3.188 + *
3.189 + * \param payloadLength The proposed PHY-level MTU
3.190 + * \param mtu The proposed MAC-level MTU
3.191 + */
3.192 + bool CheckMtuConsistency (uint16_t payloadLength, uint16_t mtu);
3.193 +
3.194 /**
3.195 * The MAC-level maximum transmission unit allowed to be sent or received by
3.196 * this network device. This corresponds to the maximum payload the device