src/wifi/model/wifi-mode.cc
changeset 11628 243b71de25a0
parent 11450 9f4ae69f12b7
equal deleted inserted replaced
11627:01fcacb5eedf 11628:243b71de25a0
    13  *
    13  *
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    19  *          Sébastien Deronne <sebastien.deronne@gmail.com>
    19  */
    20  */
    20 
    21 
    21 #include "wifi-mode.h"
    22 #include "wifi-mode.h"
    22 #include "ns3/simulator.h"
    23 #include "ns3/simulator.h"
    23 #include "ns3/assert.h"
    24 #include "ns3/assert.h"
    24 #include "ns3/log.h"
    25 #include "ns3/log.h"
       
    26 #include <cmath>
    25 
    27 
    26 namespace ns3 {
    28 namespace ns3 {
    27 
    29 
    28 /**
    30 /**
    29  * Check if the two WifiModes are identical.
    31  * Check if the two WifiModes are identical.
    65   is >> str;
    67   is >> str;
    66   mode = WifiModeFactory::GetFactory ()->Search (str);
    68   mode = WifiModeFactory::GetFactory ()->Search (str);
    67   return is;
    69   return is;
    68 }
    70 }
    69 
    71 
    70 uint32_t
       
    71 WifiMode::GetBandwidth (void) const
       
    72 {
       
    73   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
       
    74   return item->bandwidth;
       
    75 }
       
    76 
       
    77 uint64_t
    72 uint64_t
    78 WifiMode::GetPhyRate (void) const
    73 WifiMode::GetPhyRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
    79 {
    74 {
    80   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
    75   uint32_t dataRate, phyRate;
    81   return item->phyRate;
    76   dataRate = GetDataRate (channelWidth, isShortGuardInterval, nss);
       
    77   switch (GetCodeRate (nss))
       
    78     {
       
    79     case WIFI_CODE_RATE_5_6:
       
    80       phyRate = dataRate * 6 / 5;
       
    81       break;
       
    82     case WIFI_CODE_RATE_3_4:
       
    83       phyRate = dataRate * 4 / 3;
       
    84       break;
       
    85     case WIFI_CODE_RATE_2_3:
       
    86       phyRate = dataRate * 3 / 2;
       
    87       break;
       
    88     case WIFI_CODE_RATE_1_2:
       
    89       phyRate = dataRate * 2 / 1;
       
    90       break;
       
    91     case WIFI_CODE_RATE_UNDEFINED:
       
    92     default:
       
    93       phyRate = dataRate;
       
    94       break;
       
    95     }
       
    96   return phyRate;
    82 }
    97 }
    83 
    98 
    84 uint64_t
    99 uint64_t
    85 WifiMode::GetDataRate (void) const
   100 WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
    86 {
   101 {
    87   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   102   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
    88   return item->dataRate;
   103   uint64_t dataRate = 0;
       
   104   if (nss > 1)
       
   105     {
       
   106       NS_FATAL_ERROR ("MIMO is not supported");
       
   107       return 0;
       
   108     }
       
   109   if (item->modClass == WIFI_MOD_CLASS_DSSS)
       
   110     {
       
   111       dataRate = (11000000 / 11) * log2 (GetConstellationSize (1));
       
   112     }
       
   113   else if (item->modClass == WIFI_MOD_CLASS_HR_DSSS)
       
   114     {
       
   115       dataRate = (11000000 / 8) * log2 (GetConstellationSize (1));
       
   116     }
       
   117   else if (item->modClass == WIFI_MOD_CLASS_OFDM || item->modClass == WIFI_MOD_CLASS_ERP_OFDM)
       
   118     {
       
   119       double symbolRate = (1 / 4.0) * 1e6;
       
   120 
       
   121       uint32_t usableSubCarriers;
       
   122       switch (channelWidth)
       
   123         {
       
   124         case 20:
       
   125         default:
       
   126           usableSubCarriers = 48;
       
   127           break;
       
   128         case 10:
       
   129           usableSubCarriers = 24;
       
   130           break;
       
   131         case 5:
       
   132           usableSubCarriers = 12;
       
   133           break;
       
   134         }
       
   135 
       
   136       double codingRate;
       
   137       switch (GetCodeRate (1))
       
   138         {
       
   139         case WIFI_CODE_RATE_3_4:
       
   140           codingRate = (3.0 / 4.0);
       
   141           break;
       
   142         case WIFI_CODE_RATE_2_3:
       
   143           codingRate = (2.0 / 3.0);
       
   144           break;
       
   145         case WIFI_CODE_RATE_1_2:
       
   146           codingRate = (1.0 / 2.0);
       
   147           break;
       
   148         case WIFI_CODE_RATE_UNDEFINED:
       
   149         default:
       
   150           NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined");
       
   151           break;
       
   152         }
       
   153 
       
   154       uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (1));
       
   155 
       
   156       dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
       
   157     }
       
   158   else if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
       
   159     {
       
   160       if (item->mcsValue == 9)
       
   161         {
       
   162           //VHT MCS 9 forbidden at 20 MHz
       
   163           NS_ASSERT (channelWidth != 20);
       
   164         }
       
   165 
       
   166       double symbolRate;
       
   167       if (!isShortGuardInterval)
       
   168         {
       
   169           symbolRate = (1 / 4.0) * 1e6;
       
   170         }
       
   171       else
       
   172         {
       
   173           symbolRate = (1 / 3.6) * 1e6;
       
   174         }
       
   175 
       
   176       uint32_t usableSubCarriers;
       
   177       switch (channelWidth)
       
   178         {
       
   179         case 20:
       
   180         default:
       
   181           usableSubCarriers = 52;
       
   182           break;
       
   183         case 40:
       
   184           usableSubCarriers = 108;
       
   185           break;
       
   186         case 80:
       
   187           usableSubCarriers = 234;
       
   188           break;
       
   189         case 160:
       
   190           usableSubCarriers = 468;
       
   191           break;
       
   192         }
       
   193 
       
   194       double codingRate;
       
   195       switch (GetCodeRate (nss))
       
   196         {
       
   197         case WIFI_CODE_RATE_5_6:
       
   198           codingRate = (5.0 / 6.0);
       
   199           break;
       
   200         case WIFI_CODE_RATE_3_4:
       
   201           codingRate = (3.0 / 4.0);
       
   202           break;
       
   203         case WIFI_CODE_RATE_2_3:
       
   204           codingRate = (2.0 / 3.0);
       
   205           break;
       
   206         case WIFI_CODE_RATE_1_2:
       
   207           codingRate = (1.0 / 2.0);
       
   208           break;
       
   209         case WIFI_CODE_RATE_UNDEFINED:
       
   210         default:
       
   211           NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined");
       
   212           break;
       
   213         }
       
   214 
       
   215       uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (nss));
       
   216 
       
   217       dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
       
   218     }
       
   219   else
       
   220     {
       
   221       NS_ASSERT ("undefined datarate for the modulation class!");
       
   222     }
       
   223   return dataRate;
    89 }
   224 }
    90 
   225 
    91 enum WifiCodeRate
   226 enum WifiCodeRate
    92 WifiMode::GetCodeRate (void) const
   227 WifiMode::GetCodeRate (uint8_t nss) const
    93 {
   228 {
    94   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   229   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
    95   return item->codingRate;
   230   if (item->modClass == WIFI_MOD_CLASS_HT)
    96 }
   231     {
    97 
   232       NS_ASSERT (nss <= 4);
    98 uint8_t
   233       NS_ASSERT ((item->mcsValue - (8 * (nss - 1))) >= 0 || (item->mcsValue - (8 * (nss - 1))) <= 7);
    99 WifiMode::GetConstellationSize (void) const
   234       switch (item->mcsValue - (8 * (nss - 1)))
   100 {
   235         {
   101   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   236         case 0:
   102   return item->constellationSize;
   237         case 1:
       
   238         case 3:
       
   239           return WIFI_CODE_RATE_1_2;
       
   240         case 2:
       
   241         case 4:
       
   242         case 6:
       
   243           return WIFI_CODE_RATE_3_4;
       
   244         case 5:
       
   245           return WIFI_CODE_RATE_2_3;
       
   246         case 7:
       
   247           return WIFI_CODE_RATE_5_6;
       
   248         default:
       
   249           return WIFI_CODE_RATE_UNDEFINED;
       
   250         }
       
   251     }
       
   252   else if (item->modClass == WIFI_MOD_CLASS_VHT)
       
   253     {
       
   254       NS_ASSERT (nss <= 8);
       
   255       switch (item->mcsValue)
       
   256         {
       
   257         case 0:
       
   258         case 1:
       
   259         case 3:
       
   260           return WIFI_CODE_RATE_1_2;
       
   261         case 2:
       
   262         case 4:
       
   263         case 6:
       
   264         case 8:
       
   265           return WIFI_CODE_RATE_3_4;
       
   266         case 5:
       
   267           return WIFI_CODE_RATE_2_3;
       
   268         case 7:
       
   269         case 9:
       
   270           return WIFI_CODE_RATE_5_6;
       
   271         default:
       
   272           return WIFI_CODE_RATE_UNDEFINED;
       
   273         }
       
   274     }
       
   275   else
       
   276     {
       
   277       return item->codingRate;
       
   278     }
       
   279 }
       
   280 
       
   281 uint16_t
       
   282 WifiMode::GetConstellationSize (uint8_t nss) const
       
   283 {
       
   284   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
       
   285   if (item->modClass == WIFI_MOD_CLASS_HT)
       
   286     {
       
   287       NS_ASSERT (nss <= 4);
       
   288       NS_ASSERT ((item->mcsValue - (8 * (nss - 1))) >= 0 || (item->mcsValue - (8 * (nss - 1))) <= 7);
       
   289       switch (item->mcsValue - (8 * (nss - 1)))
       
   290         {
       
   291         case 0:
       
   292           return 2;
       
   293         case 1:
       
   294         case 2:
       
   295           return 4;
       
   296         case 3:
       
   297         case 4:
       
   298           return 16;
       
   299         case 5:
       
   300         case 6:
       
   301         case 7:
       
   302           return 64;
       
   303         default:
       
   304           return 0;
       
   305         }
       
   306     }
       
   307   else if (item->modClass == WIFI_MOD_CLASS_VHT)
       
   308     {
       
   309       NS_ASSERT (nss <= 8);
       
   310       switch (item->mcsValue)
       
   311         {
       
   312         case 0:
       
   313           return 2;
       
   314         case 1:
       
   315         case 2:
       
   316           return 4;
       
   317         case 3:
       
   318         case 4:
       
   319           return 16;
       
   320         case 5:
       
   321         case 6:
       
   322         case 7:
       
   323           return 64;
       
   324         case 8:
       
   325         case 9:
       
   326           return 256;
       
   327         default:
       
   328           return 0;
       
   329         }
       
   330     }
       
   331   else
       
   332     {
       
   333       return item->constellationSize;
       
   334     }
   103 }
   335 }
   104 
   336 
   105 std::string
   337 std::string
   106 WifiMode::GetUniqueName (void) const
   338 WifiMode::GetUniqueName (void) const
   107 {
   339 {
   115 {
   347 {
   116   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   348   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   117   return item->isMandatory;
   349   return item->isMandatory;
   118 }
   350 }
   119 
   351 
       
   352 uint8_t
       
   353 WifiMode::GetMcsValue (void) const
       
   354 {
       
   355   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
       
   356   if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
       
   357     {
       
   358       return item->mcsValue;
       
   359     }
       
   360   else
       
   361     {
       
   362       //We should not go here!
       
   363       NS_ASSERT (false);
       
   364       return 0;
       
   365     }
       
   366 }
       
   367 
   120 uint32_t
   368 uint32_t
   121 WifiMode::GetUid (void) const
   369 WifiMode::GetUid (void) const
   122 {
   370 {
   123   return m_uid;
   371   return m_uid;
   124 }
   372 }
   132 
   380 
   133 WifiMode::WifiMode ()
   381 WifiMode::WifiMode ()
   134   : m_uid (0)
   382   : m_uid (0)
   135 {
   383 {
   136 }
   384 }
       
   385 
   137 WifiMode::WifiMode (uint32_t uid)
   386 WifiMode::WifiMode (uint32_t uid)
   138   : m_uid (uid)
   387   : m_uid (uid)
   139 {
   388 {
   140 }
   389 }
   141 
   390 
   152 
   401 
   153 WifiMode
   402 WifiMode
   154 WifiModeFactory::CreateWifiMode (std::string uniqueName,
   403 WifiModeFactory::CreateWifiMode (std::string uniqueName,
   155                                  enum WifiModulationClass modClass,
   404                                  enum WifiModulationClass modClass,
   156                                  bool isMandatory,
   405                                  bool isMandatory,
   157                                  uint32_t bandwidth,
       
   158                                  uint32_t dataRate,
       
   159                                  enum WifiCodeRate codingRate,
   406                                  enum WifiCodeRate codingRate,
   160                                  uint8_t constellationSize)
   407                                  uint16_t constellationSize)
   161 {
   408 {
   162   WifiModeFactory *factory = GetFactory ();
   409   WifiModeFactory *factory = GetFactory ();
   163   uint32_t uid = factory->AllocateUid (uniqueName);
   410   uint32_t uid = factory->AllocateUid (uniqueName);
   164   WifiModeItem *item = factory->Get (uid);
   411   WifiModeItem *item = factory->Get (uid);
   165   item->uniqueUid = uniqueName;
   412   item->uniqueUid = uniqueName;
   166   item->modClass = modClass;
   413   item->modClass = modClass;
   167   //The modulation class for this WifiMode must be valid.
   414   //The modulation class for this WifiMode must be valid.
   168   NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
   415   NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
   169   item->bandwidth = bandwidth;
       
   170   item->dataRate = dataRate;
       
   171   item->codingRate = codingRate;
   416   item->codingRate = codingRate;
   172 
       
   173   switch (codingRate)
       
   174     {
       
   175     case WIFI_CODE_RATE_5_6:
       
   176       item->phyRate = dataRate * 6 / 5;
       
   177       break;
       
   178     case WIFI_CODE_RATE_3_4:
       
   179       item->phyRate = dataRate * 4 / 3;
       
   180       break;
       
   181     case WIFI_CODE_RATE_2_3:
       
   182       item->phyRate = dataRate * 3 / 2;
       
   183       break;
       
   184     case WIFI_CODE_RATE_1_2:
       
   185       item->phyRate = dataRate * 2 / 1;
       
   186       break;
       
   187     case WIFI_CODE_RATE_UNDEFINED:
       
   188     default:
       
   189       item->phyRate = dataRate;
       
   190       break;
       
   191     }
       
   192 
   417 
   193   //Check for compatibility between modulation class and coding
   418   //Check for compatibility between modulation class and coding
   194   //rate. If modulation class is DSSS then coding rate must be
   419   //rate. If modulation class is DSSS then coding rate must be
   195   //undefined, and vice versa. I could have done this with an
   420   //undefined, and vice versa. I could have done this with an
   196   //assertion, but it seems better to always give the error (i.e.,
   421   //assertion, but it seems better to always give the error (i.e.,
   197   //not only in non-optimised builds) and the cycles that extra test
   422   //not only in non-optimised builds) and the cycles that extra test
   198   //here costs are only suffered at simulation setup.
   423   //here costs are only suffered at simulation setup.
   199   if ((codingRate == WIFI_CODE_RATE_UNDEFINED) != (modClass == WIFI_MOD_CLASS_DSSS))
   424   if ((codingRate == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS)
   200     {
   425     {
   201       NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
   426       NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
   202                                                              << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS");
   427                                                              << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS");
   203     }
   428     }
   204 
   429 
   205   item->constellationSize = constellationSize;
   430   item->constellationSize = constellationSize;
   206   item->isMandatory = isMandatory;
   431   item->isMandatory = isMandatory;
       
   432 
       
   433   NS_ASSERT (modClass != WIFI_MOD_CLASS_HT && modClass != WIFI_MOD_CLASS_VHT);
       
   434   //fill unused mcs item with a dummy value
       
   435   item->mcsValue = 0;
       
   436 
       
   437   return WifiMode (uid);
       
   438 }
       
   439 
       
   440 WifiMode
       
   441 WifiModeFactory::CreateWifiMcs (std::string uniqueName,
       
   442                                 uint8_t mcsValue,
       
   443                                 enum WifiModulationClass modClass)
       
   444 {
       
   445   WifiModeFactory *factory = GetFactory ();
       
   446   uint32_t uid = factory->AllocateUid (uniqueName);
       
   447   WifiModeItem *item = factory->Get (uid);
       
   448   item->uniqueUid = uniqueName;
       
   449   item->modClass = modClass;
       
   450 
       
   451   //The modulation class must be either HT or VHT
       
   452   NS_ASSERT (modClass == WIFI_MOD_CLASS_HT || modClass == WIFI_MOD_CLASS_VHT);
       
   453 
       
   454   item->mcsValue = mcsValue;
       
   455   //fill unused items with dummy values
       
   456   item->constellationSize = 0;
       
   457   item->codingRate = WIFI_CODE_RATE_UNDEFINED;
       
   458   item->isMandatory = false;
   207 
   459 
   208   return WifiMode (uid);
   460   return WifiMode (uid);
   209 }
   461 }
   210 
   462 
   211 WifiMode
   463 WifiMode
   276   if (isFirstTime)
   528   if (isFirstTime)
   277     {
   529     {
   278       uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
   530       uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
   279       WifiModeItem *item = factory.Get (uid);
   531       WifiModeItem *item = factory.Get (uid);
   280       item->uniqueUid = "Invalid-WifiMode";
   532       item->uniqueUid = "Invalid-WifiMode";
   281       item->bandwidth = 0;
       
   282       item->dataRate = 0;
       
   283       item->phyRate = 0;
       
   284       item->modClass = WIFI_MOD_CLASS_UNKNOWN;
   533       item->modClass = WIFI_MOD_CLASS_UNKNOWN;
   285       item->constellationSize = 0;
   534       item->constellationSize = 0;
   286       item->codingRate = WIFI_CODE_RATE_UNDEFINED;
   535       item->codingRate = WIFI_CODE_RATE_UNDEFINED;
   287       item->isMandatory = false;
   536       item->isMandatory = false;
       
   537       item->mcsValue = 0;
   288       isFirstTime = false;
   538       isFirstTime = false;
   289     }
   539     }
   290   return &factory;
   540   return &factory;
   291 }
   541 }
   292 
   542