A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
hwmp-protocol-mac.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008,2009 IITP RAS
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Kirill Andreev <andreev@iitp.ru>
18 */
19
20#include "hwmp-protocol-mac.h"
21
22#include "dot11s-mac-header.h"
23#include "hwmp-tag.h"
24#include "ie-dot11s-perr.h"
25#include "ie-dot11s-prep.h"
26#include "ie-dot11s-preq.h"
27#include "ie-dot11s-rann.h"
28
29#include "ns3/log.h"
30#include "ns3/mesh-wifi-interface-mac.h"
31#include "ns3/mgt-action-headers.h"
32#include "ns3/nstime.h"
33#include "ns3/packet.h"
34#include "ns3/simulator.h"
35#include "ns3/wifi-mac-header.h"
36
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("HwmpProtocolMac");
41
42namespace dot11s
43{
44
46 : m_ifIndex(ifIndex),
47 m_protocol(protocol)
48{
49 NS_LOG_FUNCTION(this << ifIndex << protocol);
50}
51
53{
54}
55
56void
58{
59 NS_LOG_FUNCTION(this << parent);
60 m_parent = parent;
61}
62
63bool
65{
66 NS_LOG_FUNCTION(this << packet << header);
67 NS_ASSERT(header.IsData());
68
69 MeshHeader meshHdr;
70 HwmpTag tag;
71 if (packet->PeekPacketTag(tag))
72 {
73 NS_FATAL_ERROR("HWMP tag is not supposed to be received by network");
74 }
75
76 packet->RemoveHeader(meshHdr);
78 m_stats.rxDataBytes += packet->GetSize();
79
80 /// \todo address extension
81 Mac48Address destination;
82 Mac48Address source;
83 switch (meshHdr.GetAddressExt())
84 {
85 case 0:
86 source = header.GetAddr4();
87 destination = header.GetAddr3();
88 break;
89 default:
90 NS_FATAL_ERROR("6-address scheme is not yet supported and 4-address extension is not "
91 "supposed to be used for data frames.");
92 }
93 tag.SetSeqno(meshHdr.GetMeshSeqno());
94 tag.SetTtl(meshHdr.GetMeshTtl());
95 packet->AddPacketTag(tag);
96
97 if ((destination == Mac48Address::GetBroadcast()) &&
98 (m_protocol->DropDataFrame(meshHdr.GetMeshSeqno(), source)))
99 {
100 NS_LOG_DEBUG("Dropping frame; source " << source << " dest " << destination << " seqno "
101 << meshHdr.GetMeshSeqno());
102 return false;
103 }
104 return true;
105}
106
107bool
109{
110 NS_LOG_FUNCTION(this << packet << header);
111 m_stats.rxMgt++;
112 m_stats.rxMgtBytes += packet->GetSize();
113 WifiActionHeader actionHdr;
114 packet->RemoveHeader(actionHdr);
115 if (actionHdr.GetCategory() != WifiActionHeader::MESH)
116 {
117 return true;
118 }
120 // To determine header size here, we can rely on the knowledge that
121 // this is the last header to remove.
122 packet->RemoveHeader(elements, packet->GetSize());
123 std::vector<HwmpProtocol::FailedDestination> failedDestinations;
124 for (auto i = elements.Begin(); i != elements.End(); i++)
125 {
126 if ((*i)->ElementId() == IE_RANN)
127 {
128 NS_LOG_WARN("RANN is not supported!");
129 }
130 if ((*i)->ElementId() == IE_PREQ)
131 {
132 Ptr<IePreq> preq = DynamicCast<IePreq>(*i);
133 NS_ASSERT(preq);
134 m_stats.rxPreq++;
135 if (preq->GetOriginatorAddress() == m_protocol->GetAddress())
136 {
137 continue;
138 }
139 if (preq->GetTtl() == 0)
140 {
141 continue;
142 }
143 preq->DecrementTtl();
144 m_protocol->ReceivePreq(*preq,
145 header.GetAddr2(),
146 m_ifIndex,
147 header.GetAddr3(),
148 m_parent->GetLinkMetric(header.GetAddr2()));
149 }
150 if ((*i)->ElementId() == IE_PREP)
151 {
152 Ptr<IePrep> prep = DynamicCast<IePrep>(*i);
153 NS_ASSERT(prep);
154 m_stats.rxPrep++;
155 if (prep->GetTtl() == 0)
156 {
157 continue;
158 }
159 prep->DecrementTtl();
160 m_protocol->ReceivePrep(*prep,
161 header.GetAddr2(),
162 m_ifIndex,
163 header.GetAddr3(),
164 m_parent->GetLinkMetric(header.GetAddr2()));
165 }
166 if ((*i)->ElementId() == IE_PERR)
167 {
168 Ptr<IePerr> perr = DynamicCast<IePerr>(*i);
169 NS_ASSERT(perr);
170 m_stats.rxPerr++;
171 std::vector<HwmpProtocol::FailedDestination> destinations =
172 perr->GetAddressUnitVector();
173 for (auto i = destinations.begin(); i != destinations.end(); i++)
174 {
175 failedDestinations.push_back(*i);
176 }
177 }
178 }
179 if (!failedDestinations.empty())
180 {
181 m_protocol->ReceivePerr(failedDestinations,
182 header.GetAddr2(),
183 m_ifIndex,
184 header.GetAddr3());
185 }
186 NS_ASSERT(packet->GetSize() == 0);
187 return false;
188}
189
190bool
192{
193 NS_LOG_FUNCTION(this << packet << header);
194 if (header.IsData())
195 {
196 return ReceiveData(packet, header);
197 }
198 else
199 {
200 if (header.IsAction())
201 {
202 return ReceiveAction(packet, header);
203 }
204 else
205 {
206 return true; // don't care
207 }
208 }
209}
210
211bool
213 WifiMacHeader& header,
214 Mac48Address from,
215 Mac48Address to)
216{
217 NS_LOG_FUNCTION(this << packet << header << from << to);
218 if (!header.IsData())
219 {
220 return true;
221 }
222 HwmpTag tag;
223 bool tagExists = packet->RemovePacketTag(tag);
224 if (!tagExists)
225 {
226 NS_FATAL_ERROR("HWMP tag must exist at this point");
227 }
228 m_stats.txData++;
229 m_stats.txDataBytes += packet->GetSize();
230 MeshHeader meshHdr;
231 meshHdr.SetMeshSeqno(tag.GetSeqno());
232 meshHdr.SetMeshTtl(tag.GetTtl());
233 packet->AddHeader(meshHdr);
234 header.SetAddr1(tag.GetAddress());
236 return true;
237}
238
241{
242 WifiActionHeader actionHdr;
244 action.meshAction = WifiActionHeader::PATH_SELECTION;
245 actionHdr.SetAction(WifiActionHeader::MESH, action);
246 return actionHdr;
247}
248
249void
251{
252 NS_LOG_FUNCTION(this);
253 std::vector<IePreq> preq_vector;
254 preq_vector.push_back(preq);
255 SendPreqVector(preq_vector);
256}
257
258void
259HwmpProtocolMac::SendPreqVector(std::vector<IePreq> preq)
260{
261 NS_LOG_FUNCTION(this);
262 Ptr<Packet> packet = Create<Packet>();
264 for (auto i = preq.begin(); i != preq.end(); i++)
265 {
266 elements.AddInformationElement(Ptr<IePreq>(&(*i)));
267 }
268 packet->AddHeader(elements);
269 packet->AddHeader(GetWifiActionHeader());
270 // create 802.11 header:
271 WifiMacHeader hdr;
273 hdr.SetDsNotFrom();
274 hdr.SetDsNotTo();
275 hdr.SetAddr2(m_parent->GetAddress());
276 hdr.SetAddr3(m_protocol->GetAddress());
277 // Send Management frame
278 std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers(m_ifIndex);
279 for (auto i = receivers.begin(); i != receivers.end(); i++)
280 {
281 hdr.SetAddr1(*i);
282 m_stats.txPreq++;
283 m_stats.txMgt++;
284 m_stats.txMgtBytes += packet->GetSize();
285 m_parent->SendManagementFrame(packet, hdr);
286 }
287}
288
289void
291{
292 NS_LOG_FUNCTION(this << dst << originator_seqno << dst_seqno);
293 for (auto i = m_myPreq.begin(); i != m_myPreq.end(); i++)
294 {
295 if (i->IsFull())
296 {
297 continue;
298 }
299 NS_ASSERT(i->GetDestCount() > 0);
300 i->AddDestinationAddressElement(m_protocol->GetDoFlag(),
301 m_protocol->GetRfFlag(),
302 dst,
303 dst_seqno);
304 }
305 IePreq preq;
306 preq.SetHopcount(0);
307 preq.SetTTL(m_protocol->GetMaxTtl());
308 preq.SetPreqID(m_protocol->GetNextPreqId());
309 preq.SetOriginatorAddress(m_protocol->GetAddress());
310 preq.SetOriginatorSeqNumber(originator_seqno);
311 preq.SetLifetime(m_protocol->GetActivePathLifetime());
313 m_protocol->GetRfFlag(),
314 dst,
315 dst_seqno);
316 m_myPreq.push_back(preq);
317 SendMyPreq();
318}
319
320void
322{
323 NS_LOG_FUNCTION(this);
325 {
326 return;
327 }
328 if (m_myPreq.empty())
329 {
330 return;
331 }
332 // reschedule sending PREQ
335 Simulator::Schedule(m_protocol->GetPreqMinInterval(), &HwmpProtocolMac::SendMyPreq, this);
337 m_myPreq.clear();
338}
339
340void
342{
343 NS_LOG_FUNCTION(this << receiver);
344 // Create packet
345 Ptr<Packet> packet = Create<Packet>();
347 elements.AddInformationElement(Ptr<IePrep>(&prep));
348 packet->AddHeader(elements);
349 packet->AddHeader(GetWifiActionHeader());
350 // create 802.11 header:
351 WifiMacHeader hdr;
353 hdr.SetDsNotFrom();
354 hdr.SetDsNotTo();
355 hdr.SetAddr1(receiver);
356 hdr.SetAddr2(m_parent->GetAddress());
357 hdr.SetAddr3(m_protocol->GetAddress());
358 // Send Management frame
359 m_stats.txPrep++;
360 m_stats.txMgt++;
361 m_stats.txMgtBytes += packet->GetSize();
362 m_parent->SendManagementFrame(packet, hdr);
363}
364
365void
366HwmpProtocolMac::ForwardPerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
367 std::vector<Mac48Address> receivers)
368{
369 NS_LOG_FUNCTION(this);
370 Ptr<Packet> packet = Create<Packet>();
371 Ptr<IePerr> perr = Create<IePerr>();
373 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
374 {
375 if (!perr->IsFull())
376 {
377 perr->AddAddressUnit(*i);
378 }
379 else
380 {
381 elements.AddInformationElement(perr);
382 perr->ResetPerr();
383 }
384 }
385 if (perr->GetNumOfDest() > 0)
386 {
387 elements.AddInformationElement(perr);
388 }
389 packet->AddHeader(elements);
390 packet->AddHeader(GetWifiActionHeader());
391 // create 802.11 header:
392 WifiMacHeader hdr;
394 hdr.SetDsNotFrom();
395 hdr.SetDsNotTo();
396 hdr.SetAddr2(m_parent->GetAddress());
397 hdr.SetAddr3(m_protocol->GetAddress());
398 if (receivers.size() >= m_protocol->GetUnicastPerrThreshold())
399 {
400 receivers.clear();
401 receivers.push_back(Mac48Address::GetBroadcast());
402 }
403 // Send Management frame
404 for (auto i = receivers.begin(); i != receivers.end(); i++)
405 {
406 //
407 // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
408 // just fine.
409 //
410 Mac48Address address = *i;
411 hdr.SetAddr1(address);
412 m_stats.txPerr++;
413 m_stats.txMgt++;
414 m_stats.txMgtBytes += packet->GetSize();
415 m_parent->SendManagementFrame(packet, hdr);
416 }
417}
418
419void
420HwmpProtocolMac::InitiatePerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
421 std::vector<Mac48Address> receivers)
422{
423 NS_LOG_FUNCTION(this);
424 // All duplicates in PERR are checked here, and there is no reason to
425 // check it at any other place
426 {
427 for (auto i = receivers.begin(); i != receivers.end(); i++)
428 {
429 bool should_add = true;
430 for (auto j = m_myPerr.receivers.begin(); j != m_myPerr.receivers.end(); j++)
431 {
432 if ((*i) == (*j))
433 {
434 should_add = false;
435 }
436 }
437 if (should_add)
438 {
439 m_myPerr.receivers.push_back(*i);
440 NS_LOG_DEBUG("Initiate PERR: Adding receiver: " << (*i));
441 }
442 }
443 }
444 {
445 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
446 {
447 bool should_add = true;
448 for (auto j = m_myPerr.destinations.begin(); j != m_myPerr.destinations.end(); j++)
449 {
450 if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
451 {
452 should_add = false;
453 }
454 }
455 if (should_add)
456 {
457 m_myPerr.destinations.push_back(*i);
458 NS_LOG_DEBUG("Initiate PERR: Adding failed destination: " << (*i).destination);
459 }
460 }
461 }
462 SendMyPerr();
463}
464
465void
467{
468 NS_LOG_FUNCTION(this);
470 {
471 return;
472 }
474 Simulator::Schedule(m_protocol->GetPerrMinInterval(), &HwmpProtocolMac::SendMyPerr, this);
476 m_myPerr.destinations.clear();
477 m_myPerr.receivers.clear();
478}
479
482{
483 return m_parent->GetLinkMetric(peerAddress);
484}
485
486uint16_t
488{
489 return m_parent->GetFrequencyChannel();
490}
491
493 : txPreq(0),
494 rxPreq(0),
495 txPrep(0),
496 rxPrep(0),
497 txPerr(0),
498 rxPerr(0),
499 txMgt(0),
500 txMgtBytes(0),
501 rxMgt(0),
502 rxMgtBytes(0),
503 txData(0),
504 txDataBytes(0),
505 rxData(0),
506 rxDataBytes(0)
507{
508}
509
510void
512{
513 os << "<Statistics "
514 "txPreq= \""
515 << txPreq << "\"" << std::endl
516 << "txPrep=\"" << txPrep << "\"" << std::endl
517 << "txPerr=\"" << txPerr << "\"" << std::endl
518 << "rxPreq=\"" << rxPreq << "\"" << std::endl
519 << "rxPrep=\"" << rxPrep << "\"" << std::endl
520 << "rxPerr=\"" << rxPerr << "\"" << std::endl
521 << "txMgt=\"" << txMgt << "\"" << std::endl
522 << "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl
523 << "rxMgt=\"" << rxMgt << "\"" << std::endl
524 << "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl
525 << "txData=\"" << txData << "\"" << std::endl
526 << "txDataBytes=\"" << txDataBytes << "\"" << std::endl
527 << "rxData=\"" << rxData << "\"" << std::endl
528 << "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
529}
530
531void
532HwmpProtocolMac::Report(std::ostream& os) const
533{
534 os << "<HwmpProtocolMac" << std::endl
535 << "address =\"" << m_parent->GetAddress() << "\">" << std::endl;
536 m_stats.Print(os);
537 os << "</HwmpProtocolMac>" << std::endl;
538}
539
540void
542{
543 NS_LOG_FUNCTION(this);
545}
546
547int64_t
549{
550 return m_protocol->AssignStreams(stream);
551}
552
553} // namespace dot11s
554} // namespace ns3
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetBroadcast()
Iterator End()
Returns End of the vector.
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
Iterator Begin()
Returns Begin of the vector.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
CategoryValue GetCategory() const
Return the category value.
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr3() const
Return the address in the Address 3 field.
Mac48Address GetAddr4() const
Return the address in the Address 4 field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsAction() const
Return true if the header is an Action header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetQosMeshControlPresent()
Set the Mesh Control Present flag for the QoS header.
static WifiActionHeader GetWifiActionHeader()
void SendMyPreq()
Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
void SendPreq(IePreq preq)
Send PREQ function.
HwmpProtocolMac(uint32_t ifIndex, Ptr< HwmpProtocol > protocol)
Constructor.
void SetParent(Ptr< MeshWifiInterfaceMac > parent) override
Each plugin must be installed on an interface to work.
void SendPreqVector(std::vector< IePreq > preq)
Send PREQ function for vector of PREQ.
void SendPrep(IePrep prep, Mac48Address receiver)
Send PREP function.
void SendMyPerr()
Send PERR function.
uint16_t GetChannelId() const
Get the channel ID.
bool Receive(Ptr< Packet > packet, const WifiMacHeader &header) override
Process received frame.
void ForwardPerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Forward a path error.
Ptr< HwmpProtocol > m_protocol
protocol
bool ReceiveData(Ptr< Packet > packet, const WifiMacHeader &header)
Receive data frame.
Statistics m_stats
statistics
EventId m_preqTimer
Timer for PREQs.
void ResetStats()
Reset statistics.
uint32_t GetLinkMetric(Mac48Address peerAddress) const
bool ReceiveAction(Ptr< Packet > packet, const WifiMacHeader &header)
Receive action management frame.
void InitiatePerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
initiate my own path error
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
std::vector< IePreq > m_myPreq
container of PREQs
void Report(std::ostream &os) const
Report statistics.
bool UpdateOutcomingFrame(Ptr< Packet > packet, WifiMacHeader &header, Mac48Address from, Mac48Address to) override
Update frame before it will be forwarded down.
Ptr< MeshWifiInterfaceMac > m_parent
parent
void RequestDestination(Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno)
Request a destination.
Hwmp tag implements interaction between HWMP protocol and MeshWifiMac.
Definition: hwmp-tag.h:51
void SetTtl(uint8_t ttl)
Set the TTL value.
Definition: hwmp-tag.cc:55
uint32_t GetSeqno() const
Get the sequence number.
Definition: hwmp-tag.cc:85
void SetSeqno(uint32_t seqno)
Set sequence number.
Definition: hwmp-tag.cc:79
uint8_t GetTtl() const
Get the TTL value.
Definition: hwmp-tag.cc:61
Mac48Address GetAddress()
Get address from tag.
Definition: hwmp-tag.cc:49
See 7.3.2.97 of 802.11s draft 2.07.
See 7.3.2.96 of 802.11s draft 2.07.
void SetHopcount(uint8_t hopcount)
Set number of hops from originator to mesh STA transmitting this element.
void SetOriginatorSeqNumber(uint32_t originator_seq_number)
Set originator sequence number.
void SetTTL(uint8_t ttl)
Set remaining number of hops allowed for this element.
void SetOriginatorAddress(Mac48Address originator_address)
Set originator address value.
void SetPreqID(uint32_t id)
Set path discovery id field.
void AddDestinationAddressElement(bool doFlag, bool rfFlag, Mac48Address dest_address, uint32_t dest_seq_number)
Add a destination address unit: flags, destination and sequence number.
void SetLifetime(uint32_t lifetime)
Set lifetime in TUs for the forwarding information to be considered valid.
Mesh Control field, see Section 8.2.4.7.3 IEEE 802.11-2012.
void SetMeshSeqno(uint32_t seqno)
Set four-byte mesh sequence number.
uint32_t GetMeshSeqno() const
Get the four-byte mesh sequence number.
void SetMeshTtl(uint8_t TTL)
Set mesh TTL subfield corresponding to the remaining number of hops the MSDU/MMPDU is forwarded.
uint8_t GetAddressExt() const
Get Address Extension Mode.
uint8_t GetMeshTtl() const
Get mesh TTL function subfield value.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_MAC_MGT_ACTION
std::vector< HwmpProtocol::FailedDestination > destinations
destinations
std::vector< Mac48Address > receivers
receivers
uint32_t txMgtBytes
transmit management bytes
void Print(std::ostream &os) const
Print function.
uint32_t txDataBytes
transmit data bytes
uint32_t rxMgtBytes
receive management bytes
typedef for union of different ActionValues
#define IE_PREQ
#define IE_RANN
#define IE_PREP
#define IE_PERR