38 #include <libxml/parser.h>    46   const int PRECISION_FACTOR{100};
    48   inline xmlChar * toXMLChar(
const char * p)
    50       return reinterpret_cast<xmlChar *
>(
const_cast<char *
>(p));
    57 pPlatformService_{pPlatformService}, 
    68 EMANE::Models::IEEE80211ABG::PCRManager::openDoc(
const std::string & uri,
    69                                               xmlParserCtxtPtr * ppContext,
    70                                               xmlDoc ** ppDocument, xmlNode ** ppRoot)
    72   if((*ppContext = xmlNewParserCtxt()) == NULL)
    74       std::stringstream excString;
    75       excString << 
"IEEE80211ABG::PCRManager::openDoc: Failed to allocate parser context" << std::ends;
    80   else if((*ppDocument = xmlCtxtReadFile(*ppContext, uri.c_str(), NULL, XML_PARSE_DTDVALID)) == NULL)
    82       std::stringstream excString;
    83       excString << 
"IEEE80211ABG::PCRManager::openDoc: Failed to parse document " << uri << std::ends;
    88   else if((*ppContext)->valid == 
false)
    90       std::stringstream excString;
    91       excString << 
"IEEE80211ABG::PCRManager::openDoc: Document in " << uri << 
" is not valid" << std::ends;
    96   else if((*ppRoot = xmlDocGetRootElement(*ppDocument)) == NULL)
    98       std::stringstream excString;
    99       excString << 
"IEEE80211ABG::PCRManager::openDoc: Could not get root element" << std::ends;
   107 EMANE::Models::IEEE80211ABG::PCRManager::closeDoc(xmlParserCtxtPtr * ppContext, xmlDoc ** ppDocument)
   111       xmlFreeParserCtxt(*ppContext);
   117       xmlFreeDoc(*ppDocument);
   131   xmlParserCtxtPtr pContext{};
   135       std::stringstream excString;
   136       excString << 
"IEEE80211ABG::PCRManager::load: must supply curve file name" << std::ends;
   142   openDoc(uri, &pContext, &doc, &root);
   145   xmlNodePtr cur {root};
   153       if((!xmlStrcmp(cur->name, toXMLChar(
"pcr"))))
   155           getTable(cur->xmlChildrenNode, pcrPorMap_);
   162   closeDoc(&pContext, &doc);
   165   for(
auto & iter : pcrPorMap_)
   167       if(iter.second.pcr_.size() < 1)
   169           std::stringstream excString;
   170           excString << 
"IEEE80211ABG::PCRManager::load: need at least 1 point to define a pcr curve " << std::ends;
   182 EMANE::Models::IEEE80211ABG::PCRManager::getTable(xmlNodePtr cur, PCRPORMap & map)
   186       if((!xmlStrcmp(cur->name, toXMLChar(
"table"))))
   192           getDataRate(cur->xmlChildrenNode, map);
   201 EMANE::Models::IEEE80211ABG::PCRManager::getDataRate(xmlNodePtr cur, PCRPORMap & map)
   205       if((!xmlStrcmp(cur->name, toXMLChar(
"datarate"))))
   214           getRows(cur->xmlChildrenNode, entry.pcr_);
   216           if(map.insert(std::make_pair(u16DataRateIndex, entry)).second == 
false)
   218               std::stringstream excString;
   219               excString << 
"IEEE80211ABG::PCRManager::getDataRate: duplicate datarate index value " << u16DataRateIndex << std::ends;
   230 EMANE::Models::IEEE80211ABG::PCRManager::getRows(xmlNodePtr cur, PCREntryVector & vec)
   234       if((!xmlStrcmp(cur->name, toXMLChar(
"row"))))
   243           for(
const auto & iter : vec)
   245               if(fSINR == iter.fSINR_)
   247                   std::stringstream excString;
   248                   excString << 
"IEEE80211ABG::PCRManager::getRows: duplicate sinr value " << fSINR << std::ends;
   251               else if(fSINR < iter.fSINR_)
   253                   std::stringstream excString;
   254                   excString << 
"IEEE80211ABG::PCRManager::getRows: out of order sinr value, must be in increasing value "    255                             << fSINR << std::ends;
   261           vec.push_back(PCREntry(fSINR, fPOR));
   270 EMANE::Models::IEEE80211ABG::PCRManager::interpolate()
   273   for(
auto & iter : pcrPorMap_)
   276       for(
size_t i = 0; i < (iter.second.pcr_.size() - 1); ++i)
   279           const int x1{
static_cast<int>(iter.second.pcr_[i].fSINR_ * PRECISION_FACTOR)};
   282           const float y1{iter.second.pcr_[i].fPOR_};
   285           const int x2{
static_cast<int>(iter.second.pcr_[i + 1].fSINR_ * PRECISION_FACTOR)};
   288           const float y2{iter.second.pcr_[i + 1].fPOR_};
   291           const float slope{(y2 - y1) / (x2 - x1)};
   294           for(
int dx = x1; dx < x2; ++dx)
   297               const float por{(dx - x1) * slope + y1};
   300               iter.second.por_.push_back(por);
   304       iter.second.por_.push_back(iter.second.pcr_[iter.second.pcr_.size() - 1].fPOR_);
   314   const auto iter = pcrPorMap_.find(u16DataRateIndex);
   316   if(iter != pcrPorMap_.end())
   319       if(fSINR < iter->second.pcr_.front().fSINR_)
   323                                  "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, "   324                                  "is below the low limit sinr of %3.2f",
   329                                  iter->second.pcr_.front().fSINR_);
   335       else if(fSINR > iter->second.pcr_.back().fSINR_)
   339                                  "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, "   340                                  "is above the high limit sinr of %3.2f",
   345                                  iter->second.pcr_.back().fSINR_);
   355           if(fSINR == iter->second.pcr_.front().fSINR_ && fSINR == iter->second.pcr_.back().fSINR_)
   358               fPOR = iter->second.pcr_.front().fPOR_;
   363               const int sinrScaled{
static_cast<int>(fSINR * PRECISION_FACTOR)};
   366               const int sinrOffset{
static_cast<int>(iter->second.pcr_.front().fSINR_ * PRECISION_FACTOR)};
   369               int idx{sinrScaled - sinrOffset};
   372               if(idx >= static_cast<int>(iter->second.por_.size()))
   374                   idx = iter->second.por_.size() - 1;
   378               fPOR = iter->second.por_[idx];
   382                                      "MACI %03hu PCRManager::%s: lookup por %3.2f at table index %d",
   390           if(tablePacketSize_ > 0)
   392              fPOR = powf(fPOR, static_cast<float>(packetLen) / tablePacketSize_);
   397                                  "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, por %3.2f",
   412                              "MACI %03hu PCRManager::%s: unsupported datarate index %hu, por %3.2f",
   426 std::string EMANE::Models::IEEE80211ABG::PCRManager::getAttribute(xmlNodePtr cur, 
const xmlChar * 
id)
   428   std::string str{
"0"};
   432       xmlChar * attr {xmlGetProp(cur, 
id)};
   436           str = 
reinterpret_cast<const char *
>(attr);
   447 std::string EMANE::Models::IEEE80211ABG::PCRManager::getContent(xmlNodePtr cur)
   449   std::string str{
"0"};
   451   xmlChar * attr{xmlNodeGetContent(cur)};
   455       str = 
reinterpret_cast<const char *
>(attr);
 #define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
 
ConfigurationException is thrown when an exception occurs during configuration processing. 
 
std::uint16_t toUINT16(std::uint16_t u16Min=std::numeric_limits< std::uint16_t >::min(), std::uint16_t u16Max=std::numeric_limits< std::uint16_t >::max()) const
 
float toFloat(float fMin=std::numeric_limits< float >::lowest(), float fMax=std::numeric_limits< float >::max()) const
 
std::uint32_t toUINT32(std::uint32_t u32Min=std::numeric_limits< std::uint32_t >::min(), std::uint32_t u32Max=std::numeric_limits< std::uint32_t >::max()) const
 
void load(const std::string &uri)
 
PCRManager(NEMId id, PlatformServiceProvider *pPlatformService)
 
float getPCR(float fSinr, size_t size, std::uint16_t DataRateIndex)
 
Parameter conversion class with range checks.