From ddfe9023eba74f02b8a852ccc19a04ce04f2f62d Mon Sep 17 00:00:00 2001 From: Ramon Bauza Date: Tue, 15 Sep 2009 10:47:02 +0200 Subject: [PATCH 1/8] Channel switching support for Wifi --- AUTHORS | 1 + CHANGES.html | 3 + RELEASE_NOTES | 2 + examples/wifi-ap.cc | 3 + src/devices/wifi/dca-txop.cc | 10 ++ src/devices/wifi/dca-txop.h | 1 + src/devices/wifi/dcf-manager-test.cc | 140 +++++++++++++++++++++- src/devices/wifi/dcf-manager.cc | 87 +++++++++++++- src/devices/wifi/dcf-manager.h | 18 +++ src/devices/wifi/edca-txop-n.cc | 10 ++ src/devices/wifi/edca-txop-n.h | 1 + src/devices/wifi/interference-helper.cc | 6 +- src/devices/wifi/interference-helper.h | 1 + src/devices/wifi/mac-low.cc | 51 ++++++++ src/devices/wifi/mac-low.h | 12 ++ src/devices/wifi/wifi-phy-state-helper.cc | 76 ++++++++++++ src/devices/wifi/wifi-phy-state-helper.h | 5 + src/devices/wifi/wifi-phy.h | 14 ++- src/devices/wifi/yans-wifi-phy.cc | 71 +++++++++-- src/devices/wifi/yans-wifi-phy.h | 4 +- 20 files changed, 496 insertions(+), 20 deletions(-) diff --git a/AUTHORS b/AUTHORS index 87d19449f..3353e7652 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ Kirill Andreev (andreev@iitp.ru) Nicola Baldo (nbaldo@cttc.es) Mirko Banchi (mk.banchi@gmail.com) +Ramon Bauza (monbauza@gmail.com) Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu) Raj Bhattacharjea (raj.b@gatech.edu) Timo Bingmann (timo.bingmann@student.kit.edu) diff --git a/CHANGES.html b/CHANGES.html index 997b0e95f..d4350ab7d 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -107,6 +107,9 @@ router solicitation, DAD +

diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 102e2bdb2..f9fbfb5f8 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -57,6 +57,8 @@ New user-visible features e) 802.11 enhancements: - 10MHz and 5MHz channel width supported by 802.11a model (Ramon Bauza and Kirill Andreev) + - Channel switching support. YansWifiPhy can now switch among different channels + (Ramon Bauza and Pavel Boyko) API changes from ns-3.5 ----------------------- diff --git a/examples/wifi-ap.cc b/examples/wifi-ap.cc index f7f169ab8..f84395fa4 100644 --- a/examples/wifi-ap.cc +++ b/examples/wifi-ap.cc @@ -62,6 +62,9 @@ PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::Sta { std::cout << " state="; switch (state) { + case WifiPhy::SWITCHING: + std::cout << "switchng"; + break; case WifiPhy::TX: std::cout << "tx "; break; diff --git a/src/devices/wifi/dca-txop.cc b/src/devices/wifi/dca-txop.cc index 6b4a64f43..e19363591 100644 --- a/src/devices/wifi/dca-txop.cc +++ b/src/devices/wifi/dca-txop.cc @@ -58,6 +58,9 @@ private: virtual void DoNotifyCollision (void) { m_txop->NotifyCollision (); } + virtual void DoNotifyChannelSwitching (void) { + m_txop->NotifyChannelSwitching (); + } DcaTxop *m_txop; }; @@ -446,6 +449,13 @@ DcaTxop::NotifyCollision (void) RestartAccessIfNeeded (); } +void +DcaTxop::NotifyChannelSwitching (void) +{ + m_queue->Flush(); + m_currentPacket = 0; +} + void DcaTxop::GotCts (double snr, WifiMode txMode) { diff --git a/src/devices/wifi/dca-txop.h b/src/devices/wifi/dca-txop.h index 4fd697230..5406ac2fc 100644 --- a/src/devices/wifi/dca-txop.h +++ b/src/devices/wifi/dca-txop.h @@ -127,6 +127,7 @@ private: void NotifyAccessGranted (void); void NotifyInternalCollision (void); void NotifyCollision (void); + void NotifyChannelSwitching (void); /* event handlers */ void GotCts (double snr, WifiMode txMode); void MissedCts (void); diff --git a/src/devices/wifi/dcf-manager-test.cc b/src/devices/wifi/dcf-manager-test.cc index b94f0ed3f..8972e527c 100644 --- a/src/devices/wifi/dcf-manager-test.cc +++ b/src/devices/wifi/dcf-manager-test.cc @@ -38,6 +38,7 @@ private: virtual void DoNotifyAccessGranted (void); virtual void DoNotifyInternalCollision (void); virtual void DoNotifyCollision (void); + virtual void DoNotifyChannelSwitching (void); typedef std::pair ExpectedGrant; typedef std::list ExpectedGrants; @@ -65,6 +66,7 @@ public: void NotifyAccessGranted (uint32_t i); void NotifyInternalCollision (uint32_t i); void NotifyCollision (uint32_t i); + void NotifyChannelSwitching (uint32_t i); private: @@ -88,6 +90,9 @@ private: void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from); void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, DcfStateTest *state); + void AddCcaBusyEvt (uint64_t at, uint64_t duration); + void AddSwitchingEvt (uint64_t at, uint64_t duration); + void AddRxStartEvt (uint64_t at, uint64_t duration); typedef std::vector DcfStates; @@ -122,7 +127,11 @@ DcfStateTest::DoNotifyCollision (void) { m_test->NotifyCollision (m_i); } - +void +DcfStateTest::DoNotifyChannelSwitching (void) +{ + m_test->NotifyChannelSwitching (m_i); +} DcfManagerTest::DcfManagerTest () @@ -182,7 +191,22 @@ DcfManagerTest::NotifyCollision (uint32_t i) m_result = result; } } - +void +DcfManagerTest::NotifyChannelSwitching (uint32_t i) +{ + DcfStateTest *state = m_dcfStates[i]; + bool result = true; + if (!state->m_expectedGrants.empty ()) + { + std::pair expected = state->m_expectedGrants.front (); + state->m_expectedGrants.pop_front (); + NS_TEST_ASSERT_EQUAL (Simulator::Now (), MicroSeconds (expected.second)); + } + if (!result) + { + m_result = result; + } +} void DcfManagerTest::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from) @@ -320,7 +344,27 @@ DcfManagerTest::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Dc state->QueueTx (txTime, expectedGrantTime); m_dcfManager->RequestAccess (state); } - +void +DcfManagerTest::AddCcaBusyEvt (uint64_t at, uint64_t duration) +{ + Simulator::Schedule (MicroSeconds (at) - Now (), + &DcfManager::NotifyMaybeCcaBusyStartNow, m_dcfManager, + MicroSeconds (duration)); +} +void +DcfManagerTest::AddSwitchingEvt (uint64_t at, uint64_t duration) +{ + Simulator::Schedule (MicroSeconds (at) - Now (), + &DcfManager::NotifySwitchingStartNow, m_dcfManager, + MicroSeconds (duration)); +} +void +DcfManagerTest::AddRxStartEvt (uint64_t at, uint64_t duration) +{ + Simulator::Schedule (MicroSeconds (at) - Now (), + &DcfManager::NotifyRxStartNow, m_dcfManager, + MicroSeconds (duration)); +} @@ -559,7 +603,95 @@ DcfManagerTest::RunTests (void) AddAccessRequest (30, 50, 108, 0); ExpectCollision (30, 3, 0); // backoff: 3 slots EndTest (); - + + + // Channel switching tests + + // 0 20 23 24 25 + // | switching | sifs | aifsn | tx | + // | + // 21 access request. + StartTest (1, 3, 10); + AddDcfState (1); + AddSwitchingEvt(0,20); + AddAccessRequest (21, 1, 24, 0); + EndTest (); + + // 20 40 50 53 54 55 + // | switching | busy | sifs | aifsn | tx | + // | | + // 30 busy. 45 access request. + // + StartTest (1, 3, 10); + AddDcfState (1); + AddSwitchingEvt(20,20); + AddCcaBusyEvt(30,20); + AddAccessRequest (45, 1, 54, 0); + EndTest (); + + // 20 30 50 53 54 55 + // | rx | switching | sifs | aifsn | tx | + // | + // 51 access request. + // + StartTest (1, 3, 10); + AddDcfState (1); + AddRxStartEvt (20,40); + AddSwitchingEvt(30,20); + AddAccessRequest (51, 1, 54, 0); + EndTest (); + + // 20 30 50 53 54 55 + // | busy | switching | sifs | aifsn | tx | + // | + // 51 access request. + // + StartTest (1, 3, 10); + AddDcfState (1); + AddCcaBusyEvt (20,40); + AddSwitchingEvt(30,20); + AddAccessRequest (51, 1, 54, 0); + EndTest (); + + // 20 30 50 53 54 55 + // | nav | switching | sifs | aifsn | tx | + // | + // 51 access request. + // + StartTest (1, 3, 10); + AddDcfState (1); + AddNavStart (20,40); + AddSwitchingEvt(30,20); + AddAccessRequest (51, 1, 54, 0); + EndTest (); + + // 20 40 50 55 58 59 60 + // | tx | ack timeout | switching | sifs | aifsn | tx | + // | | + // 45 access request. 56 access request. + // + StartTest (1, 3, 10); + AddDcfState (1); + AddAccessRequestWithAckTimeout (20, 20, 20, 0); + AddAccessRequest (45, 1, 50, 0); + AddSwitchingEvt(50,5); + AddAccessRequest (56, 1, 59, 0); + EndTest (); + + // 20 60 66 70 74 78 80 100 106 110 112 + // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | sifs | aifsn | tx | + // | | + // 30 access request. 101 access request. + // + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt(20,40); + AddAccessRequest (30, 2, 80, 0); + ExpectCollision(30, 4, 0); // backoff: 4 slots + AddSwitchingEvt(80,20); + AddAccessRequest (101, 2, 110, 0); + EndTest (); + return m_result; } diff --git a/src/devices/wifi/dcf-manager.cc b/src/devices/wifi/dcf-manager.cc index 320bf0621..467caf77f 100644 --- a/src/devices/wifi/dcf-manager.cc +++ b/src/devices/wifi/dcf-manager.cc @@ -154,6 +154,11 @@ DcfState::NotifyInternalCollision (void) { DoNotifyInternalCollision (); } +void +DcfState::NotifyChannelSwitching (void) +{ + DoNotifyChannelSwitching (); +} /*************************************************************** @@ -211,6 +216,9 @@ public: virtual void NotifyMaybeCcaBusyStart (Time duration) { m_dcf->NotifyMaybeCcaBusyStartNow (duration); } + virtual void NotifySwitchingStart (Time duration) { + m_dcf->NotifySwitchingStartNow (duration); + } private: ns3::DcfManager *m_dcf; }; @@ -232,6 +240,8 @@ DcfManager::DcfManager () m_lastTxDuration (MicroSeconds (0)), m_lastBusyStart (MicroSeconds (0)), m_lastBusyDuration (MicroSeconds (0)), + m_lastSwitchingStart (MicroSeconds (0)), + m_lastSwitchingDuration (MicroSeconds (0)), m_rxing (false), m_slotTime (Seconds (0.0)), m_sifs (Seconds (0.0)), @@ -319,6 +329,18 @@ DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f) const return retval; } +Time +DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f, Time g) const +{ + Time h = Max (a, b); + Time i = Max (c, d); + Time j = Max (e, f); + Time k = Max (h, i); + Time l = Max (j, g); + Time retval = Max (k, l); + return retval; +} + bool DcfManager::IsBusy (void) const { @@ -454,12 +476,14 @@ DcfManager::GetAccessGrantStart (void) const Time navAccessStart = m_lastNavStart + m_lastNavDuration + m_sifs; Time ackTimeoutAccessStart = m_lastAckTimeoutEnd + m_sifs; Time ctsTimeoutAccessStart = m_lastCtsTimeoutEnd + m_sifs; + Time switchingAccessStart = m_lastSwitchingStart + m_lastSwitchingDuration + m_sifs; Time accessGrantedStart = MostRecent (rxAccessStart, busyAccessStart, txAccessStart, navAccessStart, ackTimeoutAccessStart, - ctsTimeoutAccessStart + ctsTimeoutAccessStart, + switchingAccessStart ); NS_LOG_INFO ("access grant start=" << accessGrantedStart << ", rx access start=" << rxAccessStart << @@ -596,6 +620,67 @@ DcfManager::NotifyMaybeCcaBusyStartNow (Time duration) m_lastBusyStart = Simulator::Now (); m_lastBusyDuration = duration; } + + +void +DcfManager::NotifySwitchingStartNow (Time duration) +{ + Time now = Simulator::Now (); + NS_ASSERT (m_lastTxStart + m_lastTxDuration <= now); + NS_ASSERT (m_lastSwitchingStart + m_lastSwitchingDuration <= now); + + if (m_rxing) + { + // channel switching during packet reception + m_lastRxEnd = Simulator::Now (); + m_lastRxDuration = m_lastRxEnd - m_lastRxStart; + m_lastRxReceivedOk = true; + m_rxing = false; + } + if (m_lastNavStart + m_lastNavDuration > now) + { + m_lastNavDuration = now - m_lastNavStart; + } + if (m_lastBusyStart + m_lastBusyDuration > now) + { + m_lastBusyDuration = now - m_lastBusyStart; + } + if (m_lastAckTimeoutEnd > now) + { + m_lastAckTimeoutEnd = now; + } + if (m_lastCtsTimeoutEnd > now) + { + m_lastCtsTimeoutEnd = now; + } + + // Cancel timeout + if (m_accessTimeout.IsRunning ()) + { + m_accessTimeout.Cancel (); + } + + // Reset backoffs + for (States::iterator i = m_states.begin (); i != m_states.end (); i++) + { + DcfState *state = *i; + uint32_t remainingSlots = state->GetBackoffSlots (); + if (remainingSlots > 0) + { + state->UpdateBackoffSlotsNow (remainingSlots, now); + NS_ASSERT(state->GetBackoffSlots()==0); + } + state->ResetCw(); + state->m_accessRequested = false; + state->NotifyChannelSwitching(); + } + + MY_DEBUG ("switching start for "<NotifyCollision (); } + virtual void DoNotifyChannelSwitching (void) { + m_txop->NotifyChannelSwitching (); + } EdcaTxopN *m_txop; }; @@ -427,6 +430,13 @@ EdcaTxopN::MissedCts (void) RestartAccessIfNeeded (); } +void +EdcaTxopN::NotifyChannelSwitching (void) +{ + m_queue->Flush(); + m_currentPacket = 0; +} + void EdcaTxopN::Queue (Ptr packet, WifiMacHeader const &hdr) { diff --git a/src/devices/wifi/edca-txop-n.h b/src/devices/wifi/edca-txop-n.h index 216c77bb1..37f43e52e 100644 --- a/src/devices/wifi/edca-txop-n.h +++ b/src/devices/wifi/edca-txop-n.h @@ -101,6 +101,7 @@ public: void NotifyAccessGranted (void); void NotifyInternalCollision (void); void NotifyCollision (void); + void NotifyChannelSwitching (void); /*event handlers*/ void GotCts (double snr, WifiMode txMode); diff --git a/src/devices/wifi/interference-helper.cc b/src/devices/wifi/interference-helper.cc index c375d095e..4e0301ba0 100644 --- a/src/devices/wifi/interference-helper.cc +++ b/src/devices/wifi/interference-helper.cc @@ -603,6 +603,10 @@ InterferenceHelper::CalculateSnrPer (Ptr event) return snrPer; } - +void +InterferenceHelper::EraseEvents (void) +{ + m_events.erase (m_events.begin (), m_events.end ()); +} } // namespace ns3 diff --git a/src/devices/wifi/interference-helper.h b/src/devices/wifi/interference-helper.h index 2140cb12a..0ae37b280 100644 --- a/src/devices/wifi/interference-helper.h +++ b/src/devices/wifi/interference-helper.h @@ -95,6 +95,7 @@ public: Time duration, double rxPower); struct InterferenceHelper::SnrPer CalculateSnrPer (Ptr event); + void EraseEvents (void); private: class NiChange { public: diff --git a/src/devices/wifi/mac-low.cc b/src/devices/wifi/mac-low.cc index bc0ee2035..c18a7638f 100644 --- a/src/devices/wifi/mac-low.cc +++ b/src/devices/wifi/mac-low.cc @@ -244,6 +244,30 @@ std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters return os; } + +/*************************************************************** + * Listener for PHY events. Forwards to MacLow + ***************************************************************/ + + +class PhyMacLowListener : public ns3::WifiPhyListener { +public: + PhyMacLowListener (ns3::MacLow *macLow) + : m_macLow (macLow) {} + virtual ~PhyMacLowListener () {} + virtual void NotifyRxStart (Time duration) {} + virtual void NotifyRxEndOk (void) {} + virtual void NotifyRxEndError (void) {} + virtual void NotifyTxStart (Time duration) {} + virtual void NotifyMaybeCcaBusyStart (Time duration) {} + virtual void NotifySwitchingStart (Time duration) { + m_macLow->NotifySwitchingStartNow (duration); + } +private: + ns3::MacLow *m_macLow; +}; + + MacLow::MacLow () : m_normalAckTimeoutEvent (), m_fastAckTimeoutEvent (), @@ -267,6 +291,14 @@ MacLow::~MacLow () NS_LOG_FUNCTION (this); } +void +MacLow::SetupPhyMacLowListener (Ptr phy) +{ + m_phyMacLowListener = new PhyMacLowListener (this); + phy->RegisterListener (m_phyMacLowListener); +} + + void MacLow::DoDispose (void) { @@ -274,6 +306,8 @@ MacLow::DoDispose (void) CancelAllEvents (); m_phy = 0; m_stationManager = 0; + delete m_phyMacLowListener; + m_phyMacLowListener = 0; } void @@ -339,6 +373,7 @@ MacLow::SetPhy (Ptr phy) m_phy = phy; m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::ReceiveOk, this)); m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, this)); + SetupPhyMacLowListener(phy); } void MacLow::SetWifiRemoteStationManager (Ptr manager) @@ -488,6 +523,22 @@ MacLow::ReceiveError (Ptr packet, double rxSnr) return; } +void +MacLow::NotifySwitchingStartNow (Time duration) +{ + NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events"); + m_stationManager->Reset(); + CancelAllEvents(); + if (m_navCounterResetCtsMissed.IsRunning ()) + { + m_navCounterResetCtsMissed.Cancel(); + } + m_lastNavStart = Simulator::Now (); + m_lastNavDuration = Seconds (0); + m_currentPacket = 0; + m_listener = 0; +} + void MacLow::ReceiveOk (Ptr packet, double rxSnr, WifiMode txMode, WifiPreamble preamble) { diff --git a/src/devices/wifi/mac-low.h b/src/devices/wifi/mac-low.h index 7f1bca086..2a1ee4002 100644 --- a/src/devices/wifi/mac-low.h +++ b/src/devices/wifi/mac-low.h @@ -356,6 +356,13 @@ public: * the MAC layer that a packet was unsuccessfully received. */ void ReceiveError (Ptr packet, double rxSnr); + /** + * \param duration switching delay duration. + * + * This method is typically invoked by the PhyMacLowListener to notify + * the MAC layer that a channel switching occured. + */ + void NotifySwitchingStartNow (Time duration); private: void CancelAllEvents (void); uint32_t GetAckSize (void) const; @@ -402,6 +409,8 @@ private: void StartDataTxTimers (void); virtual void DoDispose (void); + void SetupPhyMacLowListener (Ptr phy); + Ptr m_phy; Ptr m_stationManager; MacLowRxCallback m_rxCallback; @@ -434,6 +443,9 @@ private: Time m_lastNavStart; Time m_lastNavDuration; + + // Listerner needed to monitor when a channel switching occurs. + class PhyMacLowListener *m_phyMacLowListener; }; } // namespace ns3 diff --git a/src/devices/wifi/wifi-phy-state-helper.cc b/src/devices/wifi/wifi-phy-state-helper.cc index 5626e4281..9a4d1cae8 100644 --- a/src/devices/wifi/wifi-phy-state-helper.cc +++ b/src/devices/wifi/wifi-phy-state-helper.cc @@ -54,9 +54,11 @@ WifiPhyStateHelper::WifiPhyStateHelper () m_endTx (Seconds (0)), m_endSync (Seconds (0)), m_endCcaBusy (Seconds (0)), + m_endSwitching (Seconds (0)), m_startTx (Seconds (0)), m_startSync (Seconds (0)), m_startCcaBusy (Seconds (0)), + m_startSwitching (Seconds (0)), m_previousStateChangeTime (Seconds (0)) { NS_LOG_FUNCTION (this); @@ -104,6 +106,11 @@ WifiPhyStateHelper::IsStateTx (void) { return (GetState () == WifiPhy::TX)?true:false; } +bool +WifiPhyStateHelper::IsStateSwitching (void) +{ + return (GetState () == WifiPhy::SWITCHING)?true:false; +} @@ -128,6 +135,9 @@ WifiPhyStateHelper::GetDelayUntilIdle (void) case WifiPhy::CCA_BUSY: retval = m_endCcaBusy - Simulator::Now (); break; + case WifiPhy::SWITCHING: + retval = m_endSwitching - Simulator::Now (); + break; case WifiPhy::IDLE: retval = Seconds (0); break; @@ -163,6 +173,9 @@ WifiPhyStateHelper::StateToString (enum WifiPhy::State state) case WifiPhy::SYNC: return "SYNC"; break; + case WifiPhy::SWITCHING: + return "SWITCHING"; + break; default: NS_ASSERT (false); // quiet compiler @@ -182,6 +195,10 @@ WifiPhyStateHelper::GetState (void) { return WifiPhy::SYNC; } + else if (m_endSwitching > Simulator::Now ()) + { + return WifiPhy::SWITCHING; + } else if (m_endCcaBusy > Simulator::Now ()) { return WifiPhy::CCA_BUSY; @@ -228,6 +245,13 @@ WifiPhyStateHelper::NotifyMaybeCcaBusyStart (Time duration) (*i)->NotifyMaybeCcaBusyStart (duration); } } +void +WifiPhyStateHelper::NotifySwitchingStart (Time duration) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifySwitchingStart (duration); + } +} void WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void) @@ -235,11 +259,14 @@ WifiPhyStateHelper::LogPreviousIdleAndCcaBusyStates (void) Time now = Simulator::Now (); Time idleStart = Max (m_endCcaBusy, m_endSync); idleStart = Max (idleStart, m_endTx); + idleStart = Max (idleStart, m_endSwitching); NS_ASSERT (idleStart <= now); if (m_endCcaBusy > m_endSync && + m_endCcaBusy > m_endSwitching && m_endCcaBusy > m_endTx) { Time ccaBusyStart = Max (m_endTx, m_endSync); ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy); + ccaBusyStart = Max (ccaBusyStart, m_endSwitching); m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY); } m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE); @@ -264,11 +291,13 @@ WifiPhyStateHelper::SwitchToTx (Time txDuration, Ptr packet, WifiM case WifiPhy::CCA_BUSY: { Time ccaStart = Max (m_endSync, m_endTx); ccaStart = Max (ccaStart, m_startCcaBusy); + ccaStart = Max (ccaStart, m_endSwitching); m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); } break; case WifiPhy::IDLE: LogPreviousIdleAndCcaBusyStates (); break; + case WifiPhy::SWITCHING: default: NS_ASSERT (false); break; @@ -292,8 +321,10 @@ WifiPhyStateHelper::SwitchToSync (Time rxDuration) case WifiPhy::CCA_BUSY: { Time ccaStart = Max (m_endSync, m_endTx); ccaStart = Max (ccaStart, m_startCcaBusy); + ccaStart = Max (ccaStart, m_endSwitching); m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); } break; + case WifiPhy::SWITCHING: case WifiPhy::SYNC: case WifiPhy::TX: NS_ASSERT (false); @@ -305,6 +336,49 @@ WifiPhyStateHelper::SwitchToSync (Time rxDuration) m_endSync = now + rxDuration; NS_ASSERT (IsStateSync ()); } + +void +WifiPhyStateHelper::SwitchToChannelSwitching (Time switchingDuration) +{ + NotifySwitchingStart (switchingDuration); + Time now = Simulator::Now (); + switch (GetState ()) { + case WifiPhy::SYNC: + /* The packet which is being received as well + * as its endSync event are cancelled by the caller. + */ + m_syncing = false; + m_stateLogger (m_startSync, now - m_startSync, WifiPhy::SYNC); + m_endSync = now; + break; + case WifiPhy::CCA_BUSY: { + Time ccaStart = Max (m_endSync, m_endTx); + ccaStart = Max (ccaStart, m_startCcaBusy); + ccaStart = Max (ccaStart, m_endSwitching); + m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); + } break; + case WifiPhy::IDLE: + LogPreviousIdleAndCcaBusyStates (); + break; + case WifiPhy::TX: + case WifiPhy::SWITCHING: + default: + NS_ASSERT (false); + break; + } + + if (now < m_endCcaBusy) + { + m_endCcaBusy = now; + } + + m_stateLogger (now, switchingDuration, WifiPhy::SWITCHING); + m_previousStateChangeTime = now; + m_startSwitching = now; + m_endSwitching = now + switchingDuration; + NS_ASSERT (IsStateSwitching ()); +} + void WifiPhyStateHelper::SwitchFromSyncEndOk (Ptr packet, double snr, WifiMode mode, enum WifiPreamble preamble) { @@ -348,6 +422,8 @@ WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration) NotifyMaybeCcaBusyStart (duration); Time now = Simulator::Now (); switch (GetState ()) { + case WifiPhy::SWITCHING: + break; case WifiPhy::IDLE: LogPreviousIdleAndCcaBusyStates (); break; diff --git a/src/devices/wifi/wifi-phy-state-helper.h b/src/devices/wifi/wifi-phy-state-helper.h index b28561550..de8443b18 100644 --- a/src/devices/wifi/wifi-phy-state-helper.h +++ b/src/devices/wifi/wifi-phy-state-helper.h @@ -43,12 +43,14 @@ public: bool IsStateBusy (void); bool IsStateSync (void); bool IsStateTx (void); + bool IsStateSwitching (void); Time GetStateDuration (void); Time GetDelayUntilIdle (void); Time GetLastRxStartTime (void) const; void SwitchToTx (Time txDuration, Ptr packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower); void SwitchToSync (Time syncDuration); + void SwitchToChannelSwitching (Time switchingDuration); void SwitchFromSyncEndOk (Ptr packet, double snr, WifiMode mode, enum WifiPreamble preamble); void SwitchFromSyncEndError (Ptr packet, double snr); void SwitchMaybeToCcaBusy (Time duration); @@ -66,15 +68,18 @@ private: void NotifySyncEndOk (void); void NotifySyncEndError (void); void NotifyMaybeCcaBusyStart (Time duration); + void NotifySwitchingStart (Time duration); void DoSwitchFromSync (void); bool m_syncing; Time m_endTx; Time m_endSync; Time m_endCcaBusy; + Time m_endSwitching; Time m_startTx; Time m_startSync; Time m_startCcaBusy; + Time m_startSwitching; Time m_previousStateChangeTime; Listeners m_listeners; diff --git a/src/devices/wifi/wifi-phy.h b/src/devices/wifi/wifi-phy.h index d75ff70da..2e2092748 100644 --- a/src/devices/wifi/wifi-phy.h +++ b/src/devices/wifi/wifi-phy.h @@ -97,6 +97,14 @@ public: * what duration it reported. */ virtual void NotifyMaybeCcaBusyStart (Time duration) = 0; + /** + * \param duration the expected channel switching duration. + * + * We do not send any event to notify the end of + * channel switching. Listeners should assume that the + * channel implicitely reverts to the idle or busy states. + */ + virtual void NotifySwitchingStart (Time duration) = 0; }; @@ -127,7 +135,11 @@ public: /** * The PHY layer is IDLE. */ - IDLE + IDLE, + /** + * The PHY layer is switching to other channel. + */ + SWITCHING }; /** * arg1: packet received successfully diff --git a/src/devices/wifi/yans-wifi-phy.cc b/src/devices/wifi/yans-wifi-phy.cc index eead8afae..7efbf6739 100644 --- a/src/devices/wifi/yans-wifi-phy.cc +++ b/src/devices/wifi/yans-wifi-phy.cc @@ -302,27 +302,53 @@ YansWifiPhy::SetChannel (Ptr channel) { m_channel = channel; m_channel->Add (this); - m_channelId = 1; // always start on channel starting frequency (channel 1) + m_channelNumber = 1; // always start on channel starting frequency (channel 1) } void YansWifiPhy::SetChannelNumber (uint16_t nch) { - // TODO implement channel switching state machine here - DoSetChannelNumber (nch); -} + NS_ASSERT(!IsStateSwitching()); + switch (m_state->GetState ()) { + case YansWifiPhy::SYNC: + NS_LOG_DEBUG ("drop packet because of channel switching while reception"); + m_endSyncEvent.Cancel(); + goto switchChannel; + break; + case YansWifiPhy::TX: + NS_LOG_DEBUG ("channel switching postponed until end of current transmission"); + Simulator::Schedule (GetDelayUntilIdle(), &YansWifiPhy::SetChannelNumber, this, nch); + break; + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::IDLE: + goto switchChannel; + break; + default: + NS_ASSERT (false); + break; + } -void -YansWifiPhy::DoSetChannelNumber (uint16_t nch) -{ - NS_LOG_DEBUG("switching channel " << m_channelId << " -> " << nch); - m_channelId = nch; + return; + + switchChannel: + + NS_LOG_DEBUG("switching channel " << m_channelNumber << " -> " << nch); + m_state->SwitchToChannelSwitching(m_channelSwitchDelay); + m_interference.EraseEvents(); + /* + * Needed here to be able to correctly sensed the medium for the first + * time after the switching. The actual switching is not performed until + * after m_channelSwitchDelay. Packets received during the switching + * state are added to the event list and are employed later to figure + * out the state of the medium after the switching. + */ + m_channelNumber = nch; } uint16_t YansWifiPhy::GetChannelNumber() const { - return m_channelId; + return m_channelNumber; } double @@ -361,6 +387,24 @@ YansWifiPhy::StartReceivePacket (Ptr packet, rxPowerW); switch (m_state->GetState ()) { + case YansWifiPhy::SWITCHING: + NS_LOG_DEBUG ("drop packet because of channel switching"); + NotifyRxDrop (packet); + /* + * Packets received on the upcoming channel are added to the event list + * during the switching state. This way the medium can be correctly sensed + * when the device listens to the channel for the first time after the + * switching e.g. after channel switching, the channel may be sensed as + * busy due to other devices' tramissions started before the end of + * the switching. + */ + if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ()) + { + // that packet will be noise _after_ the completion of the + // channel switching. + goto maybeCcaBusy; + } + break; case YansWifiPhy::SYNC: NS_LOG_DEBUG ("drop packet because already in Sync (power="<< rxPowerW<<"W)"); @@ -431,7 +475,7 @@ YansWifiPhy::SendPacket (Ptr packet, WifiMode txMode, WifiPreamble * prevent it. * - we are idle */ - NS_ASSERT (!m_state->IsStateTx ()); + NS_ASSERT (!m_state->IsStateTx () && !m_state->IsStateSwitching ()); Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble); if (m_state->IsStateSync ()) @@ -563,6 +607,11 @@ YansWifiPhy::IsStateTx (void) { return m_state->IsStateTx (); } +bool +YansWifiPhy::IsStateSwitching (void) +{ + return m_state->IsStateSwitching (); +} Time YansWifiPhy::GetStateDuration (void) diff --git a/src/devices/wifi/yans-wifi-phy.h b/src/devices/wifi/yans-wifi-phy.h index 34c3313e7..c39be9f25 100644 --- a/src/devices/wifi/yans-wifi-phy.h +++ b/src/devices/wifi/yans-wifi-phy.h @@ -124,6 +124,7 @@ public: virtual bool IsStateBusy (void); virtual bool IsStateSync (void); virtual bool IsStateTx (void); + virtual bool IsStateSwitching (void); virtual Time GetStateDuration (void); virtual Time GetDelayUntilIdle (void); virtual Time GetLastRxStartTime (void) const; @@ -152,7 +153,6 @@ private: double RatioToDb (double ratio) const; double GetPowerDbm (uint8_t power) const; void EndSync (Ptr packet, Ptr event); - void DoSetChannelNumber(uint16_t id); private: double m_edThresholdW; @@ -164,7 +164,7 @@ private: uint32_t m_nTxPower; Ptr m_channel; - uint16_t m_channelId; + uint16_t m_channelNumber; Ptr m_device; Ptr m_mobility; Modes m_modes; From c8949c75a8092ffe7dec8e4069445bc02a1dbaa8 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Tue, 15 Sep 2009 13:04:28 +0200 Subject: [PATCH 2/8] put all wifi news together --- RELEASE_NOTES | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 102e2bdb2..159db5e61 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -30,8 +30,14 @@ http://www.nsnam.org/wiki/index.php/Installation New user-visible features ------------------------- - a) Add an implementation of the minstrel rate control algorithm - (Duy Nguyen for gsoc) + a) 802.11 models: + - Add an implementation of the minstrel rate control algorithm + (Duy Nguyen for gsoc) + - AthstatsHelper: enables the wifi device to produce periodic + reports similar to the ones generated by madwifi's + athstats tool (Nicola Baldo) + - 10MHz and 5MHz channel width supported by 802.11a model + (Ramon Bauza and Kirill Andreev) b) IPv6 models: - IPv6 interface; @@ -46,17 +52,10 @@ New user-visible features - Examples (ping6, simple-routing-ping6, radvd, radvd-two-prefix, icmpv6-redirect). - c) added AthstatsHelper, which enables the wifi device to produce - periodic reports similar to the ones generated by madwifi's - athstats tool (Nicola Baldo) - - d) Wireless Mesh Networking models: + c) Wireless Mesh Networking models: - General multi-interface mesh stack infrastructure (devices/mesh module). - IEEE 802.11s (Draft 3.0) model including Peering Management Protocol and HWMP. - Forwarding Layer for Meshing (FLAME) protocol. - - e) 802.11 enhancements: - - 10MHz and 5MHz channel width supported by 802.11a model (Ramon Bauza and Kirill Andreev) API changes from ns-3.5 ----------------------- From 55bf5fc2e7c22c1ec50bd29e88e488c30a9660e4 Mon Sep 17 00:00:00 2001 From: Ramon Bauza Date: Tue, 15 Sep 2009 14:33:04 +0200 Subject: [PATCH 3/8] Doxy doc for Wifi channel switching --- src/devices/wifi/dca-txop.h | 3 +++ src/devices/wifi/dcf-manager.h | 2 ++ src/devices/wifi/edca-txop-n.h | 3 +++ src/devices/wifi/mac-low.h | 3 ++- src/devices/wifi/yans-wifi-channel.h | 4 +++- src/devices/wifi/yans-wifi-phy.h | 7 +++++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/devices/wifi/dca-txop.h b/src/devices/wifi/dca-txop.h index 5406ac2fc..69b8a050f 100644 --- a/src/devices/wifi/dca-txop.h +++ b/src/devices/wifi/dca-txop.h @@ -127,6 +127,9 @@ private: void NotifyAccessGranted (void); void NotifyInternalCollision (void); void NotifyCollision (void); + /** + * When a channel switching occurs, enqueued packets are removed. + */ void NotifyChannelSwitching (void); /* event handlers */ void GotCts (double snr, WifiMode txMode); diff --git a/src/devices/wifi/dcf-manager.h b/src/devices/wifi/dcf-manager.h index e19bfcbcc..dcd2393f9 100644 --- a/src/devices/wifi/dcf-manager.h +++ b/src/devices/wifi/dcf-manager.h @@ -260,6 +260,8 @@ public: * \param duration expected duration of channel switching period * * Notify the DCF that a channel switching period has just started. + * During swtiching state, new packets can be enqueued in DcaTxop/EdcaTxop + * but they won't access to the medium until the end of the channel switching. */ void NotifySwitchingStartNow (Time duration); /** diff --git a/src/devices/wifi/edca-txop-n.h b/src/devices/wifi/edca-txop-n.h index 37f43e52e..eb80a4fc9 100644 --- a/src/devices/wifi/edca-txop-n.h +++ b/src/devices/wifi/edca-txop-n.h @@ -101,6 +101,9 @@ public: void NotifyAccessGranted (void); void NotifyInternalCollision (void); void NotifyCollision (void); + /** + * When a channel switching occurs, enqueued packets are removed. + */ void NotifyChannelSwitching (void); /*event handlers*/ diff --git a/src/devices/wifi/mac-low.h b/src/devices/wifi/mac-low.h index 2a1ee4002..7b090fbd9 100644 --- a/src/devices/wifi/mac-low.h +++ b/src/devices/wifi/mac-low.h @@ -360,7 +360,8 @@ public: * \param duration switching delay duration. * * This method is typically invoked by the PhyMacLowListener to notify - * the MAC layer that a channel switching occured. + * the MAC layer that a channel switching occured. When a channel switching + * occurs, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled. */ void NotifySwitchingStartNow (Time duration); private: diff --git a/src/devices/wifi/yans-wifi-channel.h b/src/devices/wifi/yans-wifi-channel.h index 6bd05c4e0..ab6a4d526 100644 --- a/src/devices/wifi/yans-wifi-channel.h +++ b/src/devices/wifi/yans-wifi-channel.h @@ -76,7 +76,9 @@ public: * \param preamble the preamble associated to the packet * * This method should not be invoked by normal users. It is - * currently invoked only from WifiPhy::Send. + * currently invoked only from WifiPhy::Send. YansWifiChannel + * delivers packets only between PHYs with the same m_channelNumber, + * e.g. PHYs that are operating on the same channel. */ void Send (Ptr sender, Ptr packet, double txPowerDbm, WifiMode wifiMode, WifiPreamble preamble) const; diff --git a/src/devices/wifi/yans-wifi-phy.h b/src/devices/wifi/yans-wifi-phy.h index c39be9f25..948d97bfb 100644 --- a/src/devices/wifi/yans-wifi-phy.h +++ b/src/devices/wifi/yans-wifi-phy.h @@ -77,6 +77,13 @@ public: * * where Starting channel frequency is standard-dependent, see SetStandard() * as defined in IEEE 802.11-2007 17.3.8.3.2. + * + * YansWifiPhy can switch among different channels. Basically, YansWifiPhy + * has a private attribute m_channelNumber that identifies the channel the + * PHY operates on. Channel switching cannot interrupt an ongoing transmission. + * When PHY is in TX state, the channel switching is postponed until the end + * of the current transmission. When the PHY is in SYNC state, the channel + * switching causes the drop of the sync packet. */ void SetChannelNumber (uint16_t id); /// Return current channel number, see SetChannelNumber() From b51933502b53d06356268e6592af932d3f063a71 Mon Sep 17 00:00:00 2001 From: Pavel Boyko Date: Tue, 15 Sep 2009 19:05:39 +0400 Subject: [PATCH 4/8] build fix (g++ 4.0.4 and 4.4.0 optimized only) --- src/devices/mesh/dot11s/dot11s-mac-header.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/devices/mesh/dot11s/dot11s-mac-header.cc b/src/devices/mesh/dot11s/dot11s-mac-header.cc index 482dd95e1..215e2ecb4 100644 --- a/src/devices/mesh/dot11s/dot11s-mac-header.cc +++ b/src/devices/mesh/dot11s/dot11s-mac-header.cc @@ -252,6 +252,7 @@ WifiMeshActionHeader::GetAction () return retval; default: NS_FATAL_ERROR ("Unknown mesh peering management action code"); + retval.peerLink = PEER_LINK_OPEN; /* quiet compiler */ return retval; } case MESH_PATH_SELECTION: @@ -262,6 +263,7 @@ WifiMeshActionHeader::GetAction () return retval; default: NS_FATAL_ERROR ("Unknown mesh path selection action code"); + retval.peerLink = PEER_LINK_OPEN; /* quiet compiler */ return retval; } case MESH_LINK_METRIC: @@ -272,6 +274,7 @@ WifiMeshActionHeader::GetAction () // not yet supported default: NS_FATAL_ERROR ("Unsupported mesh action"); + retval.peerLink = PEER_LINK_OPEN; /* quiet compiler */ return retval; } } From 473d80ea54c9b1fb6c1841d16d44fc8195605018 Mon Sep 17 00:00:00 2001 From: Sebastien Vincent Date: Tue, 15 Sep 2009 17:29:09 +0200 Subject: [PATCH 5/8] Fix main-random-topology sample. --- samples/main-random-topology.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/main-random-topology.cc b/samples/main-random-topology.cc index 4c7e7b512..62e2d5fbb 100644 --- a/samples/main-random-topology.cc +++ b/samples/main-random-topology.cc @@ -32,7 +32,7 @@ int main (int argc, char *argv[]) mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); mobility.Install (c); - Config::Connect ("/NodeList/*/$ns3::MobilityModelNotifier/CourseChange", + Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange", MakeCallback (&CourseChange)); Simulator::Stop (Seconds (100.0)); From 8cd2f7b8e58cad21676dbde4485f9c8c1a53c833 Mon Sep 17 00:00:00 2001 From: Sebastien Vincent Date: Tue, 15 Sep 2009 17:32:23 +0200 Subject: [PATCH 6/8] Add a way to disable DAD via an Icmpv6L4Protocol attribute. --- src/internet-stack/icmpv6-l4-protocol.cc | 16 +++++++++++++++- src/internet-stack/icmpv6-l4-protocol.h | 12 ++++++++++++ src/internet-stack/ipv6-interface.cc | 2 +- src/internet-stack/ipv6-test.cc | 1 + 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/internet-stack/icmpv6-l4-protocol.cc b/src/internet-stack/icmpv6-l4-protocol.cc index b783c6a93..8ea3ee0f6 100644 --- a/src/internet-stack/icmpv6-l4-protocol.cc +++ b/src/internet-stack/icmpv6-l4-protocol.cc @@ -69,6 +69,10 @@ TypeId Icmpv6L4Protocol::GetTypeId () static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol") .SetParent () .AddConstructor () + .AddAttribute ("DAD", "Always do DAD check.", + BooleanValue (true), + MakeBooleanAccessor (&Icmpv6L4Protocol::m_alwaysDad), + MakeBooleanChecker ()) ; return tid; } @@ -144,14 +148,24 @@ int Icmpv6L4Protocol::GetVersion () const return 1; } +bool Icmpv6L4Protocol::IsAlwaysDad () const +{ + return m_alwaysDad; +} + void Icmpv6L4Protocol::DoDAD (Ipv6Address target, Ptr interface) { NS_LOG_FUNCTION (this << target << interface); Ipv6Address addr; - Ptr ipv6 = m_node->GetObject (); + NS_ASSERT (ipv6); + if(!m_alwaysDad) + { + return; + } + /* TODO : disable multicast loopback to prevent NS probing to be received by the sender */ Ptr p = ForgeNS ("::" ,Ipv6Address::MakeSolicitedAddress (target), target, interface->GetDevice ()->GetAddress ()); diff --git a/src/internet-stack/icmpv6-l4-protocol.h b/src/internet-stack/icmpv6-l4-protocol.h index 4fecb747d..d7a13b1a5 100644 --- a/src/internet-stack/icmpv6-l4-protocol.h +++ b/src/internet-stack/icmpv6-l4-protocol.h @@ -28,6 +28,7 @@ #include "ns3/ptr.h" #include "ns3/socket.h" #include "ns3/buffer.h" +#include "ns3/boolean.h" #include "icmpv6-header.h" #include "ipv6-l4-protocol.h" #include "ndisc-cache.h" @@ -387,6 +388,12 @@ class Icmpv6L4Protocol : public Ipv6L4Protocol */ Ptr CreateCache (Ptr device, Ptr interface); + /** + * \brief Is the node must do DAD. + * \return true if node has to do DAD. + */ + bool IsAlwaysDad () const; + protected: /** * \brief Dispose this object. @@ -407,6 +414,11 @@ class Icmpv6L4Protocol : public Ipv6L4Protocol */ CacheList m_cacheList; + /** + * \brief Always do DAD ? + */ + bool m_alwaysDad; + /** * \brief Receive Neighbor Solicitation method. * \param p the packet diff --git a/src/internet-stack/ipv6-interface.cc b/src/internet-stack/ipv6-interface.cc index 9c07ec984..34d0cb82e 100644 --- a/src/internet-stack/ipv6-interface.cc +++ b/src/internet-stack/ipv6-interface.cc @@ -196,7 +196,7 @@ bool Ipv6Interface::AddAddress (Ipv6InterfaceAddress iface) /* DAD handling */ Ptr icmpv6 = m_node->GetObject ()->GetIcmpv6 (); - if (icmpv6) + if (icmpv6 && icmpv6->IsAlwaysDad ()) { Simulator::Schedule (Seconds (0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this); Simulator::Schedule (Seconds (1.), &Icmpv6L4Protocol::FunctionDadTimeout, icmpv6, this, addr); diff --git a/src/internet-stack/ipv6-test.cc b/src/internet-stack/ipv6-test.cc index 4f3de3892..55e320ca6 100644 --- a/src/internet-stack/ipv6-test.cc +++ b/src/internet-stack/ipv6-test.cc @@ -78,6 +78,7 @@ bool Ipv6L3ProtocolTest::RunTests () uint32_t index = 0; /* init */ + icmpv6->SetAttribute ("DAD", BooleanValue (false)); node->AggregateObject (ipv6); node->AggregateObject (icmpv6); ipv6->Insert (icmpv6); From a74ef755411052ef774f651c3efdb0239c528d16 Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Tue, 15 Sep 2009 11:57:12 -0700 Subject: [PATCH 7/8] silly typos and add disclaimer --- doc/manual/callbacks.texi | 4 ++++ doc/manual/tracing.texi | 30 ++++++++++++++++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/manual/callbacks.texi b/doc/manual/callbacks.texi index 36dd2293e..1abcedddc 100644 --- a/doc/manual/callbacks.texi +++ b/doc/manual/callbacks.texi @@ -267,6 +267,10 @@ implement the specific operator() method, }; @end verbatim +@emph{N.B. The previous code is not real ns-3 code. It is simplistic example +code used only to illustrate the concepts involved and to help you understand +the system more. Do not expect to find this code anywhere in the ns-3 tree} + Notice that there are two variables defined in the class above. The m_p variable is the object pointer and m_pmi is the variable containing the address of the function to execute. diff --git a/doc/manual/tracing.texi b/doc/manual/tracing.texi index d445dfc12..a8b72797a 100644 --- a/doc/manual/tracing.texi +++ b/doc/manual/tracing.texi @@ -112,7 +112,7 @@ functions. It will be useful to go walk a quick example just to reinforce what we've said. -@verbose +@verbatim #include ``ns3/object.h'' #include ``ns3/uinteger.h'' #include ``ns3/traced-value.h'' @@ -121,7 +121,7 @@ It will be useful to go walk a quick example just to reinforce what we've said. #include using namespace ns3; -@end verbose +@end verbatim The first thing to do is include the required files. As mentioned above, the trace system makes heavy use of the Object and Attribute systems. The first @@ -167,7 +167,7 @@ the @code{TracedValue} declaration. The @code{.AddTraceSource} provides the ``hooks'' used for connecting the trace source to the outside world. The @code{TracedValue} declaration provides the -infrastructure that overloads the operators above and drives the callback +infrastructure that overloads the operators mentioned above and drives the callback process. @verbatim @@ -201,9 +201,11 @@ The next step, the @code{TraceConnectWithoutContext}, forms the connection between the trace source and the trace sink. Notice the @code{MakeCallback} template function. Recall from the Callback section that this creates the specialized functor responsible for providing the overloaded @code{operator()} -used to ``fire'' the callback. The @code{TraceConnectWithoutContext}, takes -a string parameter that provides the name of the Attribute assigned to the -trace source. Let's ignore the bit about context for now. +used to ``fire'' the callback. The overloaded operators (++, --, etc.) will +use this @code{operator()} to actually invoke the callback. The +@code{TraceConnectWithoutContext}, takes a string parameter that provides +the name of the Attribute assigned to the trace source. Let's ignore the bit +about context for now since it is not important yet. Finally, the line, @@ -247,27 +249,27 @@ For example, one might find something that looks like the following in the syste @end verbatim This should look very familiar. It is the same thing as the previous example, -except that a static member function of @code{Config} is being called instead of -a method on @code{Object}, and instead of an @code{Attribute} name, a path is +except that a static member function of class @code{Config} is being called instead +of a method on @code{Object}; and instead of an @code{Attribute} name, a path is being provided. The first thing to do is to read the path backward. The last segment of the path must be an @code{Attribute} of an @code{Object}. In fact, if you had a pointer to -the @code{Object} that has the @code{Attribute} handy, you could write this just like -the previous example: +the @code{Object} that has the ``CongestionWindow'' @code{Attribute} handy (call it +@code{theObject}), you could write this just like the previous example: @verbatim void CwndTracer (uint32_t oldval, uint32_t newval) {} ... - object->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer)); + theObject->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer)); @end verbatim -And it turns out that @code{Config::ConnectWithoutContext} does exactly that. This -function takes a path that represents a chain of @code{Object} pointers and follows +It turns out that the code for @code{Config::ConnectWithoutContext} does exactly that. +This function takes a path that represents a chain of @code{Object} pointers and follows them until it gets to the end of the path and interprets the last segment as an -@code{Attribute} on the last object. +@code{Attribute} on the last object. Let's walk through what happens. The leading ``/'' character in the path refers to a so-called namespace. One of the predefined namespaces in the config system is ``NodeList'' which is a list of all of From 11b6f74f26c5da5923609c2a73cf896fccba87f9 Mon Sep 17 00:00:00 2001 From: Pavel Boyko Date: Wed, 16 Sep 2009 13:28:06 +0400 Subject: [PATCH 8/8] Build fix for g++ 4.0.4 ('... may be used uninitialized in this function') --- src/devices/mesh/dot11s/peer-management-protocol.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/mesh/dot11s/peer-management-protocol.cc b/src/devices/mesh/dot11s/peer-management-protocol.cc index fe144f0e5..cff61506a 100644 --- a/src/devices/mesh/dot11s/peer-management-protocol.cc +++ b/src/devices/mesh/dot11s/peer-management-protocol.cc @@ -241,7 +241,7 @@ PeerManagementProtocol::ReceivePeerLinkFrame (uint32_t interface, Mac48Address p Ptr peerLink = FindPeerLink (interface, peerAddress); if (peerManagementElement.SubtypeIsOpen ()) { - PmpReasonCode reasonCode; + PmpReasonCode reasonCode (REASON11S_RESERVED); bool reject = !(ShouldAcceptOpen (interface, peerAddress, reasonCode)); if (peerLink == 0) {