EMANE  1.2.1
macconfig.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014,2016-2017 - Adjacent Link LLC, Bridgewater,
3  * New Jersey
4  * Copyright (c) 2008 - DRS CenGen, LLC, Columbia, Maryland
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * * Neither the name of DRS CenGen, LLC nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 
36 #include "macconfig.h"
37 #include "utils.h"
38 
40 
41 #include <vector>
42 
43 namespace
44 {
45  // valid data rate index [1, 12], the leading 0 is only used to align the index
46  // unicast
47  const std::vector<std::uint32_t> UnicastDataRateIndexTable
48  { 0, 1000, 2000, 5500, 11000, 6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000 };
49 
50  // multicast/broadcast
51  const std::vector<std::uint32_t> BroadcastDataRateIndexTable
52  { 0, 1000, 2000, 5500, 11000, 6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000 };
53 
54  const char * pzLayerName {"MACConfig"};
55 }
56 
63 { }
64 
65 
72  logServiceProvider_(logServiceProvider),
73  id_{id}
74 { }
75 
76 
83 { }
84 
85 
87 {
88 
89  configRegistrar.registerNumeric<bool>("enablepromiscuousmode",
92  {false},
93  "Defines whether promiscuous mode is enabled or not. If promiscuous"
94  " mode is enabled, all received packets (intended for the given"
95  " node or not) that pass the probability of reception check are"
96  " sent upstream to the transport.");
97 
98  configRegistrar.registerNumeric<bool>("wmmenable",
100  {false},
101  "Defines if wireless multimedia mode (WMM) is enabled.");
102 
103  configRegistrar.registerNumeric<std::uint8_t>("mode",
105  {0},
106  "Defines the 802.11abg mode of operation. 0|2 = 802.11b"
107  " (DSS), 1 = 802.11a/g (OFDM), and 3 = 802.11b/g"
108  " (mixed mode).",
111 
112  configRegistrar.registerNumeric<std::uint8_t>("unicastrate",
113  ConfigurationProperties::DEFAULT |
115  {4},
116  "Defines the data rate to be used when transmitting unicast"
117  " packets. The index (1 through 12) to rate (Mbps) mapping is as"
118  " follows: [1 2 5.5 11 6 9 12 18 24 36 48 54]. DSS rates [1 2"
119  " 5.5 11] Mbps are valid when mode is set to 802.11b or 802.11b/g."
120  " OFDM rates [6 9 12 18 24 36 48 54] Mbps are valid when mode is"
121  " set to 802.11a/g or 802.11b/g.",
122  1,
123  12);
124 
125  configRegistrar.registerNumeric<std::uint8_t>("multicastrate",
126  ConfigurationProperties::DEFAULT |
128  {1},
129  "Defines the data rate to be used when transmitting"
130  " broadcast/multicast packets. The index (1 through 12) to rate"
131  " (Mbps) mapping is as follows: [1 2 5.5 11 6 9 12 18 24 36 48"
132  " 54]. DSS rates [1 2 5.5 11] Mbps are valid when mode is set to"
133  " 802.11b or 802.11b/g. OFDM rates [6 9 12 18 24 36 48 54] Mbps"
134  " are valid when mode is set to 802.11a/g or 802.11b/g.",
135  1,
136  12);
137 
138  configRegistrar.registerNumeric<std::uint16_t>("rtsthreshold",
140  {255},
141  "Defines a threshold in bytes for when RTS/CTS is used as part of"
142  " the carrier sensing channel access protocol when transmitting"
143  " unicast packets.",
144  0,
145  0xffff);
146 
147  configRegistrar.registerNumeric<bool>("flowcontrolenable",
149  {false},
150  "Defines whether flow control is enabled. Flow control only"
151  " works with the virtual transport and the setting must"
152  " match the setting within the virtual transport"
153  " configuration.");
154 
155  configRegistrar.registerNumeric<std::uint16_t>("flowcontroltokens",
157  {10},
158  "Defines the maximum number of flow control tokens"
159  " (packet transmission units) that can be processed"
160  " from the virtual transport without being refreshed."
161  " The number of available tokens at any given time is"
162  " coordinated with the virtual transport and when the"
163  " token count reaches zero, no further packets are"
164  " transmitted causing application socket queues to backup.",
165  1);
166 
167  configRegistrar.registerNumeric<std::uint32_t>("distance",
169  {1000},
170  "Defines the max propagation distance in meters used"
171  " to compute slot size.");
172 
173  configRegistrar.registerNonNumeric<std::string>("pcrcurveuri",
175  {},
176  "Defines the URI of the Packet Completion Rate (PCR)"
177  " curve file. The PCR curve file contains probability of"
178  " reception curves as a function of Signal to Interference"
179  " plus Noise Ratio (SINR) for each data rate.");
180 
181  configRegistrar.registerNumeric<std::uint8_t>("queuesize0",
184  "Defines the queue size for category 0.");
185 
186  configRegistrar.registerNumeric<std::uint8_t>("queuesize1",
189  "Defines the queue size for category 1.");
190 
191  configRegistrar.registerNumeric<std::uint8_t>("queuesize2",
194  "Defines the queue size for category 2.");
195 
196  configRegistrar.registerNumeric<std::uint8_t>("queuesize3",
199  "Defines the queue size for category 3.");
200 
201  configRegistrar.registerNumeric<std::uint16_t>("msdu0",
203  {MAX_PACKET_SIZE},
204  "MSDU category 0");
205 
206  configRegistrar.registerNumeric<std::uint16_t>("msdu1",
208  {MAX_PACKET_SIZE},
209  "MSDU category 1");
210 
211  configRegistrar.registerNumeric<std::uint16_t>("msdu2",
213  {MAX_PACKET_SIZE},
214  "MSDU category 2");
215 
216  configRegistrar.registerNumeric<std::uint16_t>("msdu3",
218  {MAX_PACKET_SIZE},
219  "MSDU category 3");
220 
221  configRegistrar.registerNumeric<std::uint16_t>("cwmin0",
222  ConfigurationProperties::DEFAULT |
224  {32},
225  "Defines the minimum contention window size in slots"
226  " for category 0.",
227  1,
228  0xffff);
229 
230  configRegistrar.registerNumeric<std::uint16_t>("cwmin1",
231  ConfigurationProperties::DEFAULT |
233  {32},
234  "Defines the minimum contention window size in slots"
235  " for category 1.",
236  1,
237  0xffff);
238 
239  configRegistrar.registerNumeric<std::uint16_t>("cwmin2",
240  ConfigurationProperties::DEFAULT |
242  {16},
243  "Defines the minimum contention window size in slots"
244  " for category 2.",
245  1,
246  0xffff);
247 
248  configRegistrar.registerNumeric<std::uint16_t>("cwmin3",
249  ConfigurationProperties::DEFAULT |
251  {8},
252  "Defines the minimum contention window size in slots"
253  " for category 3.",
254  1,
255  0xffff);
256 
257  configRegistrar.registerNumeric<std::uint16_t>("cwmax0",
258  ConfigurationProperties::DEFAULT |
260  {1024},
261  "Defines the maximum contention window size in slots"
262  " for category 0.",
263  1,
264  0xffff);
265 
266  configRegistrar.registerNumeric<std::uint16_t>("cwmax1",
267  ConfigurationProperties::DEFAULT |
269  {1024},
270  "Defines the maximum contention window size in slots"
271  " for category 1.",
272  1,
273  0xffff);
274 
275  configRegistrar.registerNumeric<std::uint16_t>("cwmax2",
276  ConfigurationProperties::DEFAULT |
278  {64},
279  "Defines the maximum contention window size in slots"
280  " for category 2.",
281  1,
282  0xffff);
283 
284  configRegistrar.registerNumeric<std::uint16_t>("cwmax3",
285  ConfigurationProperties::DEFAULT |
287  {16},
288  "Defines the maximum contention window size in slots"
289  " for category 3.",
290  1,
291  0xffff);
292 
293  configRegistrar.registerNumeric<float>("aifs0",
295  {0.000002f},
296  "Defines the arbitration inter frame spacing time for category 0"
297  " and contributes to the calculation of channel access overhead"
298  " when transmitting category 0 packets. If WMM is disabled,"
299  " aifs0 is used for all traffic.",
300  0.0f,
301  0.000255f);
302 
303 
304  configRegistrar.registerNumeric<float>("aifs1",
306  {0.000002f},
307  "Defines the arbitration inter frame spacing time for category 1"
308  " and contributes to the calculation of channel access overhead"
309  " when transmitting category 1 packets.",
310  0.0f,
311  0.000255);
312 
313 
314  configRegistrar.registerNumeric<float>("aifs2",
316  {0.000002f},
317  "Defines the arbitration inter frame spacing time for category 2"
318  " and contributes to the calculation of channel access overhead"
319  " when transmitting category 2 packets.",
320  0.0f,
321  0.000255f);
322 
323 
324  configRegistrar.registerNumeric<float>("aifs3",
326  {0.000001f},
327  "Defines the arbitration inter frame spacing time for category 3"
328  " and contributes to the calculation of channel access overhead"
329  " when transmitting category 3 packets.",
330  0.0f,
331  0.000255f);
332 
333  configRegistrar.registerNumeric<float>("txop0",
335  {0.0f},
336  "Defines the transmit opportunity time for category 0.",
337  0.0f,
338  1.0f);
339 
340  configRegistrar.registerNumeric<float>("txop1",
342  {0.0f},
343  "Defines the transmit opportunity time for category 1.",
344  0.0f,
345  1.0f);
346 
347  configRegistrar.registerNumeric<float>("txop2",
349  {0.0f},
350  "Defines the transmit opportunity time for category 2.",
351  0.0f,
352  1.0f);
353 
354  configRegistrar.registerNumeric<float>("txop3",
356  {0.0f},
357  "Defines the transmit opportunity time for category 3.",
358  0.0f,
359  1.0f);
360 
361  configRegistrar.registerNumeric<std::uint8_t>("retrylimit0",
363  {2},
364  "Defines the maximum number of retries attempted for"
365  " category 0.");
366 
367  configRegistrar.registerNumeric<std::uint8_t>("retrylimit1",
369  {2},
370  "Defines the maximum number of retries attempted for"
371  " category 1.");
372 
373  configRegistrar.registerNumeric<std::uint8_t>("retrylimit2",
375  {2},
376  "Defines the maximum number of retries attempted for"
377  " category 2.");
378 
379  configRegistrar.registerNumeric<std::uint8_t>("retrylimit3",
381  {2},
382  "Defines the maximum number of retries attempted for"
383  " category 3.");
384 
385  configRegistrar.registerNumeric<float>("channelactivityestimationtimer",
387  {0.1f},
388  "Defines the channel activity estimation timer in seconds. The"
389  " timer determines the lag associated with the statistical"
390  " model used to estimate number of transmitting common and"
391  " hidden neighbors based on channel activity.",
392  0.001f,
393  1.0f);
394 
395 
396  configRegistrar.registerNumeric<float>("neighbortimeout",
398  {30.0f},
399  "Defines the neighbor timeout in seconds for the neighbor"
400  " estimation algorithm.",
401  0.0f,
402  3600.0f);
403 
404  configRegistrar.registerNumeric<bool>("radiometricenable",
406  {false},
407  "Defines if radio metrics will be reported up via the Radio to"
408  " Router Interface (R2RI).");
409 
410 
411 
412  configRegistrar.registerNumeric<float>("radiometricreportinterval",
414  {1.0f},
415  "Defines the metric report interval in seconds in support of"
416  " the R2RI feature.",
417  0.1f,
418  60.0f);
419 
420  configRegistrar.registerNumeric<float>("neighbormetricdeletetime",
422  {60.0f},
423  "Defines the time in seconds of no RF receptions from a given"
424  " neighbor before it is removed from the neighbor table.",
425  1.0f,
426  3660.0f);
427 }
428 
429 
438 bool
440 {
441  return configItems_.bPromiscousModeEnable_;
442 }
443 
444 
445 
453 bool
455 {
456  return configItems_.bWmmEnable_;
457 }
458 
459 
469 {
470  switch(configItems_.u8ModeIndex_)
471  {
472  case 3: // 80211BG
474 
475  case 2: // 80211B
476  return MODULATION_TYPE_80211B;
477 
478  case 1: // 80211A
479  return MODULATION_TYPE_80211A;
480 
481  default: // 80211B
482  return MODULATION_TYPE_80211B;
483  }
484 }
485 
486 
494 std::uint8_t
496 {
497  return configItems_.u8UnicastDataRateIndex_;
498 }
499 
500 
508 std::uint8_t
510 {
511  return configItems_.u8BroadcastDataRateIndex_;
512 }
513 
514 
522 std::uint32_t
524 {
525  return UnicastDataRateIndexTable[configItems_.u8UnicastDataRateIndex_];
526 }
527 
528 
529 std::uint32_t
531 {
532  return UnicastDataRateIndexTable[configItems_.u8UnicastDataRateIndex_] >
533  BroadcastDataRateIndexTable[configItems_.u8BroadcastDataRateIndex_] ?
534  UnicastDataRateIndexTable[configItems_.u8UnicastDataRateIndex_] :
535  BroadcastDataRateIndexTable[configItems_.u8BroadcastDataRateIndex_];
536 }
537 
538 
539 
547 std::uint32_t
549 {
550  return BroadcastDataRateIndexTable[configItems_.u8BroadcastDataRateIndex_];
551 }
552 
560 std::uint32_t
562 {
563  return UnicastDataRateIndexTable[u8Index];
564 }
565 
566 
574 std::uint32_t
576 {
577  return BroadcastDataRateIndexTable[u8Index];
578 }
579 
580 
581 
582 
590 std::uint32_t
592 {
593  return configItems_.u32MaxP2PDistance_;
594 }
595 
596 
604 std::uint8_t
606 {
607  return configItems_.bWmmEnable_ == true ? MAX_ACCESS_CATEGORIES : 1;
608 }
609 
610 
620 std::uint8_t
622 {
623  switch(u8Category)
624  {
625  case 3:
626  return configItems_.u8QueueSize3_;
627 
628  case 2:
629  return configItems_.u8QueueSize2_;
630 
631  case 1:
632  return configItems_.u8QueueSize1_;
633 
634  default:
635  return configItems_.u8QueueSize0_;
636  }
637 }
638 
639 
649 std::uint16_t
651 {
652  switch(u8Category)
653  {
654  case 3:
655  return configItems_.u16MSDU3_;
656 
657  case 2:
658  return configItems_.u16MSDU2_;
659 
660  case 1:
661  return configItems_.u16MSDU1_;
662 
663  default:
664  return configItems_.u16MSDU0_;
665  }
666 }
667 
668 
669 
679 std::uint16_t
681 {
682  switch(u8Category)
683  {
684  case 3:
685  return configItems_.u16CWMin3_;
686 
687  case 2:
688  return configItems_.u16CWMin2_;
689 
690  case 1:
691  return configItems_.u16CWMin1_;
692 
693  default:
694  return configItems_.u16CWMin0_;
695  }
696 }
697 
698 
708 std::uint16_t
710 {
711  switch(u8Category)
712  {
713  case 3:
714  return configItems_.u16CWMax3_;
715 
716  case 2:
717  return configItems_.u16CWMax2_;
718 
719  case 1:
720  return configItems_.u16CWMax1_;
721 
722  default:
723  return configItems_.u16CWMax0_;
724  }
725 }
726 
727 
728 void
730 {
731  configItems_.u16CWMin0_ = u16Value;
732 
733  setCWMinRatioVector(0);
734 }
735 
736 
737 void
739 {
740  configItems_.u16CWMin1_ = u16Value;
741 
742  setCWMinRatioVector(1);
743 }
744 
745 
746 void
748 {
749  configItems_.u16CWMin2_ = u16Value;
750 
751  setCWMinRatioVector(2);
752 }
753 
754 
755 void
757 {
758  configItems_.u16CWMin3_ = u16Value;
759 
760  setCWMinRatioVector(3);
761 }
762 
763 
764 
765 
766 void
768 {
769  configItems_.u16CWMax0_ = u16Value;
770 }
771 
772 
773 void
775 {
776  configItems_.u16CWMax1_ = u16Value;
777 }
778 
779 
780 void
782 {
783  configItems_.u16CWMax2_ = u16Value;
784 }
785 
786 
787 void
789 {
790  configItems_.u16CWMax3_ = u16Value;
791 }
792 
793 
794 
795 
807 {
808  switch(u8Category)
809  {
810  case 3:
811  return configItems_.aifsMicroseconds3_;
812 
813  case 2:
814  return configItems_.aifsMicroseconds2_;
815 
816  case 1:
817  return configItems_.aifsMicroseconds1_;
818 
819  default:
820  return configItems_.aifsMicroseconds0_;
821  }
822 }
823 
824 
825 
837 {
838  switch(u8Category)
839  {
840  case 3:
841  return configItems_.txopMicroseconds3_;
842 
843  case 2:
844  return configItems_.txopMicroseconds2_;
845 
846  case 1:
847  return configItems_.txopMicroseconds1_;
848 
849  default:
850  return configItems_.txopMicroseconds0_;
851  }
852 }
853 
854 
864 std::uint8_t
866 {
867  switch(u8Category)
868  {
869  case 3:
870  return configItems_.u8RetryLimit3_;
871 
872  case 2:
873  return configItems_.u8RetryLimit2_;
874 
875  case 1:
876  return configItems_.u8RetryLimit1_;
877 
878  default:
879  return configItems_.u8RetryLimit0_;
880  }
881 }
882 
883 
884 
885 
893 bool
895 {
896  return configItems_.bFlowControlEnable_;
897 }
898 
899 
900 
908 std::uint16_t
910 {
911  return configItems_.u16FlowControlTokens_;
912 }
913 
914 
922 std::string
924 {
925  return configItems_.sPcrUri_;
926 }
927 
928 
929 
932 {
933  return configItems_.neighborTimeoutMicroseconds_;
934 }
935 
936 
937 
940 {
941  return configItems_.channelActivityIntervalMicroseconds_;
942 }
943 
944 
945 std::uint16_t
947 {
948  return configItems_.u16RtsThreshold_;
949 }
950 
951 
954 {
955  return configItems_.CWMinRatioTable_[u8Category];
956 }
957 
958 
961 {
962  return configItems_.neighborMetricDeleteTimeMicroseconds_;
963 }
964 
965 
968 {
969  return configItems_.radioMetricReportIntervalMicroseconds_;
970 }
971 
972 
973 bool
975 {
976  return configItems_.bRadioMetricEnable_;
977 }
978 
979 
980 void
981 EMANE::Models::IEEE80211ABG::MACConfig::setCWMinRatioVector(std::uint8_t u8Category)
982 {
983  const std::uint16_t cw{getCWMin(u8Category)};
984 
985  for(std::uint8_t u8Index = 0; u8Index < getNumAccessCategories(); ++u8Index)
986  {
987  const float fRatio{static_cast<float>(cw) / getCWMin(u8Index)};
988 
989  configItems_.CWMinRatioTable_[u8Category][u8Index] = fRatio > 1.0f ? 1.0f : fRatio;
990  }
991 }
992 
993 
994 void
995 EMANE::Models::IEEE80211ABG::MACConfig::initCWMinRatioTable()
996 {
997  configItems_.CWMinRatioTable_.resize(getNumAccessCategories());
998 
999  for(std::uint8_t u8Category = 0; u8Category < getNumAccessCategories(); ++u8Category)
1000  {
1001  configItems_.CWMinRatioTable_[u8Category].resize(getNumAccessCategories());
1002 
1003  setCWMinRatioVector(u8Category);
1004  }
1005 }
1006 
1007 bool
1009 {
1010  for(const auto & item : update)
1011  {
1012  if(!configureStaticItems(item) && !configureDynamicItems(item))
1013  {
1014  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1015  DEBUG_LEVEL,
1016  "MACI %03hu %s::%s invalid config item %s",
1017  id_,
1018  pzLayerName,
1019  __func__,
1020  item.first.c_str());
1021 
1022  return false;
1023  }
1024  }
1025 
1026  initCWMinRatioTable();
1027 
1028  return true;
1029 }
1030 
1031 
1032 bool
1034 {
1035  for(const auto & item : update)
1036  {
1037  if(!configureDynamicItems(item))
1038  {
1039  return false;
1040  }
1041  }
1042 
1043  initCWMinRatioTable();
1044 
1045  return true;
1046 }
1047 
1048 
1049 bool
1050 EMANE::Models::IEEE80211ABG::MACConfig::configureStaticItems(const ConfigurationNameAnyValues & item)
1051 {
1052  if(item.first == "mode")
1053  {
1054  configItems_.u8ModeIndex_ = item.second[0].asUINT8();
1055 
1056  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1057  INFO_LEVEL,
1058  "MACI %03hu %s::%s %s = %hhu",
1059  id_,
1060  pzLayerName,
1061  __func__,
1062  item.first.c_str(),
1063  configItems_.u8ModeIndex_);
1064  }
1065  else if(item.first == "distance")
1066  {
1067  configItems_.u32MaxP2PDistance_ = item.second[0].asUINT32();
1068 
1069  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1070  INFO_LEVEL,
1071  "MACI %03hu %s::%s %s = %u",
1072  id_,
1073  pzLayerName,
1074  __func__,
1075  item.first.c_str(),
1076  configItems_.u32MaxP2PDistance_);
1077  }
1078  else if(item.first == "rtsthreshold")
1079  {
1080  configItems_.u16RtsThreshold_ = item.second[0].asUINT16();
1081 
1082  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1083  INFO_LEVEL,
1084  "MACI %03hu %s::%s %s = %hu",
1085  id_,
1086  pzLayerName,
1087  __func__,
1088  item.first.c_str(),
1089  configItems_.u16RtsThreshold_);
1090  }
1091  else if(item.first == "wmmenable")
1092  {
1093  configItems_.bWmmEnable_ = item.second[0].asBool();
1094 
1095  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1096  INFO_LEVEL,
1097  "MACI %03hu %s::%s %s = %s",
1098  id_,
1099  pzLayerName,
1100  __func__,
1101  item.first.c_str(),
1102  configItems_.bWmmEnable_ ? "on" : "off");
1103  }
1104  else if(item.first == "queuesize0")
1105  {
1106  configItems_.u8QueueSize0_ = item.second[0].asUINT8();
1107 
1108  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1109  INFO_LEVEL,
1110  "MACI %03hu %s::%s %s = %hhu",
1111  id_,
1112  pzLayerName,
1113  __func__,
1114  item.first.c_str(),
1115  configItems_.u8QueueSize0_);
1116  }
1117  else if(item.first == "queuesize1")
1118  {
1119  configItems_.u8QueueSize1_ = item.second[0].asUINT8();
1120 
1121  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1122  INFO_LEVEL,
1123  "MACI %03hu %s::%s %s = %hhu",
1124  id_,
1125  pzLayerName,
1126  __func__,
1127  item.first.c_str(),
1128  configItems_.u8QueueSize1_);
1129  }
1130  else if(item.first == "queuesize2")
1131  {
1132  configItems_.u8QueueSize2_ = item.second[0].asUINT8();
1133 
1134  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1135  INFO_LEVEL,
1136  "MACI %03hu %s::%s %s = %hhu",
1137  id_,
1138  pzLayerName,
1139  __func__,
1140  item.first.c_str(),
1141  configItems_.u8QueueSize2_);
1142  }
1143  else if(item.first == "queuesize3")
1144  {
1145  configItems_.u8QueueSize3_ = item.second[0].asUINT8();
1146 
1147  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1148  INFO_LEVEL,
1149  "MACI %03hu %s::%s %s = %hhu",
1150  id_,
1151  pzLayerName,
1152  __func__,
1153  item.first.c_str(),
1154  configItems_.u8QueueSize3_);
1155  }
1156  else if(item.first == "aifs0")
1157  {
1158  configItems_.aifsMicroseconds0_ =
1159  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1160 
1161  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1162  INFO_LEVEL,
1163  "MACI %03hu %s::%s %s = %ju",
1164  id_,
1165  pzLayerName,
1166  __func__,
1167  item.first.c_str(),
1168  configItems_.aifsMicroseconds0_.count());
1169  }
1170  else if(item.first == "aifs1")
1171  {
1172  configItems_.aifsMicroseconds1_ =
1173  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1174 
1175  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1176  INFO_LEVEL,
1177  "MACI %03hu %s::%s %s = %ju",
1178  id_,
1179  pzLayerName,
1180  __func__,
1181  item.first.c_str(),
1182  configItems_.aifsMicroseconds1_.count());
1183  }
1184  else if(item.first == "aifs2")
1185  {
1186  configItems_.aifsMicroseconds2_ =
1187  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1188 
1189  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1190  INFO_LEVEL,
1191  "MACI %03hu %s::%s %s = %ju",
1192  id_,
1193  pzLayerName,
1194  __func__,
1195  item.first.c_str(),
1196  configItems_.aifsMicroseconds2_.count());
1197  }
1198  else if(item.first == "aifs3")
1199  {
1200  configItems_.aifsMicroseconds3_ =
1201  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1202 
1203  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1204  INFO_LEVEL,
1205  "MACI %03hu %s::%s %s = %ju",
1206  id_,
1207  pzLayerName,
1208  __func__,
1209  item.first.c_str(),
1210  configItems_.aifsMicroseconds3_.count());
1211  }
1212  else if(item.first == "msdu0")
1213  {
1214  configItems_.u16MSDU0_ = item.second[0].asUINT16();
1215 
1216  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1217  INFO_LEVEL,
1218  "MACI %03hu %s::%s %s = %hu",
1219  id_,
1220  pzLayerName,
1221  __func__,
1222  item.first.c_str(),
1223  configItems_.u16MSDU0_);
1224  }
1225  else if(item.first == "msdu1")
1226  {
1227  configItems_.u16MSDU1_ = item.second[0].asUINT16();
1228 
1229  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1230  INFO_LEVEL,
1231  "MACI %03hu %s::%s %s = %hu",
1232  id_,
1233  pzLayerName,
1234  __func__,
1235  item.first.c_str(),
1236  configItems_.u16MSDU1_);
1237  }
1238  else if(item.first == "msdu2")
1239  {
1240  configItems_.u16MSDU2_ = item.second[0].asUINT16();
1241 
1242  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1243  INFO_LEVEL,
1244  "MACI %03hu %s::%s %s = %hu",
1245  id_,
1246  pzLayerName,
1247  __func__,
1248  item.first.c_str(),
1249  configItems_.u16MSDU2_);
1250  }
1251  else if(item.first == "msdu3")
1252  {
1253  configItems_.u16MSDU3_ = item.second[0].asUINT16();
1254 
1255  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1256  INFO_LEVEL,
1257  "MACI %03hu %s::%s %s = %hu",
1258  id_,
1259  pzLayerName,
1260  __func__,
1261  item.first.c_str(),
1262  configItems_.u16MSDU3_);
1263  }
1264  else if(item.first == "txop0")
1265  {
1266  configItems_.txopMicroseconds0_ =
1267  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1268 
1269  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1270  INFO_LEVEL,
1271  "MACI %03hu %s::%s %s = %ju",
1272  id_,
1273  pzLayerName,
1274  __func__,
1275  item.first.c_str(),
1276  configItems_.txopMicroseconds0_.count());
1277  }
1278  else if(item.first == "txop1")
1279  {
1280  configItems_.txopMicroseconds1_ =
1281  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1282 
1283  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1284  INFO_LEVEL,
1285  "MACI %03hu %s::%s %s = %ju",
1286  id_,
1287  pzLayerName,
1288  __func__,
1289  item.first.c_str(),
1290  configItems_.txopMicroseconds1_.count());
1291  }
1292  else if(item.first == "txop2")
1293  {
1294  configItems_.txopMicroseconds2_ =
1295  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1296 
1297  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1298  INFO_LEVEL,
1299  "MACI %03hu %s::%s %s = %ju",
1300  id_,
1301  pzLayerName,
1302  __func__,
1303  item.first.c_str(),
1304  configItems_.txopMicroseconds2_.count());
1305  }
1306  else if(item.first == "txop3")
1307  {
1308  configItems_.txopMicroseconds3_ =
1309  std::chrono::duration_cast<Microseconds>(DoubleSeconds{(item.second[0].asFloat())});
1310 
1311  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1312  INFO_LEVEL,
1313  "MACI %03hu %s::%s %s = %ju",
1314  id_,
1315  pzLayerName,
1316  __func__,
1317  item.first.c_str(),
1318  configItems_.txopMicroseconds3_.count());
1319  }
1320 
1321  else if(item.first == "retrylimit0")
1322  {
1323  configItems_.u8RetryLimit0_ = item.second[0].asUINT8();
1324 
1325  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1326  INFO_LEVEL,
1327  "MACI %03hu %s::%s %s = %hhu",
1328  id_,
1329  pzLayerName,
1330  __func__,
1331  item.first.c_str(),
1332  configItems_.u8RetryLimit0_);
1333  }
1334  else if(item.first == "retrylimit1")
1335  {
1336  configItems_.u8RetryLimit1_ = item.second[0].asUINT8();
1337 
1338  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1339  INFO_LEVEL,
1340  "MACI %03hu %s::%s %s = %hhu",
1341  id_,
1342  pzLayerName,
1343  __func__,
1344  item.first.c_str(),
1345  configItems_.u8RetryLimit1_);
1346  }
1347  else if(item.first == "retrylimit2")
1348  {
1349  configItems_.u8RetryLimit2_ = item.second[0].asUINT8();
1350 
1351  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1352  INFO_LEVEL,
1353  "MACI %03hu %s::%s %s = %hhu",
1354  id_,
1355  pzLayerName,
1356  __func__,
1357  item.first.c_str(),
1358  configItems_.u8RetryLimit2_);
1359  }
1360  else if(item.first == "retrylimit3")
1361  {
1362  configItems_.u8RetryLimit3_ = item.second[0].asUINT8();
1363 
1364  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1365  INFO_LEVEL,
1366  "MACI %03hu %s::%s %s = %hhu",
1367  id_,
1368  pzLayerName,
1369  __func__,
1370  item.first.c_str(),
1371  configItems_.u8RetryLimit3_);
1372  }
1373  else if(item.first == "flowcontrolenable")
1374  {
1375  configItems_.bFlowControlEnable_ = item.second[0].asBool();
1376 
1377  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1378  INFO_LEVEL,
1379  "MACI %03hu %s::%s %s = %s",
1380  id_,
1381  pzLayerName,
1382  __func__,
1383  item.first.c_str(),
1384  configItems_.bFlowControlEnable_ ? "on" : "off");
1385  }
1386  else if(item.first == "flowcontroltokens")
1387  {
1388  configItems_.u16FlowControlTokens_ = item.second[0].asUINT16();
1389 
1390  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1391  INFO_LEVEL,
1392  "MACI %03hu %s::%s %s = %hhu",
1393  id_,
1394  pzLayerName,
1395  __func__,
1396  item.first.c_str(),
1397  configItems_.u16FlowControlTokens_);
1398  }
1399  else if(item.first == "pcrcurveuri")
1400  {
1401  configItems_.sPcrUri_ = item.second[0].asString();
1402 
1403  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1404  INFO_LEVEL,
1405  "MACI %03hu %s::%s %s = %s",
1406  id_,
1407  pzLayerName,
1408  __func__,
1409  item.first.c_str(),
1410  configItems_.sPcrUri_.c_str());
1411  }
1412  else if(item.first == "neighbortimeout")
1413  {
1414  float fValue{item.second[0].asFloat()};
1415 
1416  configItems_.neighborTimeoutMicroseconds_ =
1417  std::chrono::duration_cast<Microseconds>(DoubleSeconds{fValue});
1418 
1419  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1420  INFO_LEVEL,
1421  "MACI %03hu %s::%s %s = %f sec",
1422  id_,
1423  pzLayerName,
1424  __func__,
1425  item.first.c_str(),
1426  fValue);
1427  }
1428  else if(item.first == "channelactivityestimationtimer")
1429  {
1430  float fValue{item.second[0].asFloat()};
1431 
1433  std::chrono::duration_cast<Microseconds>(DoubleSeconds{fValue});
1434 
1435  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1436  INFO_LEVEL,
1437  "MACI %03hu %s::%s %s = %f sec",
1438  id_,
1439  pzLayerName,
1440  __func__,
1441  item.first.c_str(),
1442  fValue);
1443  }
1444  else if(item.first == "radiometricenable")
1445  {
1446  configItems_.bRadioMetricEnable_ = item.second[0].asBool();
1447 
1448  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1449  INFO_LEVEL,
1450  "MACI %03hu %s::%s %s = %s",
1451  id_,
1452  pzLayerName,
1453  __func__,
1454  item.first.c_str(),
1455  configItems_.bRadioMetricEnable_ ? "on" : "off");
1456  }
1457  else if(item.first == "radiometricreportinterval")
1458  {
1459  float fValue{item.second[0].asFloat()};
1460 
1462  std::chrono::duration_cast<Microseconds>(DoubleSeconds{fValue});
1463 
1464  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1465  INFO_LEVEL,
1466  "MACI %03hu %s::%s %s = %f sec",
1467  id_,
1468  pzLayerName,
1469  __func__,
1470  item.first.c_str(),
1471  fValue);
1472  }
1473  else if(item.first == "neighbormetricdeletetime")
1474  {
1475  float fValue{item.second[0].asFloat()};
1476 
1478  std::chrono::duration_cast<Microseconds>(DoubleSeconds{fValue});
1479 
1480  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1481  INFO_LEVEL,
1482  "MACI %03hu %s::%s %s = %f sec",
1483  id_,
1484  pzLayerName,
1485  __func__,
1486  item.first.c_str(),
1487  fValue);
1488  }
1489  else
1490  {
1491  return false;
1492  }
1493 
1494  return true;
1495 }
1496 
1497 
1498 bool
1499 EMANE::Models::IEEE80211ABG::MACConfig::configureDynamicItems(const ConfigurationNameAnyValues & item)
1500 {
1501  if(item.first == "unicastrate")
1502  {
1503  configItems_.u8UnicastDataRateIndex_ = item.second[0].asUINT8();
1504 
1505  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1506  INFO_LEVEL,
1507  "MACI %03hu %s::%s %s = %hhu",
1508  id_,
1509  pzLayerName,
1510  __func__,
1511  item.first.c_str(),
1512  configItems_.u8UnicastDataRateIndex_);
1513  }
1514  else if(item.first == "multicastrate")
1515  {
1516  configItems_.u8BroadcastDataRateIndex_ = item.second[0].asUINT8();
1517 
1518  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1519  INFO_LEVEL,
1520  "MACI %03hu %s::%s %s = %hhu",
1521  id_,
1522  pzLayerName,
1523  __func__,
1524  item.first.c_str(),
1525  configItems_.u8BroadcastDataRateIndex_);
1526  }
1527  else if(item.first == "cwmin0")
1528  {
1529  configItems_.u16CWMin0_ = item.second[0].asUINT16();
1530 
1531  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1532  INFO_LEVEL,
1533  "MACI %03hu %s::%s %s = %hu",
1534  id_,
1535  pzLayerName,
1536  __func__,
1537  item.first.c_str(),
1538  configItems_.u16CWMin0_);
1539  }
1540  else if(item.first == "cwmin1")
1541  {
1542  configItems_.u16CWMin1_ = item.second[0].asUINT16();
1543 
1544  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1545  INFO_LEVEL,
1546  "MACI %03hu %s::%s %s = %hu",
1547  id_,
1548  pzLayerName,
1549  __func__,
1550  item.first.c_str(),
1551  configItems_.u16CWMin1_);
1552  }
1553  else if(item.first == "cwmin2")
1554  {
1555  configItems_.u16CWMin2_ = item.second[0].asUINT16();
1556 
1557  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1558  INFO_LEVEL,
1559  "MACI %03hu %s::%s %s = %hu",
1560  id_,
1561  pzLayerName,
1562  __func__,
1563  item.first.c_str(),
1564  configItems_.u16CWMin2_);
1565  }
1566  else if(item.first == "cwmin3")
1567  {
1568  configItems_.u16CWMin3_ = item.second[0].asUINT16();
1569 
1570  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1571  INFO_LEVEL,
1572  "MACI %03hu %s::%s %s = %hu",
1573  id_,
1574  pzLayerName,
1575  __func__,
1576  item.first.c_str(),
1577  configItems_.u16CWMin3_);
1578  }
1579  else if(item.first == "cwmax0")
1580  {
1581  configItems_.u16CWMax0_ = item.second[0].asUINT16();
1582 
1583  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1584  INFO_LEVEL,
1585  "MACI %03hu %s::%s %s = %hu",
1586  id_,
1587  pzLayerName,
1588  __func__,
1589  item.first.c_str(),
1590  configItems_.u16CWMax0_);
1591  }
1592  else if(item.first == "cwmax1")
1593  {
1594  configItems_.u16CWMax1_ = item.second[0].asUINT16();
1595 
1596  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1597  INFO_LEVEL,
1598  "MACI %03hu %s::%s %s = %hu",
1599  id_,
1600  pzLayerName,
1601  __func__,
1602  item.first.c_str(),
1603  configItems_.u16CWMax1_);
1604  }
1605  else if(item.first == "cwmax2")
1606  {
1607  configItems_.u16CWMax2_ = item.second[0].asUINT16();
1608 
1609  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1610  INFO_LEVEL,
1611  "MACI %03hu %s::%s %s = %hu",
1612  id_,
1613  pzLayerName,
1614  __func__,
1615  item.first.c_str(),
1616  configItems_.u16CWMax2_);
1617  }
1618  else if(item.first == "cwmax3")
1619  {
1620  configItems_.u16CWMax3_ = item.second[0].asUINT16();
1621 
1622  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1623  INFO_LEVEL,
1624  "MACI %03hu %s::%s %s = %hu",
1625  id_,
1626  pzLayerName,
1627  __func__,
1628  item.first.c_str(),
1629  configItems_.u16CWMax3_);
1630  }
1631  else if(item.first == "enablepromiscuousmode")
1632  {
1633  configItems_.bPromiscousModeEnable_ = item.second[0].asBool();
1634 
1635  LOGGER_STANDARD_LOGGING(logServiceProvider_,
1636  INFO_LEVEL,
1637  "MACI %03hu %s::%s %s = %s",
1638  id_,
1639  pzLayerName,
1640  __func__,
1641  item.first.c_str(),
1642  configItems_.bPromiscousModeEnable_ ? "on" : "off");
1643  }
1644  else
1645  {
1646  return false;
1647  }
1648 
1649  return true;
1650 }
bool configure(const ConfigurationUpdate &update)
Definition: macconfig.cc:1008
std::uint8_t getQueueSize(std::uint8_t) const
get the queue size for a given queue index
Definition: macconfig.cc:621
std::uint16_t getRtsThreshold() const
Definition: macconfig.cc:946
void setCWMax3(std::uint16_t u16Value)
Definition: macconfig.cc:788
std::uint32_t getBroadcastDataRateKbps() const
get the broadcast datarate
Definition: macconfig.cc:548
Microseconds getNeighborTimeoutMicroseconds() const
Definition: macconfig.cc:931
std::uint8_t getNumAccessCategories() const
get the number of access categories (queues)
Definition: macconfig.cc:605
void setCWMax0(std::uint16_t u16Value)
Definition: macconfig.cc:767
void registerNonNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
std::uint8_t getBroadcastDataRateIndex() const
get the broadcast datarate index
Definition: macconfig.cc:509
Microseconds getAifsMicroseconds(std::uint8_t) const
get the aifs for a given queue index
Definition: macconfig.cc:806
void setCWMin3(std::uint16_t u16Value)
Definition: macconfig.cc:756
Microseconds getTxOpMicroseconds(std::uint8_t) const
get the txop for a given queue index
Definition: macconfig.cc:836
const std::uint8_t MAX_ACCESS_CATEGORIES
Definition: macconfig.h:63
Log service provider interface.
void setCWMin0(std::uint16_t u16Value)
Definition: macconfig.cc:729
std::uint16_t getCWMin(std::uint8_t) const
get the min contention window size for a given queue index
Definition: macconfig.cc:680
void setCWMax2(std::uint16_t u16Value)
Definition: macconfig.cc:781
ConfigItems()
ieee80211abg mac configuration initializer.
Definition: macconfig.cc:62
const std::uint16_t MAX_PACKET_SIZE
Definition: macconfig.h:68
Microseconds getChannelActivityIntervalMicroseconds() const
Definition: macconfig.cc:939
std::uint32_t getUnicastDataRateKbps() const
get the unicast datarate
Definition: macconfig.cc:523
std::uint16_t getFlowControlTokens() const
get the number of flow control tokens
Definition: macconfig.cc:909
std::chrono::microseconds Microseconds
Definition: types.h:45
void setCWMin1(std::uint16_t u16Value)
Definition: macconfig.cc:738
std::chrono::duration< double > DoubleSeconds
Definition: types.h:47
std::string getPcrUri() const
get the pcr uri
Definition: macconfig.cc:923
std::uint16_t NEMId
Definition: types.h:52
const std::uint8_t MODULATION_TYPE_INDEX_MIN
Definition: macconfig.h:71
bool processConfiguration(const ConfigurationUpdate &update)
Definition: macconfig.cc:1033
Microseconds getNeighborMetricDeleteTimeMicroseconds() const
Definition: macconfig.cc:960
const std::uint8_t QUEUE_SIZE_DEFAULT
Definition: macconfig.h:65
MODULATION_TYPE getModulationType() const
get the modulation type
Definition: macconfig.cc:468
std::uint8_t getRetryLimit(std::uint8_t) const
get the retry limit for a given queue index
Definition: macconfig.cc:865
bool getPromiscuosEnable() const
get the promiscuous mode
Definition: macconfig.cc:439
The ConfigurationRegistrar allows NEM layers to register the configuration items they require...
std::vector< ConfigurationNameAnyValues > ConfigurationUpdate
void registerConfiguration(ConfigurationRegistrar &configRegistrar)
Definition: macconfig.cc:86
std::pair< std::string, std::vector< EMANE::Any > > ConfigurationNameAnyValues
Microseconds getRadioMetricReportIntervalMicroseconds() const
Definition: macconfig.cc:967
std::uint8_t getUnicastDataRateIndex() const
get the unicast datarate index
Definition: macconfig.cc:495
bool getWmmEnable() const
get the wmm mode
Definition: macconfig.cc:454
void setCWMax1(std::uint16_t u16Value)
Definition: macconfig.cc:774
void setCWMin2(std::uint16_t u16Value)
Definition: macconfig.cc:747
std::uint32_t getMaxDataRateKbps() const
Definition: macconfig.cc:530
void registerNumeric(const std::string &sName, const ConfigurationProperties &properties=ConfigurationProperties::NONE, const std::initializer_list< T > &values={}, const std::string &sUsage="", T minValue=std::numeric_limits< T >::lowest(), T maxValue=std::numeric_limits< T >::max(), std::size_t minOccurs=1, std::size_t maxOccurs=1, const std::string &sRegexPattern={})
std::vector< float > CWRatioVector
Definition: macconfig.h:75
#define LOGGER_STANDARD_LOGGING(logger, level, fmt, args...)
std::uint16_t getCWMax(std::uint8_t) const
get the max contention window size for a given queue index
Definition: macconfig.cc:709
MACConfig(LogServiceProvider &logServiceProvider, NEMId id)
constructor
Definition: macconfig.cc:71
std::uint16_t getQueueEntrySize(std::uint8_t) const
get the queue entry size for a given queue index
Definition: macconfig.cc:650
CWRatioVector getCWMinRatioVector(std::uint8_t) const
Definition: macconfig.cc:953
std::uint32_t getMaxP2pDistance() const
get the max ptp distance
Definition: macconfig.cc:591
const std::uint8_t MODULATION_TYPE_INDEX_MAX
Definition: macconfig.h:72
bool getFlowControlEnable() const
get the flow control enable status
Definition: macconfig.cc:894