sort out various MTU options
authorCraig Dowell <craigdo@ee.washington.edu>
Mon Aug 04 17:32:32 2008 -0700 (18 months ago)
changeset 3506cba7b2b80fe8
parent 3504 0261c789e17e
child 3507 11bfc339df59
sort out various MTU options
examples/udp-echo.cc
src/devices/csma/csma-net-device.cc
src/devices/csma/csma-net-device.h
     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