--- a/bindings/python/ns3_module_common.py Thu May 28 21:41:45 2009 -0700
+++ b/bindings/python/ns3_module_common.py Fri May 29 10:15:19 2009 +0400
@@ -9,6 +9,16 @@
module.add_class('Buffer')
## buffer.h: ns3::Buffer::Iterator [class]
module.add_class('Iterator', outer_class=root_module['ns3::Buffer'])
+ ## packet.h: ns3::ByteTagIterator [class]
+ module.add_class('ByteTagIterator')
+ ## packet.h: ns3::ByteTagIterator::Item [class]
+ module.add_class('Item', outer_class=root_module['ns3::ByteTagIterator'])
+ ## byte-tag-list.h: ns3::ByteTagList [class]
+ module.add_class('ByteTagList')
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator [class]
+ module.add_class('Iterator', outer_class=root_module['ns3::ByteTagList'])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item [struct]
+ module.add_class('Item', outer_class=root_module['ns3::ByteTagList::Iterator'])
## data-rate.h: ns3::DataRate [class]
module.add_class('DataRate')
## packet.h: ns3::Packet [class]
@@ -21,20 +31,18 @@
module.add_enum('', ['PAYLOAD', 'HEADER', 'TRAILER'], outer_class=root_module['ns3::PacketMetadata::Item'])
## packet-metadata.h: ns3::PacketMetadata::ItemIterator [class]
module.add_class('ItemIterator', outer_class=root_module['ns3::PacketMetadata'])
+ ## packet.h: ns3::PacketTagIterator [class]
+ module.add_class('PacketTagIterator')
+ ## packet.h: ns3::PacketTagIterator::Item [class]
+ module.add_class('Item', outer_class=root_module['ns3::PacketTagIterator'])
+ ## packet-tag-list.h: ns3::PacketTagList [class]
+ module.add_class('PacketTagList')
+ ## packet-tag-list.h: ns3::PacketTagList::TagData [struct]
+ module.add_class('TagData', outer_class=root_module['ns3::PacketTagList'])
## tag.h: ns3::Tag [class]
module.add_class('Tag', parent=root_module['ns3::ObjectBase'])
## tag-buffer.h: ns3::TagBuffer [class]
module.add_class('TagBuffer')
- ## packet.h: ns3::TagIterator [class]
- module.add_class('TagIterator')
- ## packet.h: ns3::TagIterator::Item [class]
- module.add_class('Item', outer_class=root_module['ns3::TagIterator'])
- ## tag-list.h: ns3::TagList [class]
- module.add_class('TagList')
- ## tag-list.h: ns3::TagList::Iterator [class]
- module.add_class('Iterator', outer_class=root_module['ns3::TagList'])
- ## tag-list.h: ns3::TagList::Iterator::Item [struct]
- module.add_class('Item', outer_class=root_module['ns3::TagList::Iterator'])
## chunk.h: ns3::Chunk [class]
module.add_class('Chunk', parent=root_module['ns3::ObjectBase'])
## data-rate.h: ns3::DataRateChecker [class]
@@ -107,18 +115,22 @@
def register_methods(root_module):
register_Ns3Buffer_methods(root_module, root_module['ns3::Buffer'])
register_Ns3BufferIterator_methods(root_module, root_module['ns3::Buffer::Iterator'])
+ register_Ns3ByteTagIterator_methods(root_module, root_module['ns3::ByteTagIterator'])
+ register_Ns3ByteTagIteratorItem_methods(root_module, root_module['ns3::ByteTagIterator::Item'])
+ register_Ns3ByteTagList_methods(root_module, root_module['ns3::ByteTagList'])
+ register_Ns3ByteTagListIterator_methods(root_module, root_module['ns3::ByteTagList::Iterator'])
+ register_Ns3ByteTagListIteratorItem_methods(root_module, root_module['ns3::ByteTagList::Iterator::Item'])
register_Ns3DataRate_methods(root_module, root_module['ns3::DataRate'])
register_Ns3Packet_methods(root_module, root_module['ns3::Packet'])
register_Ns3PacketMetadata_methods(root_module, root_module['ns3::PacketMetadata'])
register_Ns3PacketMetadataItem_methods(root_module, root_module['ns3::PacketMetadata::Item'])
register_Ns3PacketMetadataItemIterator_methods(root_module, root_module['ns3::PacketMetadata::ItemIterator'])
+ register_Ns3PacketTagIterator_methods(root_module, root_module['ns3::PacketTagIterator'])
+ register_Ns3PacketTagIteratorItem_methods(root_module, root_module['ns3::PacketTagIterator::Item'])
+ register_Ns3PacketTagList_methods(root_module, root_module['ns3::PacketTagList'])
+ register_Ns3PacketTagListTagData_methods(root_module, root_module['ns3::PacketTagList::TagData'])
register_Ns3Tag_methods(root_module, root_module['ns3::Tag'])
register_Ns3TagBuffer_methods(root_module, root_module['ns3::TagBuffer'])
- register_Ns3TagIterator_methods(root_module, root_module['ns3::TagIterator'])
- register_Ns3TagIteratorItem_methods(root_module, root_module['ns3::TagIterator::Item'])
- register_Ns3TagList_methods(root_module, root_module['ns3::TagList'])
- register_Ns3TagListIterator_methods(root_module, root_module['ns3::TagList::Iterator'])
- register_Ns3TagListIteratorItem_methods(root_module, root_module['ns3::TagList::Iterator::Item'])
register_Ns3Chunk_methods(root_module, root_module['ns3::Chunk'])
register_Ns3DataRateChecker_methods(root_module, root_module['ns3::DataRateChecker'])
register_Ns3DataRateValue_methods(root_module, root_module['ns3::DataRateValue'])
@@ -346,6 +358,113 @@
is_const=True)
return
+def register_Ns3ByteTagIterator_methods(root_module, cls):
+ ## packet.h: ns3::ByteTagIterator::ByteTagIterator(ns3::ByteTagIterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagIterator const &', 'arg0')])
+ ## packet.h: bool ns3::ByteTagIterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## packet.h: ns3::ByteTagIterator::Item ns3::ByteTagIterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::ByteTagIterator::Item',
+ [])
+ return
+
+def register_Ns3ByteTagIteratorItem_methods(root_module, cls):
+ ## packet.h: ns3::ByteTagIterator::Item::Item(ns3::ByteTagIterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagIterator::Item const &', 'arg0')])
+ ## packet.h: ns3::TypeId ns3::ByteTagIterator::Item::GetTypeId() const [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_const=True)
+ ## packet.h: uint32_t ns3::ByteTagIterator::Item::GetStart() const [member function]
+ cls.add_method('GetStart',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## packet.h: uint32_t ns3::ByteTagIterator::Item::GetEnd() const [member function]
+ cls.add_method('GetEnd',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## packet.h: void ns3::ByteTagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
+ cls.add_method('GetTag',
+ 'void',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ return
+
+def register_Ns3ByteTagList_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::ByteTagList() [constructor]
+ cls.add_constructor([])
+ ## byte-tag-list.h: ns3::ByteTagList::ByteTagList(ns3::ByteTagList const & o) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList const &', 'o')])
+ ## byte-tag-list.h: ns3::TagBuffer ns3::ByteTagList::Add(ns3::TypeId tid, uint32_t bufferSize, int32_t start, int32_t end) [member function]
+ cls.add_method('Add',
+ 'ns3::TagBuffer',
+ [param('ns3::TypeId', 'tid'), param('uint32_t', 'bufferSize'), param('int32_t', 'start'), param('int32_t', 'end')])
+ ## byte-tag-list.h: void ns3::ByteTagList::Add(ns3::ByteTagList const & o) [member function]
+ cls.add_method('Add',
+ 'void',
+ [param('ns3::ByteTagList const &', 'o')])
+ ## byte-tag-list.h: void ns3::ByteTagList::RemoveAll() [member function]
+ cls.add_method('RemoveAll',
+ 'void',
+ [])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator ns3::ByteTagList::Begin(int32_t offsetStart, int32_t offsetEnd) const [member function]
+ cls.add_method('Begin',
+ 'ns3::ByteTagList::Iterator',
+ [param('int32_t', 'offsetStart'), param('int32_t', 'offsetEnd')],
+ is_const=True)
+ ## byte-tag-list.h: void ns3::ByteTagList::AddAtEnd(int32_t adjustment, int32_t appendOffset) [member function]
+ cls.add_method('AddAtEnd',
+ 'void',
+ [param('int32_t', 'adjustment'), param('int32_t', 'appendOffset')])
+ ## byte-tag-list.h: void ns3::ByteTagList::AddAtStart(int32_t adjustment, int32_t prependOffset) [member function]
+ cls.add_method('AddAtStart',
+ 'void',
+ [param('int32_t', 'adjustment'), param('int32_t', 'prependOffset')])
+ return
+
+def register_Ns3ByteTagListIterator_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Iterator(ns3::ByteTagList::Iterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList::Iterator const &', 'arg0')])
+ ## byte-tag-list.h: bool ns3::ByteTagList::Iterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item ns3::ByteTagList::Iterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::ByteTagList::Iterator::Item',
+ [])
+ ## byte-tag-list.h: uint32_t ns3::ByteTagList::Iterator::GetOffsetStart() const [member function]
+ cls.add_method('GetOffsetStart',
+ 'uint32_t',
+ [],
+ is_const=True)
+ return
+
+def register_Ns3ByteTagListIteratorItem_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::tid [variable]
+ cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::size [variable]
+ cls.add_instance_attribute('size', 'uint32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::start [variable]
+ cls.add_instance_attribute('start', 'int32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::end [variable]
+ cls.add_instance_attribute('end', 'int32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::buf [variable]
+ cls.add_instance_attribute('buf', 'ns3::TagBuffer', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::Item(ns3::ByteTagList::Iterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList::Iterator::Item const &', 'arg0')])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::Item(ns3::TagBuffer buf) [constructor]
+ cls.add_constructor([param('ns3::TagBuffer', 'buf')])
+ return
+
def register_Ns3DataRate_methods(root_module, cls):
cls.add_output_stream_operator()
cls.add_binary_comparison_operator('!=')
@@ -388,19 +507,24 @@
cls.add_method('AddAtEnd',
'void',
[param('ns3::Ptr< ns3::Packet const >', 'packet')])
+ ## packet.h: void ns3::Packet::AddByteTag(ns3::Tag const & tag) const [member function]
+ cls.add_method('AddByteTag',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
## packet.h: void ns3::Packet::AddHeader(ns3::Header const & header) [member function]
cls.add_method('AddHeader',
'void',
[param('ns3::Header const &', 'header')])
+ ## packet.h: void ns3::Packet::AddPacketTag(ns3::Tag const & tag) const [member function]
+ cls.add_method('AddPacketTag',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
## packet.h: void ns3::Packet::AddPaddingAtEnd(uint32_t size) [member function]
cls.add_method('AddPaddingAtEnd',
'void',
[param('uint32_t', 'size')])
- ## packet.h: void ns3::Packet::AddTag(ns3::Tag const & tag) const [member function]
- cls.add_method('AddTag',
- 'void',
- [param('ns3::Tag const &', 'tag')],
- is_const=True)
## packet.h: void ns3::Packet::AddTrailer(ns3::Trailer const & trailer) [member function]
cls.add_method('AddTrailer',
'void',
@@ -439,21 +563,26 @@
'void',
[],
is_static=True)
- ## packet.h: bool ns3::Packet::FindFirstMatchingTag(ns3::Tag & tag) const [member function]
- cls.add_method('FindFirstMatchingTag',
+ ## packet.h: bool ns3::Packet::FindFirstMatchingByteTag(ns3::Tag & tag) const [member function]
+ cls.add_method('FindFirstMatchingByteTag',
'bool',
[param('ns3::Tag &', 'tag')],
is_const=True)
+ ## packet.h: ns3::ByteTagIterator ns3::Packet::GetByteTagIterator() const [member function]
+ cls.add_method('GetByteTagIterator',
+ 'ns3::ByteTagIterator',
+ [],
+ is_const=True)
+ ## packet.h: ns3::PacketTagIterator ns3::Packet::GetPacketTagIterator() const [member function]
+ cls.add_method('GetPacketTagIterator',
+ 'ns3::PacketTagIterator',
+ [],
+ is_const=True)
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_const=True)
- ## packet.h: ns3::TagIterator ns3::Packet::GetTagIterator() const [member function]
- cls.add_method('GetTagIterator',
- 'ns3::TagIterator',
- [],
- is_const=True)
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
@@ -469,6 +598,11 @@
'uint32_t',
[param('ns3::Header &', 'header')],
is_const=True)
+ ## packet.h: bool ns3::Packet::PeekPacketTag(ns3::Tag & tag) const [member function]
+ cls.add_method('PeekPacketTag',
+ 'bool',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
## packet.h: uint32_t ns3::Packet::PeekTrailer(ns3::Trailer & trailer) [member function]
cls.add_method('PeekTrailer',
'uint32_t',
@@ -478,13 +612,22 @@
'void',
[param('std::ostream &', 'os')],
is_const=True)
- ## packet.h: void ns3::Packet::PrintTags(std::ostream & os) const [member function]
- cls.add_method('PrintTags',
+ ## packet.h: void ns3::Packet::PrintByteTags(std::ostream & os) const [member function]
+ cls.add_method('PrintByteTags',
'void',
[param('std::ostream &', 'os')],
is_const=True)
- ## packet.h: void ns3::Packet::RemoveAllTags() [member function]
- cls.add_method('RemoveAllTags',
+ ## packet.h: void ns3::Packet::PrintPacketTags(std::ostream & os) const [member function]
+ cls.add_method('PrintPacketTags',
+ 'void',
+ [param('std::ostream &', 'os')],
+ is_const=True)
+ ## packet.h: void ns3::Packet::RemoveAllByteTags() [member function]
+ cls.add_method('RemoveAllByteTags',
+ 'void',
+ [])
+ ## packet.h: void ns3::Packet::RemoveAllPacketTags() [member function]
+ cls.add_method('RemoveAllPacketTags',
'void',
[])
## packet.h: void ns3::Packet::RemoveAtEnd(uint32_t size) [member function]
@@ -499,6 +642,10 @@
cls.add_method('RemoveHeader',
'uint32_t',
[param('ns3::Header &', 'header')])
+ ## packet.h: bool ns3::Packet::RemovePacketTag(ns3::Tag & tag) [member function]
+ cls.add_method('RemovePacketTag',
+ 'bool',
+ [param('ns3::Tag &', 'tag')])
## packet.h: uint32_t ns3::Packet::RemoveTrailer(ns3::Trailer & trailer) [member function]
cls.add_method('RemoveTrailer',
'uint32_t',
@@ -623,6 +770,80 @@
[])
return
+def register_Ns3PacketTagIterator_methods(root_module, cls):
+ ## packet.h: ns3::PacketTagIterator::PacketTagIterator(ns3::PacketTagIterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagIterator const &', 'arg0')])
+ ## packet.h: bool ns3::PacketTagIterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## packet.h: ns3::PacketTagIterator::Item ns3::PacketTagIterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::PacketTagIterator::Item',
+ [])
+ return
+
+def register_Ns3PacketTagIteratorItem_methods(root_module, cls):
+ ## packet.h: ns3::PacketTagIterator::Item::Item(ns3::PacketTagIterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagIterator::Item const &', 'arg0')])
+ ## packet.h: ns3::TypeId ns3::PacketTagIterator::Item::GetTypeId() const [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_const=True)
+ ## packet.h: void ns3::PacketTagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
+ cls.add_method('GetTag',
+ 'void',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ return
+
+def register_Ns3PacketTagList_methods(root_module, cls):
+ ## packet-tag-list.h: ns3::PacketTagList::PacketTagList() [constructor]
+ cls.add_constructor([])
+ ## packet-tag-list.h: ns3::PacketTagList::PacketTagList(ns3::PacketTagList const & o) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagList const &', 'o')])
+ ## packet-tag-list.h: void ns3::PacketTagList::Add(ns3::Tag const & tag) const [member function]
+ cls.add_method('Add',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
+ ## packet-tag-list.h: bool ns3::PacketTagList::Remove(ns3::Tag & tag) [member function]
+ cls.add_method('Remove',
+ 'bool',
+ [param('ns3::Tag &', 'tag')])
+ ## packet-tag-list.h: bool ns3::PacketTagList::Peek(ns3::Tag & tag) const [member function]
+ cls.add_method('Peek',
+ 'bool',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ ## packet-tag-list.h: void ns3::PacketTagList::RemoveAll() [member function]
+ cls.add_method('RemoveAll',
+ 'void',
+ [])
+ ## packet-tag-list.h: ns3::PacketTagList::TagData const * ns3::PacketTagList::Head() const [member function]
+ cls.add_method('Head',
+ 'ns3::PacketTagList::TagData const *',
+ [],
+ is_const=True)
+ return
+
+def register_Ns3PacketTagListTagData_methods(root_module, cls):
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::data [variable]
+ cls.add_instance_attribute('data', 'uint8_t [ 20 ]', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::next [variable]
+ cls.add_instance_attribute('next', 'ns3::PacketTagList::TagData *', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::tid [variable]
+ cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::count [variable]
+ cls.add_instance_attribute('count', 'uint32_t', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::TagData(ns3::PacketTagList::TagData const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagList::TagData const &', 'arg0')])
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::TagData() [constructor]
+ cls.add_constructor([])
+ return
+
def register_Ns3Tag_methods(root_module, cls):
## tag.h: ns3::Tag::Tag(ns3::Tag const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Tag const &', 'arg0')])
@@ -718,113 +939,6 @@
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
return
-def register_Ns3TagIterator_methods(root_module, cls):
- ## packet.h: ns3::TagIterator::TagIterator(ns3::TagIterator const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagIterator const &', 'arg0')])
- ## packet.h: bool ns3::TagIterator::HasNext() const [member function]
- cls.add_method('HasNext',
- 'bool',
- [],
- is_const=True)
- ## packet.h: ns3::TagIterator::Item ns3::TagIterator::Next() [member function]
- cls.add_method('Next',
- 'ns3::TagIterator::Item',
- [])
- return
-
-def register_Ns3TagIteratorItem_methods(root_module, cls):
- ## packet.h: ns3::TagIterator::Item::Item(ns3::TagIterator::Item const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagIterator::Item const &', 'arg0')])
- ## packet.h: ns3::TypeId ns3::TagIterator::Item::GetTypeId() const [member function]
- cls.add_method('GetTypeId',
- 'ns3::TypeId',
- [],
- is_const=True)
- ## packet.h: uint32_t ns3::TagIterator::Item::GetStart() const [member function]
- cls.add_method('GetStart',
- 'uint32_t',
- [],
- is_const=True)
- ## packet.h: uint32_t ns3::TagIterator::Item::GetEnd() const [member function]
- cls.add_method('GetEnd',
- 'uint32_t',
- [],
- is_const=True)
- ## packet.h: void ns3::TagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
- cls.add_method('GetTag',
- 'void',
- [param('ns3::Tag &', 'tag')],
- is_const=True)
- return
-
-def register_Ns3TagList_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::TagList() [constructor]
- cls.add_constructor([])
- ## tag-list.h: ns3::TagList::TagList(ns3::TagList const & o) [copy constructor]
- cls.add_constructor([param('ns3::TagList const &', 'o')])
- ## tag-list.h: ns3::TagBuffer ns3::TagList::Add(ns3::TypeId tid, uint32_t bufferSize, int32_t start, int32_t end) [member function]
- cls.add_method('Add',
- 'ns3::TagBuffer',
- [param('ns3::TypeId', 'tid'), param('uint32_t', 'bufferSize'), param('int32_t', 'start'), param('int32_t', 'end')])
- ## tag-list.h: void ns3::TagList::Add(ns3::TagList const & o) [member function]
- cls.add_method('Add',
- 'void',
- [param('ns3::TagList const &', 'o')])
- ## tag-list.h: void ns3::TagList::RemoveAll() [member function]
- cls.add_method('RemoveAll',
- 'void',
- [])
- ## tag-list.h: ns3::TagList::Iterator ns3::TagList::Begin(int32_t offsetStart, int32_t offsetEnd) const [member function]
- cls.add_method('Begin',
- 'ns3::TagList::Iterator',
- [param('int32_t', 'offsetStart'), param('int32_t', 'offsetEnd')],
- is_const=True)
- ## tag-list.h: void ns3::TagList::AddAtEnd(int32_t adjustment, int32_t appendOffset) [member function]
- cls.add_method('AddAtEnd',
- 'void',
- [param('int32_t', 'adjustment'), param('int32_t', 'appendOffset')])
- ## tag-list.h: void ns3::TagList::AddAtStart(int32_t adjustment, int32_t prependOffset) [member function]
- cls.add_method('AddAtStart',
- 'void',
- [param('int32_t', 'adjustment'), param('int32_t', 'prependOffset')])
- return
-
-def register_Ns3TagListIterator_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::Iterator::Iterator(ns3::TagList::Iterator const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagList::Iterator const &', 'arg0')])
- ## tag-list.h: bool ns3::TagList::Iterator::HasNext() const [member function]
- cls.add_method('HasNext',
- 'bool',
- [],
- is_const=True)
- ## tag-list.h: ns3::TagList::Iterator::Item ns3::TagList::Iterator::Next() [member function]
- cls.add_method('Next',
- 'ns3::TagList::Iterator::Item',
- [])
- ## tag-list.h: uint32_t ns3::TagList::Iterator::GetOffsetStart() const [member function]
- cls.add_method('GetOffsetStart',
- 'uint32_t',
- [],
- is_const=True)
- return
-
-def register_Ns3TagListIteratorItem_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::Iterator::Item::tid [variable]
- cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::size [variable]
- cls.add_instance_attribute('size', 'uint32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::start [variable]
- cls.add_instance_attribute('start', 'int32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::end [variable]
- cls.add_instance_attribute('end', 'int32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::buf [variable]
- cls.add_instance_attribute('buf', 'ns3::TagBuffer', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::Item(ns3::TagList::Iterator::Item const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagList::Iterator::Item const &', 'arg0')])
- ## tag-list.h: ns3::TagList::Iterator::Item::Item(ns3::TagBuffer buf) [constructor]
- cls.add_constructor([param('ns3::TagBuffer', 'buf')])
- return
-
def register_Ns3Chunk_methods(root_module, cls):
## chunk.h: ns3::Chunk::Chunk(ns3::Chunk const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Chunk const &', 'arg0')])
--- a/doc/doxygen.conf Thu May 28 21:41:45 2009 -0700
+++ b/doc/doxygen.conf Fri May 29 10:15:19 2009 +0400
@@ -300,7 +300,7 @@
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
-HIDE_UNDOC_CLASSES = YES
+HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mesh.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/global-routing-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/mesh-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/dot11s-helper.h"
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+using namespace ns3;
+using namespace dot11s;
+
+NS_LOG_COMPONENT_DEFINE ("TestMeshScript");
+class MeshTest
+{
+ public:
+ /// Init test
+ MeshTest ();
+ /// Configure test from command line arguments
+ void Configure (int argc, char ** argv);
+ /// Run test
+ int Run ();
+ private:
+ int xSize;
+ int ySize;
+ double step;
+ double randomStart;
+ double totalTime;
+ double packetInterval;
+ uint16_t packetSize;
+ uint32_t nIfaces;
+ bool chan;
+ bool pcap;
+ uint64_t seed;
+ /// List of network nodes
+ NodeContainer nodes;
+ /// List of all mesh point devices
+ NetDeviceContainer meshDevices;
+ //Addresses of interfaces:
+ Ipv4InterfaceContainer interfaces;
+ //InternetStackHelper stack;
+ //Ipv4AddressHelper address;
+ private:
+ /// Create nodes and setup theis mobility
+ void CreateNodes ();
+ /// Install internet stack on nodes
+ void InstallInternetStack ();
+ /// Install applications
+ void InstallApplication ();
+ /// Print mesh devices diagnostics
+ void Report ();
+};
+MeshTest::MeshTest () :
+ xSize (3),
+ ySize (3),
+ step (100.0),
+ randomStart (0.1),
+ totalTime (100.0),
+ packetInterval (0.1),
+ packetSize (1024),
+ nIfaces (1),
+ chan (true),
+ pcap (false),
+ seed (1)
+{
+}
+void
+MeshTest::Configure (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.AddValue ("x-size", "Number of nodes in a row grid. [6]", xSize);
+ cmd.AddValue ("y-size", "Number of rows in a grid. [6]", ySize);
+ cmd.AddValue ("step", "Size of edge in our grid, meters. [100 m]", step);
+ cmd.AddValue ("start", "Maximum random start delay, seconds. [0.1 s]", randomStart);
+ cmd.AddValue ("time", "Simulation time, seconds [100 s]", totalTime);
+ cmd.AddValue ("packet-interval", "Interval between packets, seconds [0.001 s]", packetInterval);
+ cmd.AddValue ("packet-size", "Size of packets", packetSize);
+ cmd.AddValue ("interfaces", "Number of radio interfaces used by each mesh point. [1]", nIfaces);
+ cmd.AddValue ("channels", "Use different frequency channels for different interfaces. [0]", chan);
+ cmd.AddValue ("pcap", "Enable PCAP traces on interfaces. [0]", pcap);
+ cmd.AddValue ("seed", "Seed value", seed);
+
+ cmd.Parse (argc, argv);
+ NS_LOG_DEBUG ("Grid:" << xSize << "*" << ySize);
+ NS_LOG_DEBUG ("Simulation time: " << totalTime << " s");
+ SeedManager::SetSeed(seed);
+}
+void
+MeshTest::CreateNodes ()
+{
+ nodes.Create (ySize*xSize);
+ // Setting channel
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ wifiPhy.SetChannel (wifiChannel.Create ());
+ // Install mesh point devices & protocols
+ MeshWifiHelper mesh;
+ mesh.SetSpreadInterfaceChannels (chan);
+ std::vector<uint32_t> roots;
+ //roots.push_back(xSize-1);
+ //roots.push_back(xSize*ySize-xSize);
+ meshDevices = mesh.Install (wifiPhy, nodes, roots, nIfaces);
+ // Setup mobility
+ MobilityHelper mobility;
+ mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+ "MinX", DoubleValue (0.0),
+ "MinY", DoubleValue (0.0),
+ "DeltaX", DoubleValue (step),
+ "DeltaY", DoubleValue (step),
+ "GridWidth", UintegerValue (xSize),
+ "LayoutType", StringValue ("RowFirst"));
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (nodes);
+ if (pcap)
+ wifiPhy.EnablePcapAll (std::string ("mp-"));
+}
+void
+MeshTest::InstallInternetStack ()
+{
+ InternetStackHelper stack;
+ stack.Install (nodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ interfaces = address.Assign (meshDevices);
+}
+void
+MeshTest::InstallApplication ()
+{
+ UdpEchoServerHelper echoServer (9);
+ ApplicationContainer serverApps = echoServer.Install (nodes.Get (0));
+ serverApps.Start (Seconds (0.0));
+ serverApps.Stop (Seconds (totalTime));
+ UdpEchoClientHelper echoClient (interfaces.GetAddress (0), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue ((uint32_t)(totalTime*(1/packetInterval))));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (packetInterval)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (packetSize));
+ ApplicationContainer clientApps = echoClient.Install (nodes.Get (xSize*ySize-1));
+ clientApps.Start (Seconds (0.0));
+ clientApps.Stop (Seconds (totalTime));
+}
+int
+MeshTest::Run ()
+{
+ CreateNodes ();
+ InstallInternetStack ();
+ InstallApplication ();
+ Simulator::Schedule (Seconds(totalTime), & MeshTest::Report, this);
+ Simulator::Stop (Seconds (totalTime));
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+}
+void
+MeshTest::Report ()
+{
+ NS_LOG_UNCOND("Report is here:");
+ unsigned n (0);
+ for (NetDeviceContainer::Iterator i = meshDevices.Begin (); i != meshDevices.End (); ++i, ++n)
+ {
+ std::ostringstream os;
+ os << "mp-report-" << n << ".xml";
+ std::cerr << "Printing mesh point device #" << n << " diagnostics to " << os.str () << "\n";
+ std::ofstream of;
+ of.open (os.str().c_str());
+ if (! of.is_open ())
+ {
+ std::cerr << "Error: Can't open file " << os.str() << "\n";
+ return;
+ }
+ MeshWifiHelper::Report (*i, of);
+ of.close ();
+ }
+}
+int
+main (int argc, char *argv[])
+{
+ MeshTest t;
+ t.Configure (argc, argv);
+ return t.Run();
+}
--- a/examples/stats/wifi-example-apps.cc Thu May 28 21:41:45 2009 -0700
+++ b/examples/stats/wifi-example-apps.cc Fri May 29 10:15:19 2009 +0400
@@ -131,7 +131,7 @@
TimestampTag timestamp;
timestamp.SetTimestamp(Simulator::Now());
- packet->AddTag(timestamp);
+ packet->AddByteTag (timestamp);
// Could connect the socket since the address never changes; using SendTo
// here simply because all of the standard apps do not.
@@ -250,7 +250,7 @@
}
TimestampTag timestamp;
- packet->FindFirstMatchingTag(timestamp);
+ packet->FindFirstMatchingByteTag(timestamp);
Time tx = timestamp.GetTimestamp();
if (m_delay != 0) {
--- a/examples/wscript Thu May 28 21:41:45 2009 -0700
+++ b/examples/wscript Fri May 29 10:15:19 2009 +0400
@@ -124,6 +124,10 @@
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'wifi-ap.cc'
+ obj = bld.create_ns3_program('mesh',
+ ['core', 'simulator', 'mobility', 'wifi'])
+ obj.source = 'mesh.cc'
+
bld.add_subdirs('stats')
obj = bld.create_ns3_program('wifi-wired-bridging',
--- a/samples/main-packet-tag.cc Thu May 28 21:41:45 2009 -0700
+++ b/samples/main-packet-tag.cc Fri May 29 10:15:19 2009 +0400
@@ -101,19 +101,19 @@
// store the tag in a packet.
Ptr<Packet> p = Create<Packet> (100);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
// create a copy of the packet
Ptr<Packet> aCopy = p->Copy ();
// read the tag from the packet copy
MyTag tagCopy;
- p->FindFirstMatchingTag (tagCopy);
+ p->PeekPacketTag (tagCopy);
// the copy and the original are the same !
NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
- aCopy->PrintTags (std::cout);
+ aCopy->PrintPacketTags (std::cout);
std::cout << std::endl;
return 0;
--- a/src/applications/udp-echo/udp-echo-client.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/applications/udp-echo/udp-echo-client.cc Fri May 29 10:15:19 2009 +0400
@@ -90,6 +90,7 @@
UdpEchoClient::DoDispose (void)
{
NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_UNCOND("TOTAL SENT:"<<m_sent);
Application::DoDispose ();
}
--- a/src/applications/udp-echo/udp-echo-server.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/applications/udp-echo/udp-echo-server.cc Fri May 29 10:15:19 2009 +0400
@@ -52,11 +52,13 @@
UdpEchoServer::UdpEchoServer ()
{
NS_LOG_FUNCTION_NOARGS ();
+ m_received = 0;
}
UdpEchoServer::~UdpEchoServer()
{
NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_UNCOND("Total received:"<<m_received);
m_socket = 0;
}
@@ -118,10 +120,11 @@
if (InetSocketAddress::IsMatchingType (from))
{
InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+ m_received ++;
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
address.GetIpv4());
- packet->RemoveAllTags ();
+ packet->RemoveAllPacketTags ();
NS_LOG_LOGIC ("Echoing packet");
socket->SendTo (packet, 0, from);
--- a/src/applications/udp-echo/udp-echo-server.h Thu May 28 21:41:45 2009 -0700
+++ b/src/applications/udp-echo/udp-echo-server.h Fri May 29 10:15:19 2009 +0400
@@ -60,6 +60,7 @@
uint16_t m_port;
Ptr<Socket> m_socket;
Address m_local;
+ uint32_t m_received;
};
} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/byte-tag-list.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,421 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "byte-tag-list.h"
+#include "ns3/log.h"
+#include <vector>
+#include <string.h>
+
+NS_LOG_COMPONENT_DEFINE ("ByteTagList");
+
+#define USE_FREE_LIST 1
+#define FREE_LIST_SIZE 1000
+#define OFFSET_MAX (2147483647)
+
+namespace ns3 {
+
+struct ByteTagListData {
+ uint32_t size;
+ uint32_t count;
+ uint32_t dirty;
+ uint8_t data[4];
+};
+
+#ifdef USE_FREE_LIST
+static class ByteTagListDataFreeList : public std::vector<struct ByteTagListData *>
+{
+public:
+ ~ByteTagListDataFreeList ();
+} g_freeList;
+static uint32_t g_maxSize = 0;
+
+ByteTagListDataFreeList::~ByteTagListDataFreeList ()
+{
+ for (ByteTagListDataFreeList::iterator i = begin ();
+ i != end (); i++)
+ {
+ uint8_t *buffer = (uint8_t *)(*i);
+ delete [] buffer;
+ }
+}
+#endif /* USE_FREE_LIST */
+
+ByteTagList::Iterator::Item::Item (TagBuffer buf_)
+ : buf (buf_)
+{}
+
+bool
+ByteTagList::Iterator::HasNext (void) const
+{
+ return m_current < m_end;
+}
+struct ByteTagList::Iterator::Item
+ByteTagList::Iterator::Next (void)
+{
+ NS_ASSERT (HasNext ());
+ struct Item item = Item (TagBuffer (m_current+16, m_end));
+ item.tid.SetUid (m_nextTid);
+ item.size = m_nextSize;
+ item.start = std::max (m_nextStart, m_offsetStart);
+ item.end = std::min (m_nextEnd, m_offsetEnd);
+ m_current += 4 + 4 + 4 + 4 + item.size;
+ item.buf.TrimAtEnd (m_end - m_current);
+ PrepareForNext ();
+ return item;
+}
+void
+ByteTagList::Iterator::PrepareForNext (void)
+{
+ while (m_current < m_end)
+ {
+ TagBuffer buf = TagBuffer (m_current, m_end);
+ m_nextTid = buf.ReadU32 ();
+ m_nextSize = buf.ReadU32 ();
+ m_nextStart = buf.ReadU32 ();
+ m_nextEnd = buf.ReadU32 ();
+ if (m_nextStart >= m_offsetEnd || m_nextEnd <= m_offsetStart)
+ {
+ m_current += 4 + 4 + 4 + 4 + m_nextSize;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+ByteTagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
+ : m_current (start),
+ m_end (end),
+ m_offsetStart (offsetStart),
+ m_offsetEnd (offsetEnd)
+{
+ PrepareForNext ();
+}
+
+uint32_t
+ByteTagList::Iterator::GetOffsetStart (void) const
+{
+ return m_offsetStart;
+}
+
+
+ByteTagList::ByteTagList ()
+ : m_used (0),
+ m_data (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+ByteTagList::ByteTagList (const ByteTagList &o)
+ : m_used (o.m_used),
+ m_data (o.m_data)
+{
+ NS_LOG_FUNCTION (this << &o);
+ if (m_data != 0)
+ {
+ m_data->count++;
+ }
+}
+ByteTagList &
+ByteTagList::operator = (const ByteTagList &o)
+{
+ NS_LOG_FUNCTION (this << &o);
+ if (this == &o)
+ {
+ return *this;
+ }
+
+ Deallocate (m_data);
+ m_data = o.m_data;
+ m_used = o.m_used;
+ if (m_data != 0)
+ {
+ m_data->count++;
+ }
+ return *this;
+}
+ByteTagList::~ByteTagList ()
+{
+ NS_LOG_FUNCTION (this);
+ Deallocate (m_data);
+ m_data = 0;
+ m_used = 0;
+}
+
+TagBuffer
+ByteTagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
+{
+ NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
+ uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
+ NS_ASSERT (m_used <= spaceNeeded);
+ if (m_data == 0)
+ {
+ m_data = Allocate (spaceNeeded);
+ m_used = 0;
+ }
+ else if (m_data->size < spaceNeeded ||
+ (m_data->count != 1 && m_data->dirty != m_used))
+ {
+ struct ByteTagListData *newData = Allocate (spaceNeeded);
+ memcpy (&newData->data, &m_data->data, m_used);
+ Deallocate (m_data);
+ m_data = newData;
+ }
+ TagBuffer tag = TagBuffer (&m_data->data[m_used],
+ &m_data->data[spaceNeeded]);
+ tag.WriteU32 (tid.GetUid ());
+ tag.WriteU32 (bufferSize);
+ tag.WriteU32 (start);
+ tag.WriteU32 (end);
+ m_used = spaceNeeded;
+ m_data->dirty = m_used;
+ return tag;
+}
+
+void
+ByteTagList::Add (const ByteTagList &o)
+{
+ NS_LOG_FUNCTION (this << &o);
+ ByteTagList::Iterator i = o.BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+}
+
+void
+ByteTagList::RemoveAll (void)
+{
+ NS_LOG_FUNCTION (this);
+ Deallocate (m_data);
+ m_data = 0;
+ m_used = 0;
+}
+
+ByteTagList::Iterator
+ByteTagList::BeginAll (void) const
+{
+ NS_LOG_FUNCTION (this);
+ // I am not totally sure but I might need to use
+ // INT32_MIN instead of zero below.
+ return Begin (0, OFFSET_MAX);
+}
+
+ByteTagList::Iterator
+ByteTagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
+{
+ NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
+ if (m_data == 0)
+ {
+ return Iterator (0, 0, offsetStart, offsetEnd);
+ }
+ else
+ {
+ return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
+ }
+}
+
+bool
+ByteTagList::IsDirtyAtEnd (int32_t appendOffset)
+{
+ NS_LOG_FUNCTION (this << appendOffset);
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ if (item.end > appendOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+ByteTagList::IsDirtyAtStart (int32_t prependOffset)
+{
+ NS_LOG_FUNCTION (this << prependOffset);
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ if (item.start < prependOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+ByteTagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
+{
+ NS_LOG_FUNCTION (this << adjustment << appendOffset);
+ if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
+ {
+ return;
+ }
+ ByteTagList list;
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.start >= appendOffset)
+ {
+ continue;
+ }
+ else if (item.start < appendOffset && item.end > appendOffset)
+ {
+ item.end = appendOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+void
+ByteTagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
+{
+ NS_LOG_FUNCTION (this << adjustment << prependOffset);
+ if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
+ {
+ return;
+ }
+ ByteTagList list;
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.end <= prependOffset)
+ {
+ continue;
+ }
+ else if (item.end > prependOffset && item.start < prependOffset)
+ {
+ item.start = prependOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+#ifdef USE_FREE_LIST
+
+struct ByteTagListData *
+ByteTagList::Allocate (uint32_t size)
+{
+ NS_LOG_FUNCTION (this << size);
+ while (!g_freeList.empty ())
+ {
+ struct ByteTagListData *data = g_freeList.back ();
+ g_freeList.pop_back ();
+ NS_ASSERT (data != 0);
+ if (data->size >= size)
+ {
+ data->count = 1;
+ data->dirty = 0;
+ return data;
+ }
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+ uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct ByteTagListData) - 4];
+ struct ByteTagListData *data = (struct ByteTagListData *)buffer;
+ data->count = 1;
+ data->size = size;
+ data->dirty = 0;
+ return data;
+}
+
+void
+ByteTagList::Deallocate (struct ByteTagListData *data)
+{
+ NS_LOG_FUNCTION (this << data);
+ if (data == 0)
+ {
+ return;
+ }
+ g_maxSize = std::max (g_maxSize, data->size);
+ data->count--;
+ if (data->count == 0)
+ {
+ if (g_freeList.size () > FREE_LIST_SIZE ||
+ data->size < g_maxSize)
+ {
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+ else
+ {
+ g_freeList.push_back (data);
+ }
+ }
+}
+
+#else /* USE_FREE_LIST */
+
+struct ByteTagListData *
+ByteTagList::Allocate (uint32_t size)
+{
+ NS_LOG_FUNCTION (this << size);
+ uint8_t *buffer = new uint8_t [size + sizeof (struct ByteTagListData) - 4];
+ struct ByteTagListData *data = (struct ByteTagListData *)buffer;
+ data->count = 1;
+ data->size = size;
+ data->dirty = 0;
+ return data;
+}
+
+void
+ByteTagList::Deallocate (struct ByteTagListData *data)
+{
+ NS_LOG_FUNCTION (this << data);
+ if (data == 0)
+ {
+ return;
+ }
+ data->count--;
+ if (data->count == 0)
+ {
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+}
+
+#endif /* USE_FREE_LIST */
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/byte-tag-list.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef BYTE_TAG_LIST_H
+#define BYTE_TAG_LIST_H
+
+#include <stdint.h>
+#include "ns3/type-id.h"
+#include "tag-buffer.h"
+
+namespace ns3 {
+
+struct ByteTagListData;
+
+/**
+ * \ingroup packet
+ *
+ * \brief keep track of the tags stored in a packet.
+ *
+ * This class is mostly private to the Packet implementation and users
+ * should never have to access it directly.
+ *
+ * \internal
+ * The implementation of this class is a bit tricky so, there are a couple
+ * of things to keep in mind here:
+ *
+ * - it stores all tags in a single byte buffer: each tag is stored
+ * as 4 32bit integers (TypeId, tag data size, start, end) followed
+ * by the tag data as generated by Tag::Serialize.
+ *
+ * - the struct ByteTagListData structure which contains the tag byte buffer
+ * is shared and, thus, reference-counted. This data structure is unshared
+ * as-needed to emulate COW semantics.
+ *
+ * - each tag tags a unique set of bytes identified by the pair of offsets
+ * (start,end). These offsets are provided by Buffer::GetCurrentStartOffset
+ * and Buffer::GetCurrentEndOffset which means that they are relative to
+ * the start of the 'virtual byte buffer' as explained in the documentation
+ * for the ns3::Buffer class. Whenever the origin of the offset of the Buffer
+ * instance associated to this ByteTagList instance changes, the Buffer class
+ * reports this to its container Packet class as a bool return value
+ * in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens
+ * the Packet class calls ByteTagList::AddAtEnd and ByteTagList::AddAtStart to update
+ * the byte offsets of each tag in the ByteTagList.
+ *
+ * - whenever bytes are removed from the packet byte buffer, the ByteTagList offsets
+ * are never updated because we rely on the fact that they will be updated in
+ * either the next call to Packet::AddHeader or Packet::AddTrailer or when
+ * the user iterates the tag list with Packet::GetTagIterator and
+ * TagIterator::Next.
+ */
+class ByteTagList
+{
+public:
+
+ class Iterator
+ {
+ public:
+ struct Item
+ {
+ TypeId tid;
+ uint32_t size;
+ int32_t start;
+ int32_t end;
+ TagBuffer buf;
+ Item (TagBuffer buf);
+ private:
+ friend class ByteTagList;
+ friend class ByteTagList::Iterator;
+ };
+ bool HasNext (void) const;
+ struct ByteTagList::Iterator::Item Next (void);
+ uint32_t GetOffsetStart (void) const;
+ private:
+ friend class ByteTagList;
+ Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd);
+ void PrepareForNext (void);
+ uint8_t *m_current;
+ uint8_t *m_end;
+ int32_t m_offsetStart;
+ int32_t m_offsetEnd;
+ uint32_t m_nextTid;
+ uint32_t m_nextSize;
+ int32_t m_nextStart;
+ int32_t m_nextEnd;
+ };
+
+ ByteTagList ();
+ ByteTagList (const ByteTagList &o);
+ ByteTagList &operator = (const ByteTagList &o);
+ ~ByteTagList ();
+
+ /**
+ * \param tid the typeid of the tag added
+ * \param bufferSize the size of the tag when its serialization will
+ * be completed. Typically, the return value of Tag::GetSerializedSize
+ * \param start offset which uniquely identifies the first byte tagged by this tag.
+ * \param end offset which uniquely identifies the last byte tagged by this tag.
+ * \returns a buffer which can be used to write the tag data.
+ *
+ *
+ */
+ TagBuffer Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end);
+
+ /**
+ * \param o the other list of tags to aggregate.
+ *
+ * Aggregate the two lists of tags.
+ */
+ void Add (const ByteTagList &o);
+
+ void RemoveAll (void);
+
+ /**
+ * \param offsetStart the offset which uniquely identifies the first data byte
+ * present in the byte buffer associated to this ByteTagList.
+ * \param offsetEnd the offset which uniquely identifies the last data byte
+ * present in the byte buffer associated to this ByteTagList.
+ * \returns an iterator
+ *
+ * The returned iterator will allow you to loop through the set of tags present
+ * in this list: the boundaries of each tag as reported by their start and
+ * end offsets will be included within the input offsetStart and offsetEnd.
+ */
+ ByteTagList::Iterator Begin (int32_t offsetStart, int32_t offsetEnd) const;
+
+ /**
+ * Adjust the offsets stored internally by the adjustment delta and
+ * make sure that all offsets are smaller than appendOffset which represents
+ * the location where new bytes have been added to the byte buffer.
+ */
+ void AddAtEnd (int32_t adjustment, int32_t appendOffset);
+ /**
+ * Adjust the offsets stored internally by the adjustment delta and
+ * make sure that all offsets are bigger than prependOffset which represents
+ * the location where new bytes have been added to the byte buffer.
+ */
+ void AddAtStart (int32_t adjustment, int32_t prependOffset);
+
+private:
+ bool IsDirtyAtEnd (int32_t appendOffset);
+ bool IsDirtyAtStart (int32_t prependOffset);
+ ByteTagList::Iterator BeginAll (void) const;
+
+ struct ByteTagListData *Allocate (uint32_t size);
+ void Deallocate (struct ByteTagListData *data);
+
+ uint16_t m_used;
+ struct ByteTagListData *m_data;
+};
+
+} // namespace ns3
+
+#endif /* BYTE_TAG_LIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-tag-list.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,177 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "packet-tag-list.h"
+#include "tag-buffer.h"
+#include "tag.h"
+#include "ns3/fatal-error.h"
+#include "ns3/log.h"
+#include <string.h>
+
+NS_LOG_COMPONENT_DEFINE ("PacketTagList");
+
+namespace ns3 {
+
+#ifdef USE_FREE_LIST
+
+struct PacketTagList::TagData *PacketTagList::g_free = 0;
+uint32_t PacketTagList::g_nfree = 0;
+
+struct PacketTagList::TagData *
+PacketTagList::AllocData (void) const
+{
+ NS_LOG_FUNCTION (g_nfree);
+ struct PacketTagList::TagData *retval;
+ if (g_free != 0)
+ {
+ retval = g_free;
+ g_free = g_free->m_next;
+ g_nfree--;
+ }
+ else
+ {
+ retval = new struct PacketTagList::TagData ();
+ }
+ return retval;
+}
+
+void
+PacketTagList::FreeData (struct TagData *data) const
+{
+ NS_LOG_FUNCTION (g_nfree << data);
+ if (g_nfree > 1000)
+ {
+ delete data;
+ return;
+ }
+ g_nfree++;
+ data->next = g_free;
+ data->tid = TypeId ();
+ g_free = data;
+}
+#else
+struct PacketTagList::TagData *
+PacketTagList::AllocData (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ struct PacketTagList::TagData *retval;
+ retval = new struct PacketTagList::TagData ();
+ return retval;
+}
+
+void
+PacketTagList::FreeData (struct TagData *data) const
+{
+ NS_LOG_FUNCTION (data);
+ delete data;
+}
+#endif
+
+bool
+PacketTagList::Remove (Tag &tag)
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ TypeId tid = tag.GetInstanceTypeId ();
+ bool found = false;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ found = true;
+ tag.Deserialize (TagBuffer (cur->data, cur->data+PACKET_TAG_MAX_SIZE));
+ }
+ }
+ if (!found)
+ {
+ return false;
+ }
+ struct TagData *start = 0;
+ struct TagData **prevNext = &start;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ /**
+ * XXX
+ * Note: I believe that we could optimize this to
+ * avoid copying each TagData located after the target id
+ * and just link the already-copied list to the next tag.
+ */
+ continue;
+ }
+ struct TagData *copy = AllocData ();
+ copy->tid = cur->tid;
+ copy->count = 1;
+ copy->next = 0;
+ memcpy (copy->data, cur->data, PACKET_TAG_MAX_SIZE);
+ *prevNext = copy;
+ prevNext = ©->next;
+ }
+ *prevNext = 0;
+ RemoveAll ();
+ m_next = start;
+ return true;
+}
+
+void
+PacketTagList::Add (const Tag &tag) const
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ // ensure this id was not yet added
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ NS_ASSERT (cur->tid != tag.GetInstanceTypeId ());
+ }
+ struct TagData *head = AllocData ();
+ head->count = 1;
+ head->next = 0;
+ head->tid = tag.GetInstanceTypeId ();
+ head->next = m_next;
+ NS_ASSERT (tag.GetSerializedSize () < PACKET_TAG_MAX_SIZE);
+ tag.Serialize (TagBuffer (head->data, head->data+tag.GetSerializedSize ()));
+
+ const_cast<PacketTagList *> (this)->m_next = head;
+}
+
+bool
+PacketTagList::Peek (Tag &tag) const
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ TypeId tid = tag.GetInstanceTypeId ();
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ /* found tag */
+ tag.Deserialize (TagBuffer (cur->data, cur->data+PACKET_TAG_MAX_SIZE));
+ return true;
+ }
+ }
+ /* no tag found */
+ return false;
+}
+
+const struct PacketTagList::TagData *
+PacketTagList::Head (void) const
+{
+ return m_next;
+}
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-tag-list.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_TAG_LIST_H
+#define PACKET_TAG_LIST_H
+
+#include <stdint.h>
+#include <ostream>
+#include "ns3/type-id.h"
+
+namespace ns3 {
+
+class Tag;
+
+/**
+ * \ingroup constants
+ * \brief Tag maximum size
+ * The maximum size (in bytes) of a Tag is stored
+ * in this constant.
+ */
+#define PACKET_TAG_MAX_SIZE 20
+
+class PacketTagList
+{
+public:
+ struct TagData {
+ uint8_t data[PACKET_TAG_MAX_SIZE];
+ struct TagData *next;
+ TypeId tid;
+ uint32_t count;
+ };
+
+ inline PacketTagList ();
+ inline PacketTagList (PacketTagList const &o);
+ inline PacketTagList &operator = (PacketTagList const &o);
+ inline ~PacketTagList ();
+
+ void Add (Tag const&tag) const;
+ bool Remove (Tag &tag);
+ bool Peek (Tag &tag) const;
+ inline void RemoveAll (void);
+
+ const struct PacketTagList::TagData *Head (void) const;
+
+private:
+
+ bool Remove (TypeId tid);
+ struct PacketTagList::TagData *AllocData (void) const;
+ void FreeData (struct TagData *data) const;
+
+ static struct PacketTagList::TagData *g_free;
+ static uint32_t g_nfree;
+
+ struct TagData *m_next;
+};
+
+} // namespace ns3
+
+/****************************************************
+ * Implementation of inline methods for performance
+ ****************************************************/
+
+namespace ns3 {
+
+PacketTagList::PacketTagList ()
+ : m_next ()
+{}
+
+PacketTagList::PacketTagList (PacketTagList const &o)
+ : m_next (o.m_next)
+{
+ if (m_next != 0)
+ {
+ m_next->count++;
+ }
+}
+
+PacketTagList &
+PacketTagList::operator = (PacketTagList const &o)
+{
+ // self assignment
+ if (m_next == o.m_next)
+ {
+ return *this;
+ }
+ RemoveAll ();
+ m_next = o.m_next;
+ if (m_next != 0)
+ {
+ m_next->count++;
+ }
+ return *this;
+}
+
+PacketTagList::~PacketTagList ()
+{
+ RemoveAll ();
+}
+
+void
+PacketTagList::RemoveAll (void)
+{
+ struct TagData *prev = 0;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ cur->count--;
+ if (cur->count > 0)
+ {
+ break;
+ }
+ if (prev != 0)
+ {
+ FreeData (prev);
+ }
+ prev = cur;
+ }
+ if (prev != 0)
+ {
+ FreeData (prev);
+ }
+ m_next = 0;
+}
+
+} // namespace ns3
+
+#endif /* PACKET_TAG_LIST_H */
--- a/src/common/packet.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/common/packet.cc Fri May 29 10:15:19 2009 +0400
@@ -28,22 +28,22 @@
uint32_t Packet::m_globalUid = 0;
TypeId
-TagIterator::Item::GetTypeId (void) const
+ByteTagIterator::Item::GetTypeId (void) const
{
return m_tid;
}
uint32_t
-TagIterator::Item::GetStart (void) const
+ByteTagIterator::Item::GetStart (void) const
{
return m_start;
}
uint32_t
-TagIterator::Item::GetEnd (void) const
+ByteTagIterator::Item::GetEnd (void) const
{
return m_end;
}
void
-TagIterator::Item::GetTag (Tag &tag) const
+ByteTagIterator::Item::GetTag (Tag &tag) const
{
if (tag.GetInstanceTypeId () != GetTypeId ())
{
@@ -51,31 +51,64 @@
}
tag.Deserialize (m_buffer);
}
-TagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
+ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
: m_tid (tid),
m_start (start),
m_end (end),
m_buffer (buffer)
{}
bool
-TagIterator::HasNext (void) const
+ByteTagIterator::HasNext (void) const
{
return m_current.HasNext ();
}
-TagIterator::Item
-TagIterator::Next (void)
+ByteTagIterator::Item
+ByteTagIterator::Next (void)
{
- TagList::Iterator::Item i = m_current.Next ();
- return TagIterator::Item (i.tid,
- i.start-m_current.GetOffsetStart (),
- i.end-m_current.GetOffsetStart (),
- i.buf);
+ ByteTagList::Iterator::Item i = m_current.Next ();
+ return ByteTagIterator::Item (i.tid,
+ i.start-m_current.GetOffsetStart (),
+ i.end-m_current.GetOffsetStart (),
+ i.buf);
}
-TagIterator::TagIterator (TagList::Iterator i)
+ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
: m_current (i)
{}
+PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
+ : m_current (head)
+{}
+bool
+PacketTagIterator::HasNext (void) const
+{
+ return m_current != 0;
+}
+PacketTagIterator::Item
+PacketTagIterator::Next (void)
+{
+ NS_ASSERT (HasNext ());
+ const struct PacketTagList::TagData *prev = m_current;
+ m_current = m_current->next;
+ return PacketTagIterator::Item (prev);
+}
+
+PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
+ : m_data (data)
+{}
+TypeId
+PacketTagIterator::Item::GetTypeId (void) const
+{
+ return m_data->tid;
+}
+void
+PacketTagIterator::Item::GetTag (Tag &tag) const
+{
+ NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
+ tag.Deserialize (TagBuffer ((uint8_t*)m_data->data, (uint8_t*)m_data->data+PACKET_TAG_MAX_SIZE));
+}
+
+
void
Packet::Ref (void) const
{
@@ -102,7 +135,8 @@
Packet::Packet ()
: m_buffer (),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, 0),
m_refCount (1)
{
@@ -111,7 +145,8 @@
Packet::Packet (const Packet &o)
: m_buffer (o.m_buffer),
- m_tagList (o.m_tagList),
+ m_byteTagList (o.m_byteTagList),
+ m_packetTagList (o.m_packetTagList),
m_metadata (o.m_metadata),
m_refCount (1)
{}
@@ -124,14 +159,16 @@
return *this;
}
m_buffer = o.m_buffer;
- m_tagList = o.m_tagList;
+ m_byteTagList = o.m_byteTagList;
+ m_packetTagList = o.m_packetTagList;
m_metadata = o.m_metadata;
return *this;
}
Packet::Packet (uint32_t size)
: m_buffer (size),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -139,7 +176,8 @@
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -149,9 +187,11 @@
i.Write (buffer, size);
}
-Packet::Packet (const Buffer &buffer, const TagList &tagList, const PacketMetadata &metadata)
+Packet::Packet (const Buffer &buffer, const ByteTagList &byteTagList,
+ const PacketTagList &packetTagList, const PacketMetadata &metadata)
: m_buffer (buffer),
- m_tagList (tagList),
+ m_byteTagList (byteTagList),
+ m_packetTagList (packetTagList),
m_metadata (metadata),
m_refCount (1)
{}
@@ -166,7 +206,7 @@
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
// again, call the constructor directly rather than
// through Create because it is private.
- return Ptr<Packet> (new Packet (buffer, m_tagList, metadata), false);
+ return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
}
uint32_t
@@ -184,8 +224,8 @@
bool resized = m_buffer.AddAtStart (size);
if (resized)
{
- m_tagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
- m_buffer.GetCurrentStartOffset () + size);
+ m_byteTagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
+ m_buffer.GetCurrentStartOffset () + size);
}
header.Serialize (m_buffer.Begin ());
m_metadata.AddHeader (header, size);
@@ -215,8 +255,8 @@
bool resized = m_buffer.AddAtEnd (size);
if (resized)
{
- m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
- m_buffer.GetCurrentEndOffset () - size);
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
+ m_buffer.GetCurrentEndOffset () - size);
}
Buffer::Iterator end = m_buffer.End ();
trailer.Serialize (end);
@@ -247,12 +287,12 @@
uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
m_buffer.AddAtEnd (packet->m_buffer);
uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
- m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart,
- appendPrependOffset);
- TagList copy = packet->m_tagList;
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart,
+ appendPrependOffset);
+ ByteTagList copy = packet->m_byteTagList;
copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
appendPrependOffset);
- m_tagList.Add (copy);
+ m_byteTagList.Add (copy);
m_metadata.AddAtEnd (packet->m_metadata);
}
void
@@ -263,8 +303,8 @@
bool resized = m_buffer.AddAtEnd (size);
if (resized)
{
- m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
- m_buffer.GetCurrentEndOffset () - size);
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+ m_buffer.GetCurrentEndOffset () - size);
}
m_metadata.AddPaddingAtEnd (size);
}
@@ -284,10 +324,10 @@
}
void
-Packet::RemoveAllTags (void)
+Packet::RemoveAllByteTags (void)
{
NS_LOG_FUNCTION (this);
- m_tagList.RemoveAll ();
+ m_byteTagList.RemoveAll ();
}
uint8_t const *
@@ -316,12 +356,12 @@
}
void
-Packet::PrintTags (std::ostream &os) const
+Packet::PrintByteTags (std::ostream &os) const
{
- TagIterator i = GetTagIterator ();
+ ByteTagIterator i = GetByteTagIterator ();
while (i.HasNext ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
if (constructor.IsNull ())
@@ -537,29 +577,29 @@
}
void
-Packet::AddTag (const Tag &tag) const
+Packet::AddByteTag (const Tag &tag) const
{
NS_LOG_FUNCTION (this << &tag);
- TagList *list = const_cast<TagList *> (&m_tagList);
+ ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
- m_buffer.GetCurrentStartOffset (),
- m_buffer.GetCurrentEndOffset ());
+ m_buffer.GetCurrentStartOffset (),
+ m_buffer.GetCurrentEndOffset ());
tag.Serialize (buffer);
}
-TagIterator
-Packet::GetTagIterator (void) const
+ByteTagIterator
+Packet::GetByteTagIterator (void) const
{
- return TagIterator (m_tagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
+ return ByteTagIterator (m_byteTagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
}
bool
-Packet::FindFirstMatchingTag (Tag &tag) const
+Packet::FindFirstMatchingByteTag (Tag &tag) const
{
TypeId tid = tag.GetInstanceTypeId ();
- TagIterator i = GetTagIterator ();
+ ByteTagIterator i = GetByteTagIterator ();
while (i.HasNext ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
if (tid == item.GetTypeId ())
{
item.GetTag (tag);
@@ -569,6 +609,59 @@
return false;
}
+void
+Packet::AddPacketTag (const Tag &tag) const
+{
+ m_packetTagList.Add (tag);
+}
+bool
+Packet::RemovePacketTag (Tag &tag)
+{
+ bool found = m_packetTagList.Remove (tag);
+ return found;
+}
+bool
+Packet::PeekPacketTag (Tag &tag) const
+{
+ bool found = m_packetTagList.Peek (tag);
+ return found;
+}
+void
+Packet::RemoveAllPacketTags (void)
+{
+ m_packetTagList.RemoveAll ();
+}
+
+void
+Packet::PrintPacketTags (std::ostream &os) const
+{
+ PacketTagIterator i = GetPacketTagIterator ();
+ while (i.HasNext ())
+ {
+ PacketTagIterator::Item item = i.Next ();
+ NS_ASSERT (item.GetTypeId ().HasConstructor ());
+ Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
+ NS_ASSERT (!constructor.IsNull ());
+ ObjectBase *instance = constructor ();
+ Tag *tag = dynamic_cast<Tag *> (instance);
+ NS_ASSERT (tag != 0);
+ item.GetTag (*tag);
+ tag->Print (os);
+ delete tag;
+ if (i.HasNext ())
+ {
+ os << " ";
+ }
+ }
+}
+
+PacketTagIterator
+Packet::GetPacketTagIterator (void) const
+{
+ return PacketTagIterator (m_packetTagList.Head ());
+}
+
+
std::ostream& operator<< (std::ostream& os, const Packet &packet)
{
packet.Print (os);
@@ -578,8 +671,6 @@
} // namespace ns3
-
-
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
@@ -766,14 +857,14 @@
namespace ns3 {
-class PacketTest: public Test
+static class PacketTest: public Test
{
public:
PacketTest ();
virtual bool RunTests (void);
private:
bool DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
-};
+} g_packetTest;
PacketTest::PacketTest ()
@@ -795,11 +886,11 @@
}
va_end (ap);
- TagIterator i = p->GetTagIterator ();
+ ByteTagIterator i = p->GetByteTagIterator ();
uint32_t j = 0;
while (i.HasNext () && j < expected.size ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
struct Expected e = expected[j];
std::ostringstream oss;
oss << "anon::ATestTag<" << e.n << ">";
@@ -838,12 +929,12 @@
Ptr<const Packet> p = Create<Packet> (1000);
- p->AddTag (ATestTag<1> ());
+ p->AddByteTag (ATestTag<1> ());
CHECK (p, 1, E (1, 0, 1000));
Ptr<const Packet> copy = p->Copy ();
CHECK (copy, 1, E (1, 0, 1000));
- p->AddTag (ATestTag<2> ());
+ p->AddByteTag (ATestTag<2> ());
CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
@@ -854,7 +945,7 @@
CHECK (&c0, 1, E (1, 0, 1000));
CHECK (&c1, 1, E (1, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
- c0.AddTag (ATestTag<10> ());
+ c0.AddByteTag (ATestTag<10> ());
CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
CHECK (&c1, 1, E (1, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
@@ -863,11 +954,11 @@
Ptr<Packet> frag0 = p->CreateFragment (0, 10);
Ptr<Packet> frag1 = p->CreateFragment (10, 90);
Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
- frag0->AddTag (ATestTag<3> ());
+ frag0->AddByteTag (ATestTag<3> ());
CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
- frag1->AddTag (ATestTag<4> ());
+ frag1->AddByteTag (ATestTag<4> ());
CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
- frag2->AddTag (ATestTag<5> ());
+ frag2->AddByteTag (ATestTag<5> ());
CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
frag1->AddAtEnd (frag2);
@@ -887,7 +978,7 @@
frag0 = 0;
p = Create<Packet> (1000);
- p->AddTag (ATestTag<20> ());
+ p->AddByteTag (ATestTag<20> ());
CHECK (p, 1, E (20, 0, 1000));
frag0 = p->CreateFragment (10, 90);
CHECK (p, 1, E (20, 0, 1000));
@@ -898,7 +989,7 @@
{
Ptr<Packet> tmp = Create<Packet> (100);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 100));
tmp->AddHeader (ATestHeader<10> ());
CHECK (tmp, 1, E (20, 10, 110));
@@ -909,7 +1000,7 @@
CHECK (tmp, 1, E (20, 10, 110));
tmp = Create<Packet> (100);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 100));
tmp->AddTrailer (ATestTrailer<10> ());
CHECK (tmp, 1, E (20, 0, 100));
@@ -924,7 +1015,7 @@
{
Ptr<Packet> tmp = Create<Packet> (0);
tmp->AddHeader (ATestHeader<156> ());
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 156));
tmp->RemoveAtStart (120);
CHECK (tmp, 1, E (20, 0, 36));
@@ -935,29 +1026,56 @@
{
Ptr<Packet> tmp = Create<Packet> (0);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 0, E (20, 0, 0));
}
{
Ptr<Packet> tmp = Create<Packet> (1000);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 1000));
tmp->RemoveAtStart (1000);
CHECK (tmp, 0, E (0,0,0));
Ptr<Packet> a = Create<Packet> (10);
- a->AddTag (ATestTag<10> ());
+ a->AddByteTag (ATestTag<10> ());
CHECK (a, 1, E (10, 0, 10));
tmp->AddAtEnd (a);
CHECK (tmp, 1, E (10, 0, 10));
}
-
+
+ {
+ Packet p;
+ ATestTag<10> a;
+ p.AddPacketTag (a);
+ NS_TEST_ASSERT (p.PeekPacketTag (a));
+ ATestTag<11> b;
+ p.AddPacketTag (b);
+ NS_TEST_ASSERT (p.PeekPacketTag (b));
+ NS_TEST_ASSERT (p.PeekPacketTag (a));
+ Packet copy = p;
+ NS_TEST_ASSERT (copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ ATestTag<12> c;
+ NS_TEST_ASSERT (!copy.PeekPacketTag (c));
+ copy.AddPacketTag (c);
+ NS_TEST_ASSERT (copy.PeekPacketTag (c));
+ NS_TEST_ASSERT (copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ NS_TEST_ASSERT (!p.PeekPacketTag (c));
+ copy.RemovePacketTag (b);
+ NS_TEST_ASSERT (!copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (p.PeekPacketTag (b));
+ p.RemovePacketTag (a);
+ NS_TEST_ASSERT (!p.PeekPacketTag (a));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ NS_TEST_ASSERT (!p.PeekPacketTag (c));
+ NS_TEST_ASSERT (copy.PeekPacketTag (c));
+ p.RemoveAllPacketTags ();
+ NS_TEST_ASSERT (!p.PeekPacketTag (b));
+ }
return result;
}
-
-static PacketTest g_packetTest;
-
-}; // namespace ns3
+} // namespace ns3
#endif /* RUN_SELF_TESTS */
--- a/src/common/packet.h Thu May 28 21:41:45 2009 -0700
+++ b/src/common/packet.h Fri May 29 10:15:19 2009 +0400
@@ -26,7 +26,8 @@
#include "trailer.h"
#include "packet-metadata.h"
#include "tag.h"
-#include "tag-list.h"
+#include "byte-tag-list.h"
+#include "packet-tag-list.h"
#include "ns3/callback.h"
#include "ns3/assert.h"
#include "ns3/ptr.h"
@@ -45,7 +46,7 @@
*
* This is a java-style iterator.
*/
-class TagIterator
+class ByteTagIterator
{
public:
/**
@@ -81,7 +82,7 @@
*/
void GetTag (Tag &tag) const;
private:
- friend class TagIterator;
+ friend class ByteTagIterator;
Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer);
TypeId m_tid;
uint32_t m_start;
@@ -98,16 +99,63 @@
Item Next (void);
private:
friend class Packet;
- TagIterator (TagList::Iterator i);
- TagList::Iterator m_current;
+ ByteTagIterator (ByteTagList::Iterator i);
+ ByteTagList::Iterator m_current;
+};
+
+/**
+ * \ingroup packet
+ * \brief Iterator over the set of 'packet' tags in a packet
+ *
+ * This is a java-style iterator.
+ */
+class PacketTagIterator
+{
+public:
+ /**
+ * Identifies a tag within a packet.
+ */
+ class Item
+ {
+ public:
+ /**
+ * \returns the ns3::TypeId associated to this tag.
+ */
+ TypeId GetTypeId (void) const;
+ /**
+ * \param tag the user tag to which the data should be copied.
+ *
+ * Read the requested tag and store it in the user-provided
+ * tag instance. This method will crash if the type of the
+ * tag provided by the user does not match the type of
+ * the underlying tag.
+ */
+ void GetTag (Tag &tag) const;
+ private:
+ friend class PacketTagIterator;
+ Item (const struct PacketTagList::TagData *data);
+ const struct PacketTagList::TagData *m_data;
+ };
+ /**
+ * \returns true if calling Next is safe, false otherwise.
+ */
+ bool HasNext (void) const;
+ /**
+ * \returns the next item found and prepare for the next one.
+ */
+ Item Next (void);
+private:
+ friend class Packet;
+ PacketTagIterator (const struct PacketTagList::TagData *head);
+ const struct PacketTagList::TagData *m_current;
};
/**
* \ingroup packet
* \brief network packets
*
- * Each network packet contains a byte buffer, a set of tags, and
- * metadata.
+ * Each network packet contains a byte buffer, a set of byte tags, a set of
+ * packet tags, and metadata.
*
* - The byte buffer stores the serialized content of the headers and trailers
* added to a packet. The serialized representation of these headers is expected
@@ -115,17 +163,23 @@
* forces you to do this) which means that the content of a packet buffer
* is expected to be that of a real packet.
*
- * - Each tag tags a subset of the bytes in the packet byte buffer with the
- * information stored in the tag. A classic example of a tag is a FlowIdTag
- * which contains a flow id: the set of bytes tagged by this tag implicitely
- * belong to the attached flow id.
- *
* - The metadata describes the type of the headers and trailers which
* were serialized in the byte buffer. The maintenance of metadata is
* optional and disabled by default. To enable it, you must call
* Packet::EnableMetadata and this will allow you to get non-empty
* output from Packet::Print and Packet::Print.
*
+ * - The set of tags contain simulation-specific information which cannot
+ * be stored in the packet byte buffer because the protocol headers or trailers
+ * have no standard-conformant field for this information. So-called
+ * 'byte' tags are used to tag a subset of the bytes in the packet byte buffer
+ * while 'packet' tags are used to tag the packet itself. The main difference
+ * between these two kinds of tags is what happens when packets are copied,
+ * fragmented, and reassembled: 'byte' tags follow bytes while 'packet' tags
+ * follow packets. A classic example of a 'byte' tag is a FlowIdTag
+ * which contains a flow id: the set of bytes tagged by this tag implicitely
+ * belong to the attached flow id.
+ *
* Implementing a new type of Header or Trailer for a new protocol is
* pretty easy and is a matter of creating a subclass of the ns3::Header
* or of the ns3::Trailer base class, and implementing the methods
@@ -236,13 +290,6 @@
* \returns the number of bytes read from the end of the packet.
*/
uint32_t PeekTrailer (Trailer &trailer);
- /**
- * \param os output stream in which the data should be printed.
- *
- * Iterate over the tags present in this packet, and
- * invoke the Print method of each tag stored in the packet.
- */
- void PrintTags (std::ostream &os) const;
/**
* Concatenate the input packet at the end of the current
@@ -388,11 +435,11 @@
* totally evil to allow a trace sink to modify the content of a
* packet).
*/
- void AddTag (const Tag &tag) const;
+ void AddByteTag (const Tag &tag) const;
/**
- * \returns an iterator over the set of tags included in this packet.
+ * \returns an iterator over the set of byte tags included in this packet.
*/
- TagIterator GetTagIterator (void) const;
+ ByteTagIterator GetByteTagIterator (void) const;
/**
* \param tag the tag to search in this packet
* \returns true if the requested tag type was found, false otherwise.
@@ -400,17 +447,78 @@
* If the requested tag type is found, it is copied in the user's
* provided tag instance.
*/
- bool FindFirstMatchingTag (Tag &tag) const;
+ bool FindFirstMatchingByteTag (Tag &tag) const;
/**
* Remove all the tags stored in this packet.
*/
- void RemoveAllTags (void);
+ void RemoveAllByteTags (void);
+
+ /**
+ * \param os output stream in which the data should be printed.
+ *
+ * Iterate over the tags present in this packet, and
+ * invoke the Print method of each tag stored in the packet.
+ */
+ void PrintByteTags (std::ostream &os) const;
+
+ /**
+ * \param tag the tag to store in this packet
+ *
+ * Add a tag to this packet. This method calls the
+ * Tag::GetSerializedSize and, then, Tag::Serialize.
+ *
+ * Note that this method is const, that is, it does not
+ * modify the state of this packet, which is fairly
+ * un-intuitive.
+ *
+ * \sa AddTag
+ */
+ void AddPacketTag (const Tag &tag) const;
+ /**
+ * \param tag the tag to remove from this packet
+ * \returns true if the requested tag is found, false
+ * otherwise.
+ *
+ * Remove a tag from this packet. This method calls
+ * Tag::Deserialize if the tag is found.
+ */
+ bool RemovePacketTag (Tag &tag);
+ /**
+ * \param tag the tag to search in this packet
+ * \returns true if the requested tag is found, false
+ * otherwise.
+ *
+ * Search a matching tag and call Tag::Deserialize if it is found.
+ */
+ bool PeekPacketTag (Tag &tag) const;
+ /**
+ * Remove all packet tags.
+ */
+ void RemoveAllPacketTags (void);
+
+ /**
+ * \param os the stream in which we want to print data.
+ *
+ * Print the list of 'packet' tags.
+ *
+ * \sa Packet::AddPacketTag, Packet::RemovePacketTag, Packet::PeekPacketTag,
+ * Packet::RemoveAllPacketTags
+ */
+ void PrintPacketTags (std::ostream &os) const;
+
+ /**
+ * \returns an object which can be used to iterate over the list of
+ * packet tags.
+ */
+ PacketTagIterator GetPacketTagIterator (void) const;
private:
- Packet (const Buffer &buffer, const TagList &tagList, const PacketMetadata &metadata);
+ Packet (const Buffer &buffer, const ByteTagList &byteTagList,
+ const PacketTagList &packetTagList, const PacketMetadata &metadata);
Buffer m_buffer;
- TagList m_tagList;
+ ByteTagList m_byteTagList;
+ PacketTagList m_packetTagList;
PacketMetadata m_metadata;
mutable uint32_t m_refCount;
static uint32_t m_globalUid;
@@ -435,11 +543,14 @@
* - ns3::Packet::AddHeader
* - ns3::Packet::AddTrailer
* - both versions of ns3::Packet::AddAtEnd
+ * - ns3::Packet::RemovePacketTag
*
* Non-dirty operations:
* - ns3::Packet::AddTag
* - ns3::Packet::RemoveAllTags
* - ns3::Packet::PeekTag
+ * - ns3::Packet::RemoveAllPacketTags
+ * - ns3::Packet::PeekPacketTag
* - ns3::Packet::RemoveHeader
* - ns3::Packet::RemoveTrailer
* - ns3::Packet::CreateFragment
--- a/src/common/tag-list.cc Thu May 28 21:41:45 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "tag-list.h"
-#include "ns3/log.h"
-#include <vector>
-#include <string.h>
-
-NS_LOG_COMPONENT_DEFINE ("TagList");
-
-#define USE_FREE_LIST 1
-#define FREE_LIST_SIZE 1000
-#define OFFSET_MAX (2147483647)
-
-namespace ns3 {
-
-struct TagListData {
- uint32_t size;
- uint32_t count;
- uint32_t dirty;
- uint8_t data[4];
-};
-
-#ifdef USE_FREE_LIST
-static class TagListDataFreeList : public std::vector<struct TagListData *>
-{
-public:
- ~TagListDataFreeList ();
-} g_freeList;
-static uint32_t g_maxSize = 0;
-
-TagListDataFreeList::~TagListDataFreeList ()
-{
- for (TagListDataFreeList::iterator i = begin ();
- i != end (); i++)
- {
- uint8_t *buffer = (uint8_t *)(*i);
- delete [] buffer;
- }
-}
-#endif /* USE_FREE_LIST */
-
-TagList::Iterator::Item::Item (TagBuffer buf_)
- : buf (buf_)
-{}
-
-bool
-TagList::Iterator::HasNext (void) const
-{
- return m_current < m_end;
-}
-struct TagList::Iterator::Item
-TagList::Iterator::Next (void)
-{
- NS_ASSERT (HasNext ());
- struct Item item = Item (TagBuffer (m_current+16, m_end));
- item.tid.SetUid (m_nextTid);
- item.size = m_nextSize;
- item.start = std::max (m_nextStart, m_offsetStart);
- item.end = std::min (m_nextEnd, m_offsetEnd);
- m_current += 4 + 4 + 4 + 4 + item.size;
- item.buf.TrimAtEnd (m_end - m_current);
- PrepareForNext ();
- return item;
-}
-void
-TagList::Iterator::PrepareForNext (void)
-{
- while (m_current < m_end)
- {
- TagBuffer buf = TagBuffer (m_current, m_end);
- m_nextTid = buf.ReadU32 ();
- m_nextSize = buf.ReadU32 ();
- m_nextStart = buf.ReadU32 ();
- m_nextEnd = buf.ReadU32 ();
- if (m_nextStart >= m_offsetEnd || m_nextEnd <= m_offsetStart)
- {
- m_current += 4 + 4 + 4 + 4 + m_nextSize;
- }
- else
- {
- break;
- }
- }
-}
-TagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
- : m_current (start),
- m_end (end),
- m_offsetStart (offsetStart),
- m_offsetEnd (offsetEnd)
-{
- PrepareForNext ();
-}
-
-uint32_t
-TagList::Iterator::GetOffsetStart (void) const
-{
- return m_offsetStart;
-}
-
-
-TagList::TagList ()
- : m_used (0),
- m_data (0)
-{
- NS_LOG_FUNCTION (this);
-}
-TagList::TagList (const TagList &o)
- : m_used (o.m_used),
- m_data (o.m_data)
-{
- NS_LOG_FUNCTION (this << &o);
- if (m_data != 0)
- {
- m_data->count++;
- }
-}
-TagList &
-TagList::operator = (const TagList &o)
-{
- NS_LOG_FUNCTION (this << &o);
- if (this == &o)
- {
- return *this;
- }
-
- Deallocate (m_data);
- m_data = o.m_data;
- m_used = o.m_used;
- if (m_data != 0)
- {
- m_data->count++;
- }
- return *this;
-}
-TagList::~TagList ()
-{
- NS_LOG_FUNCTION (this);
- Deallocate (m_data);
- m_data = 0;
- m_used = 0;
-}
-
-TagBuffer
-TagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
-{
- NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
- uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
- NS_ASSERT (m_used <= spaceNeeded);
- if (m_data == 0)
- {
- m_data = Allocate (spaceNeeded);
- m_used = 0;
- }
- else if (m_data->size < spaceNeeded ||
- (m_data->count != 1 && m_data->dirty != m_used))
- {
- struct TagListData *newData = Allocate (spaceNeeded);
- memcpy (&newData->data, &m_data->data, m_used);
- Deallocate (m_data);
- m_data = newData;
- }
- TagBuffer tag = TagBuffer (&m_data->data[m_used],
- &m_data->data[spaceNeeded]);
- tag.WriteU32 (tid.GetUid ());
- tag.WriteU32 (bufferSize);
- tag.WriteU32 (start);
- tag.WriteU32 (end);
- m_used = spaceNeeded;
- m_data->dirty = m_used;
- return tag;
-}
-
-void
-TagList::Add (const TagList &o)
-{
- NS_LOG_FUNCTION (this << &o);
- TagList::Iterator i = o.BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
-}
-
-void
-TagList::RemoveAll (void)
-{
- NS_LOG_FUNCTION (this);
- Deallocate (m_data);
- m_data = 0;
- m_used = 0;
-}
-
-TagList::Iterator
-TagList::BeginAll (void) const
-{
- NS_LOG_FUNCTION (this);
- // I am not totally sure but I might need to use
- // INT32_MIN instead of zero below.
- return Begin (0, OFFSET_MAX);
-}
-
-TagList::Iterator
-TagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
-{
- NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
- if (m_data == 0)
- {
- return Iterator (0, 0, offsetStart, offsetEnd);
- }
- else
- {
- return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
- }
-}
-
-bool
-TagList::IsDirtyAtEnd (int32_t appendOffset)
-{
- NS_LOG_FUNCTION (this << appendOffset);
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- if (item.end > appendOffset)
- {
- return true;
- }
- }
- return false;
-}
-
-bool
-TagList::IsDirtyAtStart (int32_t prependOffset)
-{
- NS_LOG_FUNCTION (this << prependOffset);
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- if (item.start < prependOffset)
- {
- return true;
- }
- }
- return false;
-}
-
-void
-TagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
-{
- NS_LOG_FUNCTION (this << adjustment << appendOffset);
- if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
- {
- return;
- }
- TagList list;
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- item.start += adjustment;
- item.end += adjustment;
-
- if (item.start >= appendOffset)
- {
- continue;
- }
- else if (item.start < appendOffset && item.end > appendOffset)
- {
- item.end = appendOffset;
- }
- else
- {
- // nothing to do.
- }
- TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
- *this = list;
-}
-
-void
-TagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
-{
- NS_LOG_FUNCTION (this << adjustment << prependOffset);
- if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
- {
- return;
- }
- TagList list;
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- item.start += adjustment;
- item.end += adjustment;
-
- if (item.end <= prependOffset)
- {
- continue;
- }
- else if (item.end > prependOffset && item.start < prependOffset)
- {
- item.start = prependOffset;
- }
- else
- {
- // nothing to do.
- }
- TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
- *this = list;
-}
-
-#ifdef USE_FREE_LIST
-
-struct TagListData *
-TagList::Allocate (uint32_t size)
-{
- NS_LOG_FUNCTION (this << size);
- while (!g_freeList.empty ())
- {
- struct TagListData *data = g_freeList.back ();
- g_freeList.pop_back ();
- NS_ASSERT (data != 0);
- if (data->size >= size)
- {
- data->count = 1;
- data->dirty = 0;
- return data;
- }
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
- uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct TagListData) - 4];
- struct TagListData *data = (struct TagListData *)buffer;
- data->count = 1;
- data->size = size;
- data->dirty = 0;
- return data;
-}
-
-void
-TagList::Deallocate (struct TagListData *data)
-{
- NS_LOG_FUNCTION (this << data);
- if (data == 0)
- {
- return;
- }
- g_maxSize = std::max (g_maxSize, data->size);
- data->count--;
- if (data->count == 0)
- {
- if (g_freeList.size () > FREE_LIST_SIZE ||
- data->size < g_maxSize)
- {
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
- else
- {
- g_freeList.push_back (data);
- }
- }
-}
-
-#else /* USE_FREE_LIST */
-
-struct TagListData *
-TagList::Allocate (uint32_t size)
-{
- NS_LOG_FUNCTION (this << size);
- uint8_t *buffer = new uint8_t [size + sizeof (struct TagListData) - 4];
- struct TagListData *data = (struct TagListData *)buffer;
- data->count = 1;
- data->size = size;
- data->dirty = 0;
- return data;
-}
-
-void
-TagList::Deallocate (struct TagListData *data)
-{
- NS_LOG_FUNCTION (this << data);
- if (data == 0)
- {
- return;
- }
- data->count--;
- if (data->count == 0)
- {
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
-}
-
-#endif /* USE_FREE_LIST */
-
-
-} // namespace ns3
--- a/src/common/tag-list.h Thu May 28 21:41:45 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef TAG_LIST_H
-#define TAG_LIST_H
-
-#include <stdint.h>
-#include "ns3/type-id.h"
-#include "tag-buffer.h"
-
-namespace ns3 {
-
-struct TagListData;
-
-/**
- * \ingroup packet
- *
- * \brief keep track of the tags stored in a packet.
- *
- * This class is mostly private to the Packet implementation and users
- * should never have to access it directly.
- *
- * \internal
- * The implementation of this class is a bit tricky so, there are a couple
- * of things to keep in mind here:
- *
- * - it stores all tags in a single byte buffer: each tag is stored
- * as 4 32bit integers (TypeId, tag data size, start, end) followed
- * by the tag data as generated by Tag::Serialize.
- *
- * - the struct TagListData structure which contains the tag byte buffer
- * is shared and, thus, reference-counted. This data structure is unshared
- * as-needed to emulate COW semantics.
- *
- * - each tag tags a unique set of bytes identified by the pair of offsets
- * (start,end). These offsets are provided by Buffer::GetCurrentStartOffset
- * and Buffer::GetCurrentEndOffset which means that they are relative to
- * the start of the 'virtual byte buffer' as explained in the documentation
- * for the ns3::Buffer class. Whenever the origin of the offset of the Buffer
- * instance associated to this TagList instance changes, the Buffer class
- * reports this to its container Packet class as a bool return value
- * in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens
- * the Packet class calls TagList::AddAtEnd and TagList::AddAtStart to update
- * the byte offsets of each tag in the TagList.
- *
- * - whenever bytes are removed from the packet byte buffer, the TagList offsets
- * are never updated because we rely on the fact that they will be updated in
- * either the next call to Packet::AddHeader or Packet::AddTrailer or when
- * the user iterates the tag list with Packet::GetTagIterator and
- * TagIterator::Next.
- */
-class TagList
-{
-public:
-
- class Iterator
- {
- public:
- struct Item
- {
- TypeId tid;
- uint32_t size;
- int32_t start;
- int32_t end;
- TagBuffer buf;
- Item (TagBuffer buf);
- private:
- friend class TagList;
- friend class TagList::Iterator;
- };
- bool HasNext (void) const;
- struct TagList::Iterator::Item Next (void);
- uint32_t GetOffsetStart (void) const;
- private:
- friend class TagList;
- Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd);
- void PrepareForNext (void);
- uint8_t *m_current;
- uint8_t *m_end;
- int32_t m_offsetStart;
- int32_t m_offsetEnd;
- uint32_t m_nextTid;
- uint32_t m_nextSize;
- int32_t m_nextStart;
- int32_t m_nextEnd;
- };
-
- TagList ();
- TagList (const TagList &o);
- TagList &operator = (const TagList &o);
- ~TagList ();
-
- /**
- * \param tid the typeid of the tag added
- * \param bufferSize the size of the tag when its serialization will
- * be completed. Typically, the return value of Tag::GetSerializedSize
- * \param start offset which uniquely identifies the first byte tagged by this tag.
- * \param end offset which uniquely identifies the last byte tagged by this tag.
- * \returns a buffer which can be used to write the tag data.
- *
- *
- */
- TagBuffer Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end);
-
- /**
- * \param o the other list of tags to aggregate.
- *
- * Aggregate the two lists of tags.
- */
- void Add (const TagList &o);
-
- void RemoveAll (void);
-
- /**
- * \param offsetStart the offset which uniquely identifies the first data byte
- * present in the byte buffer associated to this TagList.
- * \param offsetEnd the offset which uniquely identifies the last data byte
- * present in the byte buffer associated to this TagList.
- * \returns an iterator
- *
- * The returned iterator will allow you to loop through the set of tags present
- * in this list: the boundaries of each tag as reported by their start and
- * end offsets will be included within the input offsetStart and offsetEnd.
- */
- TagList::Iterator Begin (int32_t offsetStart, int32_t offsetEnd) const;
-
- /**
- * Adjust the offsets stored internally by the adjustment delta and
- * make sure that all offsets are smaller than appendOffset which represents
- * the location where new bytes have been added to the byte buffer.
- */
- void AddAtEnd (int32_t adjustment, int32_t appendOffset);
- /**
- * Adjust the offsets stored internally by the adjustment delta and
- * make sure that all offsets are bigger than prependOffset which represents
- * the location where new bytes have been added to the byte buffer.
- */
- void AddAtStart (int32_t adjustment, int32_t prependOffset);
-
-private:
- bool IsDirtyAtEnd (int32_t appendOffset);
- bool IsDirtyAtStart (int32_t prependOffset);
- TagList::Iterator BeginAll (void) const;
-
- struct TagListData *Allocate (uint32_t size);
- void Deallocate (struct TagListData *data);
-
- uint16_t m_used;
- struct TagListData *m_data;
-};
-
-} // namespace ns3
-
-#endif /* TAG_LIST_H */
--- a/src/common/tag.h Thu May 28 21:41:45 2009 -0700
+++ b/src/common/tag.h Fri May 29 10:15:19 2009 +0400
@@ -41,8 +41,8 @@
/**
* \returns the number of bytes required to serialize the data of the tag.
*
- * This method is typically invoked by Packet::AddTag just prior to calling
- * Tag::Serialize.
+ * This method is typically invoked by Packet::AddPacketTag or Packet::AddByteTag
+ * just prior to calling Tag::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
/**
@@ -65,7 +65,8 @@
/**
* \param os the stream to print to
*
- * This method is typically invoked from the Packet::PrintTags method
+ * This method is typically invoked from the Packet::PrintByteTags
+ * or Packet::PrintPacketTags methods.
*/
virtual void Print (std::ostream &os) const = 0;
};
--- a/src/common/wscript Thu May 28 21:41:45 2009 -0700
+++ b/src/common/wscript Fri May 29 10:15:19 2009 +0400
@@ -14,8 +14,9 @@
'data-rate.cc',
'error-model.cc',
'tag.cc',
- 'tag-list.cc',
+ 'byte-tag-list.cc',
'tag-buffer.cc',
+ 'packet-tag-list.cc',
]
headers = bld.new_task_gen('ns3header')
@@ -31,6 +32,7 @@
'data-rate.h',
'error-model.h',
'tag.h',
- 'tag-list.h',
+ 'byte-tag-list.h',
'tag-buffer.h',
+ 'packet-tag-list.h',
]
--- a/src/contrib/delay-jitter-estimation.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/contrib/delay-jitter-estimation.cc Fri May 29 10:15:19 2009 +0400
@@ -83,14 +83,14 @@
DelayJitterEstimation::PrepareTx (Ptr<const Packet> packet)
{
DelayJitterEstimationTimestampTag tag;
- packet->AddTag (tag);
+ packet->AddByteTag (tag);
}
void
DelayJitterEstimation::RecordRx (Ptr<const Packet> packet)
{
DelayJitterEstimationTimestampTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->FindFirstMatchingByteTag (tag);
if (!found)
{
return;
--- a/src/core/test.h Thu May 28 21:41:45 2009 -0700
+++ b/src/core/test.h Fri May 29 10:15:19 2009 +0400
@@ -110,7 +110,7 @@
#define NS_TEST_ASSERT_EQUAL_FILELINE(got, expected, file, line) \
do { \
- if ((got) != (expected)) \
+ if (! ((got) == (expected))) \
{ \
Failure () << file << ":" <<line \
<< ": expected " << (expected) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,38 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "airtime-metric.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mode.h"
+namespace ns3 {
+namespace dot11s {
+uint32_t
+AirtimeLinkMetricCalculator::CalculateMetric(Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac)
+{
+ WifiRemoteStation * station = mac->GetStationManager ()->Lookup(peerAddress);
+ NS_ASSERT(station != 0);
+ Ptr<Packet> test_frame = Create<Packet> (test_length);
+ uint32_t rate = station->GetDataMode(test_frame, test_length+header_length).GetDataRate ();
+ uint32_t payload_nanosec = (uint32_t) ((double) (test_length * 8) * 1e9 / ((double)rate));
+ uint32_t metric = (uint32_t) (((double) (payload_nanosec + overhead_nanosec)) / 102.4 * (station->GetAvgSlrc () + 1));
+ return metric;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef AIRTIME_METRIC_H
+#define AIRTIME_METRIC_H
+#include "ns3/mesh-wifi-interface-mac.h"
+namespace ns3 {
+namespace dot11s {
+class AirtimeLinkMetricCalculator : public RefCountBase
+{
+ public:
+ friend class MeshWifiInterfaceMac;
+ uint32_t CalculateMetric(Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac);
+ private:
+ ///\Microseconds of overhead:
+ static const uint32_t overhead_nanosec =
+ (34 //DIFS
+ +9*2 //SIFS
+ +16*2 //Preamble
+ +24) //Ack
+ *1000; //nanoseconds
+ static const uint32_t test_length = 1024;
+ static const uint32_t header_length = 36;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-helper.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#include "dot11s-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/wifi-channel.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/aarf-wifi-manager.h"
+#include "airtime-metric.h"
+namespace ns3 {
+namespace dot11s {
+
+MeshWifiHelper::MeshWifiHelper () :
+ m_randomStartDelay (Seconds (0)),
+ m_spreadInterfaceChannels (false)
+{
+}
+void
+MeshWifiHelper::SetRandomStartDelay (Time t)
+{
+ m_randomStartDelay = t;
+}
+
+void
+MeshWifiHelper::SetSpreadInterfaceChannels (bool s)
+{
+ m_spreadInterfaceChannels = s;
+}
+
+
+Ptr<WifiNetDevice>
+MeshWifiHelper::CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node) const
+{
+ Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
+
+ // Creating MAC for this interface
+ Ptr<MeshWifiInterfaceMac> mac = CreateObject<MeshWifiInterfaceMac> ();
+ mac->SetSsid (Ssid ());
+ if (m_randomStartDelay > Seconds (0))
+ mac->SetRandomStartDelay (m_randomStartDelay);
+ Ptr<WifiRemoteStationManager> manager = CreateObject<AarfWifiManager> ();
+ Ptr<WifiPhy> phy = phyHelper.Create (node, device);
+ mac->SetAddress (Mac48Address::Allocate ());
+ device->SetMac (mac);
+ device->SetPhy (phy);
+ device->SetRemoteStationManager (manager);
+ Ptr<AirtimeLinkMetricCalculator> metric = Create <AirtimeLinkMetricCalculator> ();
+ mac->SetLinkMetricCallback (MakeCallback(&AirtimeLinkMetricCalculator::CalculateMetric, metric));
+ /*
+ if (channel > 0)
+ mac->SwitchFrequencyChannel (channel);
+ */
+ return device;
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phyHelper, NodeContainer c, std::vector<uint32_t> roots, uint32_t nInterfaces) const
+{
+ NetDeviceContainer devices;
+ uint32_t node_index = 0;
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+
+ // Create a mesh point device
+ Ptr<MeshPointDevice> mp = CreateObject<MeshPointDevice> ();
+ node->AddDevice (mp);
+
+ // Create wifi interfaces (single interface by default)
+ for (uint32_t i = 0; i < nInterfaces; ++i)
+ {
+ Ptr<WifiNetDevice> iface = CreateInterface (phyHelper, node);
+
+ node->AddDevice (iface);
+ mp->AddInterface (iface);
+ }
+
+ // Set different channels on different ifaces
+ if (m_spreadInterfaceChannels)
+ {
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ for (size_t i = 0; i < ifaces.size(); ++i)
+ {
+ uint32_t channel = i * 5;
+
+ Ptr<WifiNetDevice> iface = ifaces[i]->GetObject<WifiNetDevice> ();
+ NS_ASSERT (iface);
+ Ptr<MeshWifiInterfaceMac> mac = iface->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac);
+
+ mac->SwitchFrequencyChannel (channel);
+ }
+ }
+
+ // Install 802.11s protocols
+ Ptr<PeerManagementProtocol> pmp = CreateObject<PeerManagementProtocol> ();
+ pmp->SetMeshId("mesh",4);
+ bool install_ok = pmp->Install (mp);
+ NS_ASSERT (install_ok);
+
+ Ptr<HwmpProtocol> hwmp = CreateObject<HwmpProtocol> ();
+ install_ok = hwmp->Install (mp);
+ NS_ASSERT (install_ok);
+
+ pmp->SetPeerLinkStatusCallback(MakeCallback(&HwmpProtocol::PeerLinkStatus, hwmp));
+ hwmp->SetNeighboursCallback(MakeCallback(&PeerManagementProtocol::GetActiveLinks, pmp));
+ // Setting root mesh point
+ for(std::vector<uint32_t>::const_iterator root_iterator = roots.begin (); root_iterator != roots.end (); root_iterator ++)
+ //if(*root_iterator == i.GetDistanceFrom(c.Begin ()))
+ if(*root_iterator == node_index)
+ hwmp->SetRoot ();
+ devices.Add (mp);
+ node_index ++;
+ }
+ return devices;
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phy, Ptr<Node> node, std::vector<uint32_t> roots, uint32_t nInterfaces) const
+{
+ return Install (phy, NodeContainer (node), roots, nInterfaces);
+}
+void
+MeshWifiHelper::Report (const ns3::Ptr<ns3::NetDevice>& device, std::ostream& os)
+{
+ Ptr <MeshPointDevice> mp = device->GetObject<MeshPointDevice> ();
+ NS_ASSERT (mp != 0);
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ os << "<MeshPointDevice ReportTime=\"" << Simulator::Now().GetSeconds() << "s\" MpAddress=\"" << mp->GetAddress () << "\">\n";
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = ifaces.begin(); i != ifaces.end(); ++i)
+ {
+ Ptr<WifiNetDevice> device = (*i)->GetObject<WifiNetDevice> ();
+ NS_ASSERT (device != 0);
+ Ptr<MeshWifiInterfaceMac> mac = device->GetMac()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac != 0);
+ mac->Report(os);
+ }
+ Ptr <HwmpProtocol> hwmp = mp->GetObject<HwmpProtocol> ();
+ NS_ASSERT(hwmp != 0);
+ hwmp->Report (os);
+
+ Ptr <PeerManagementProtocol> pmp = mp->GetObject<PeerManagementProtocol> ();
+ NS_ASSERT(pmp != 0);
+ pmp->Report (os);
+ os << "</MeshPointDevice>\n";
+}
+void
+MeshWifiHelper::ResetStats (const ns3::Ptr<ns3::NetDevice>& device)
+{
+ Ptr <MeshPointDevice> mp = device->GetObject<MeshPointDevice> ();
+ NS_ASSERT (mp != 0);
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = ifaces.begin(); i != ifaces.end(); ++i)
+ {
+ Ptr<WifiNetDevice> device = (*i)->GetObject<WifiNetDevice> ();
+ NS_ASSERT (device != 0);
+ Ptr<MeshWifiInterfaceMac> mac = device->GetMac()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac != 0);
+ mac->ResetStats ();
+ }
+ Ptr <HwmpProtocol> hwmp = mp->GetObject<HwmpProtocol> ();
+ NS_ASSERT(hwmp != 0);
+ hwmp->ResetStats ();
+
+ Ptr <PeerManagementProtocol> pmp = mp->GetObject<PeerManagementProtocol> ();
+ NS_ASSERT(pmp != 0);
+ pmp->ResetStats ();
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-helper.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef _MESHWIFIHELPER_H
+#define _MESHWIFIHELPER_H
+
+#include "ns3/wifi-helper.h"
+#include "ns3/nstime.h"
+#include "ns3/peer-management-protocol.h"
+#include "ns3/hwmp-protocol.h"
+#include "ie-dot11s-id.h"
+
+namespace ns3 {
+namespace dot11s {
+
+class WifiChannel;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Helper to create IEEE 802.11s mesh networks
+ */
+class MeshWifiHelper
+{
+public:
+ MeshWifiHelper ();
+ /// Set maximum random start delay
+ void SetRandomStartDelay (Time delay);
+ /**
+ * \brief Spread/not spread frequency channels of MP interfaces.
+ *
+ * If set to true different non-overlaping 20MHz frequency
+ * channels will be assigned to different mesh point interfaces.
+ */
+ void SetSpreadInterfaceChannels (bool);
+
+ /**
+ * \brief Install 802.11s mesh device & protocols on given node
+ *
+ * \param phy Wifi PHY helper
+ * \param nodes List of nodes to install
+ * \param roots List of root mesh points
+ * \param nInterfaces Number of mesh point radio interfaces (= WiFi NICs)
+ *
+ * \return list of created mesh point devices, see MeshPointDevice
+ */
+ NetDeviceContainer Install (const WifiPhyHelper &phyHelper, NodeContainer c, std::vector<uint32_t> roots = std::vector<uint32_t> (), uint32_t nInterfaces = 1) const;
+ /**
+ * \brief Install 802.11s mesh device & protocols on given node
+ *
+ * \param phy Wifi PHY helper
+ * \param node Node to install
+ * \param roots List of root mesh points
+ * \param nInterfaces Number of mesh point radio interfaces (= WiFi NICs)
+ *
+ * \return list of created mesh point devices, see MeshPointDevice
+ */
+ NetDeviceContainer Install (const WifiPhyHelper &phy, Ptr<Node> node, std::vector<uint32_t> roots = std::vector<uint32_t> (), uint32_t nInterfaces = 1) const;
+ static void Report (const ns3::Ptr<ns3::NetDevice>&, std::ostream&);
+ static void ResetStats (const ns3::Ptr<ns3::NetDevice>&);
+private:
+ Time m_randomStartDelay;
+ bool m_spreadInterfaceChannels;
+
+ /// Create single mesh interface NIC
+ Ptr<WifiNetDevice> CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node) const;
+
+};
+} // namespace dot11s
+} //namespace ns3
+
+#endif /* _MESHWIFIHELPER_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,381 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "dot11s-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+namespace dot11s {
+/***********************************************************
+ * Here Mesh Mac Header functionality is defined.
+ ***********************************************************/
+TypeId
+MeshHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::Dot11sMacHeader")
+ .SetParent<Header> ()
+ .AddConstructor<MeshHeader> ()
+ ;
+ return tid;
+}
+MeshHeader::MeshHeader ():
+ m_meshFlags (0),
+ m_meshTtl (0),
+ m_meshSeqno (0),
+ m_addr4 (Mac48Address ()),
+ m_addr5 (Mac48Address ()),
+ m_addr6 (Mac48Address ())
+{
+}
+MeshHeader::~MeshHeader ()
+{
+}
+TypeId
+MeshHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+MeshHeader::SetAddr4 (Mac48Address address)
+{
+ m_addr4 = address;
+}
+void
+MeshHeader::SetAddr5 (Mac48Address address)
+{
+ m_addr5 = address;
+}
+void
+MeshHeader::SetAddr6 (Mac48Address address)
+{
+ m_addr6 = address;
+}
+Mac48Address
+MeshHeader::GetAddr4 () const
+{
+ return m_addr4;
+}
+Mac48Address
+MeshHeader::GetAddr5 () const
+{
+ return m_addr5;
+}
+Mac48Address
+MeshHeader::GetAddr6 () const
+{
+ return m_addr6;
+}
+void
+MeshHeader::SetMeshSeqno (uint32_t seqno)
+{
+ m_meshSeqno = seqno;
+}
+uint32_t
+MeshHeader::GetMeshSeqno () const
+{
+ return m_meshSeqno;
+}
+void
+MeshHeader::SetMeshTtl (uint8_t TTL)
+{
+ m_meshTtl = TTL;
+}
+uint8_t
+MeshHeader::GetMeshTtl () const
+{
+ return m_meshTtl;
+}
+void
+MeshHeader::SetAddressExt (uint8_t num_of_addresses)
+{
+ if (num_of_addresses > 3)
+ return;
+ m_meshFlags |= 0xc0 & (num_of_addresses << 6);
+}
+uint8_t
+MeshHeader::GetAddressExt () const
+{
+ return ((0xc0 & m_meshFlags) >> 6);
+}
+uint32_t
+MeshHeader::GetSerializedSize () const
+{
+ return 6 + GetAddressExt () * 6;
+}
+void
+MeshHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (m_meshFlags);
+ i.WriteU8 (m_meshTtl);
+ i.WriteU32 (m_meshSeqno);
+ uint8_t addresses_to_add = GetAddressExt ();
+ //Writing Address extensions:
+ if ((addresses_to_add == 1) || (addresses_to_add == 3))
+ WriteTo (i, m_addr4);
+ if (addresses_to_add > 1)
+ WriteTo (i, m_addr5);
+ if (addresses_to_add > 1)
+ WriteTo (i, m_addr6);
+}
+uint32_t
+MeshHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint8_t addresses_to_read = 0;
+ m_meshFlags = i.ReadU8 ();
+ m_meshTtl = i.ReadU8 ();
+ m_meshSeqno = i.ReadU32 ();
+ addresses_to_read = (m_meshFlags & 0xc0) >> 6;
+ if ((addresses_to_read == 1) || (addresses_to_read == 3))
+ ReadFrom (i, m_addr4);
+ if (addresses_to_read > 1)
+ ReadFrom (i, m_addr5);
+ if (addresses_to_read > 1)
+ ReadFrom (i, m_addr6);
+ return i.GetDistanceFrom (start);
+}
+void
+MeshHeader::Print (std::ostream &os) const
+{
+ os << "flags = " << (uint16_t)m_meshFlags
+ << "\nttl = " << (uint16_t)m_meshTtl
+ << "\nseqno = " << m_meshSeqno
+ << "\naddr4 = " << m_addr4
+ << "\naddr5 = " << m_addr5
+ << "\naddr6 = " << m_addr6;
+}
+bool operator== (const MeshHeader & a, const MeshHeader & b)
+{
+ return (
+ (a.m_meshFlags == b.m_meshFlags) &&
+ (a.m_meshTtl == b.m_meshTtl) &&
+ (a.m_meshSeqno == b.m_meshSeqno) &&
+ (a.m_addr4 == b.m_addr4) &&
+ (a.m_addr5 == b.m_addr5) &&
+ (a.m_addr6 == b.m_addr6)
+ );
+}
+/**********************************************************
+ * ActionFrame
+ **********************************************************/
+WifiMeshActionHeader::WifiMeshActionHeader ()
+{
+}
+WifiMeshActionHeader::~WifiMeshActionHeader ()
+{
+}
+void
+WifiMeshActionHeader::SetAction (
+ WifiMeshActionHeader::CategoryValue type,
+ WifiMeshActionHeader::ActionValue action)
+{
+ m_category = type;
+
+ switch (type)
+ {
+ case MESH_PEER_LINK_MGT:
+ {
+ m_actionValue = action.peerLink;
+ break;
+ }
+ case MESH_PATH_SELECTION:
+ {
+ m_actionValue = action.pathSelection;
+ break;
+ }
+ case MESH_LINK_METRIC:
+ case MESH_INTERWORK_ACTION:
+ case MESH_RESOURCE_COORDINATION:
+ break;
+ };
+}
+WifiMeshActionHeader::CategoryValue
+WifiMeshActionHeader::GetCategory ()
+{
+ switch (m_category)
+ {
+ case MESH_PEER_LINK_MGT:
+ return MESH_PEER_LINK_MGT;
+ case MESH_LINK_METRIC:
+ return MESH_LINK_METRIC;
+ case MESH_PATH_SELECTION:
+ return MESH_PATH_SELECTION;
+ case MESH_INTERWORK_ACTION:
+ return MESH_INTERWORK_ACTION;
+ case MESH_RESOURCE_COORDINATION:
+ return MESH_RESOURCE_COORDINATION;
+ default:
+ NS_ASSERT (false);
+ return MESH_PEER_LINK_MGT;
+ }
+}
+WifiMeshActionHeader::ActionValue
+WifiMeshActionHeader::GetAction ()
+{
+ ActionValue retval;
+ switch (m_category)
+ {
+ case MESH_PEER_LINK_MGT:
+ switch (m_actionValue)
+ {
+ case PEER_LINK_OPEN:
+ retval.peerLink = PEER_LINK_OPEN;
+ return retval;
+ case PEER_LINK_CONFIRM:
+ retval.peerLink = PEER_LINK_CONFIRM;
+ return retval;
+ case PEER_LINK_CLOSE:
+ retval.peerLink = PEER_LINK_CLOSE;
+ return retval;
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+ case MESH_PATH_SELECTION:
+ switch (m_actionValue)
+ {
+ case PATH_REQUEST:
+ retval.pathSelection = PATH_REQUEST;
+ return retval;
+ case PATH_REPLY:
+ retval.pathSelection = PATH_REPLY;
+ return retval;
+ case PATH_ERROR:
+ retval.pathSelection = PATH_ERROR;
+ return retval;
+ case ROOT_ANNOUNCEMENT:
+ retval.pathSelection = ROOT_ANNOUNCEMENT;
+ return retval;
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+ case MESH_LINK_METRIC:
+ // ???
+ case MESH_INTERWORK_ACTION:
+ // ???
+ case MESH_RESOURCE_COORDINATION:
+ // ???
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+}
+TypeId
+WifiMeshActionHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiMeshActionHeader")
+ .SetParent<Header> ()
+ .AddConstructor<WifiMeshActionHeader> ()
+ ;
+ return tid;
+}
+TypeId
+WifiMeshActionHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+WifiMeshActionHeader::Print (std::ostream &os) const
+{
+}
+uint32_t
+WifiMeshActionHeader::GetSerializedSize () const
+{
+ return 2;
+}
+void
+WifiMeshActionHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteU8 (m_category);
+ start.WriteU8 (m_actionValue);
+}
+uint32_t
+WifiMeshActionHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_category = i.ReadU8 ();
+ m_actionValue = i.ReadU8 ();
+ return i.GetDistanceFrom (start);
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for Dot11sMacHeader
+struct Dot11sMacHeaderBist : public Test
+{
+ Dot11sMacHeaderBist () : Test ("Mesh/802.11s/MeshHeader") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static Dot11sMacHeaderBist g_Dot11sMacHeaderBist;
+
+bool Dot11sMacHeaderBist::RunTests ()
+{
+ bool result (true);
+ {
+ MeshHeader a;
+ a.SetAddressExt(3);
+ a.SetAddr4(Mac48Address ("11:22:33:44:55:66"));
+ a.SetAddr5(Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6(Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ MeshHeader a;
+ a.SetAddressExt(2);
+ a.SetAddr5(Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6(Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ MeshHeader a;
+ a.SetAddressExt(1);
+ a.SetAddr4(Mac48Address ("11:22:33:44:55:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef MESH_WIFI_MAC_HEADER_H
+#define MESH_WIFI_MAC_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Mesh Control field, see IEEE 802.11s draft 3.0 section 7.1.3.5b
+ *
+ * Header format: | Mesh flags: 1 | TTL: 1 | Sequence number: 4 | Address ext.: 0, 6, 12 or 18 |
+ */
+class MeshHeader : public Header
+{
+public:
+ MeshHeader ();
+ ~MeshHeader ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+
+ void SetAddr4 (Mac48Address address);
+ void SetAddr5 (Mac48Address address);
+ void SetAddr6 (Mac48Address address);
+ Mac48Address GetAddr4 () const;
+ Mac48Address GetAddr5 () const;
+ Mac48Address GetAddr6 () const;
+
+ void SetMeshSeqno (uint32_t seqno);
+ uint32_t GetMeshSeqno () const;
+
+ void SetMeshTtl (uint8_t TTL);
+ uint8_t GetMeshTtl () const;
+
+ void SetAddressExt (uint8_t num_of_addresses);
+ uint8_t GetAddressExt () const;
+
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_meshFlags;
+ uint8_t m_meshTtl;
+ uint32_t m_meshSeqno;
+ Mac48Address m_addr4;
+ Mac48Address m_addr5;
+ Mac48Address m_addr6;
+ friend bool operator== (const MeshHeader & a, const MeshHeader & b);
+};
+bool operator== (const MeshHeader & a, const MeshHeader & b);
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief See IEEE 802.11s draft 3.0 section 7.2.3.14
+ *
+ * Header format: | category: 1 | action value: 1 |
+ */
+class WifiMeshActionHeader : public Header
+{
+public:
+ WifiMeshActionHeader ();
+ ~WifiMeshActionHeader ();
+
+ /* Compatible with open80211s implementation */
+ enum CategoryValue //table 7-24 staring from 4
+ {
+ MESH_PEER_LINK_MGT = 30,
+ MESH_LINK_METRIC = 31,
+ MESH_PATH_SELECTION = 32,
+ MESH_INTERWORK_ACTION = 33,
+ MESH_RESOURCE_COORDINATION = 34,
+ };
+ /* Compatible with open80211s implementation */
+ enum PeerLinkMgtActionValue
+ {
+ PEER_LINK_OPEN = 0,
+ PEER_LINK_CONFIRM = 1,
+ PEER_LINK_CLOSE = 2,
+ };
+ enum LinkMetricActionValue
+ {
+ LINK_METRIC_REQUEST = 0,
+ LINK_METRIC_REPORT,
+ };
+ /* Compatible with open80211s implementation */
+ enum PathSelectionActionValue
+ {
+ PATH_REQUEST = 0,
+ PATH_REPLY = 1,
+ PATH_ERROR = 2,
+ ROOT_ANNOUNCEMENT = 3,
+ };
+ enum InterworkActionValue
+ {
+ PORTAL_ANNOUNCEMENT = 0,
+ };
+ enum ResourceCoordinationActionValue
+ {
+ CONGESTION_CONTROL_NOTIFICATION = 0,
+ MDA_SETUP_REQUEST,
+ MDA_SETUP_REPLY,
+ MDAOP_ADVERTISMENT_REQUEST,
+ MDAOP_ADVERTISMENTS,
+ MDAOP_SET_TEARDOWN,
+ BEACON_TIMING_REQUEST,
+ BEACON_TIMING_RESPONSE,
+ TBTT_ADJASTMENT_REQUEST,
+ MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+ };
+ typedef union
+ {
+ enum PeerLinkMgtActionValue peerLink;
+ enum LinkMetricActionValue linkMetrtic;
+ enum PathSelectionActionValue pathSelection;
+ enum InterworkActionValue interwork;
+ enum ResourceCoordinationActionValue resourceCoordination;
+ } ActionValue;
+ void SetAction (enum CategoryValue type,ActionValue action);
+
+ CategoryValue GetCategory ();
+ ActionValue GetAction ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_category;
+ uint8_t m_actionValue;
+};
+} //namespace dot11s
+} // namespace ns3
+#endif /* MESH_WIFI_MAC_HEADER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is doxygen module description, don't include
+ */
+/**
+ * \ingroup mesh
+ * \defgroup dot11s IEEE 802.11s draft
+ *
+ * \brief IEEE 802.11s (mesh) draft standard implementation
+ *
+ * Current model conforms IEEE 802.11s D3.0 draft version and includes
+ * Peer Management Protocol and HWMP (routing) Protocol implementations.
+ *
+ * The multi-interface (aka multi radio) mesh points are supported as an
+ * extensions of ieee draft version 3.0. Note that corresponding helper
+ * creates single interface station by default.
+ */
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/log.h"
+#include "hwmp-mac-plugin.h"
+#include "dot11s-mac-header.h"
+#include "hwmp-protocol.h"
+#include "hwmp-tag.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpMacPlugin");
+HwmpMacPlugin::HwmpMacPlugin (uint32_t ifIndex, Ptr<HwmpProtocol> protocol):
+ m_ifIndex (ifIndex),
+ m_protocol (protocol)
+{
+}
+HwmpMacPlugin::~HwmpMacPlugin ()
+{
+}
+void
+HwmpMacPlugin::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+bool
+HwmpMacPlugin::Receive (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ //TODO: here we fix only mesh header
+ if(header.IsData())
+ {
+ MeshHeader meshHdr;
+ HwmpTag tag;
+ if(packet->PeekPacketTag (tag))
+ {
+ NS_ASSERT (false);
+ }
+ packet->RemoveHeader(meshHdr);
+ m_stats.recvData ++;
+ m_stats.recvDataBytes += packet->GetSize ();
+ //TODO: address extension
+ Mac48Address destination;
+ switch (meshHdr.GetAddressExt ())
+ {
+ case 0:
+ destination = header.GetAddr3 ();
+ break;
+ default:
+ NS_ASSERT(false);
+ };
+ tag.SetSeqno (meshHdr.GetMeshSeqno ());
+ if(meshHdr.GetMeshTtl () == 0)
+ {
+ NS_ASSERT(false);
+ return false;
+ }
+ tag.SetTtl (meshHdr.GetMeshTtl () - 1);
+ if(m_protocol->GetAddress() != destination)
+ packet->AddPacketTag(tag);
+ if (destination == Mac48Address::GetBroadcast ())
+ if(m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (), header.GetAddr4 ()) )
+ return false;
+ }
+ if(header.IsAction())
+ {
+ m_stats.recvMgt ++;
+ m_stats.recvMgtBytes += packet->GetSize ();
+ WifiMeshActionHeader actionHdr;
+ packet->RemoveHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ if(actionHdr.GetCategory () != WifiMeshActionHeader::MESH_PATH_SELECTION)
+ return true;
+ switch (actionValue.pathSelection)
+ {
+ case WifiMeshActionHeader::PATH_REQUEST:
+ {
+ IePreq preq;
+ m_stats.recvPreq ++;
+ packet->RemoveHeader (preq);
+ if(preq.GetOriginatorAddress () == m_protocol->GetAddress ())
+ return false;
+ if (preq.GetTtl () == 0)
+ return false;
+ preq.DecrementTtl ();
+ m_protocol->ReceivePreq (preq, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (), m_parent->GetLinkMetric(header.GetAddr2 ()));
+ return false;
+ }
+ case WifiMeshActionHeader::PATH_REPLY:
+ {
+ IePrep prep;
+ m_stats.recvPrep ++;
+ packet->RemoveHeader (prep);
+ if(prep.GetTtl () == 0)
+ return false;
+ prep.DecrementTtl ();
+ m_protocol->ReceivePrep (prep, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (), m_parent->GetLinkMetric(header.GetAddr2 ()));
+ return false;
+ }
+ case WifiMeshActionHeader::PATH_ERROR:
+ {
+ IePerr perr;
+ m_stats.recvPerr ++;
+ packet->RemoveHeader (perr);
+ m_protocol->ReceivePerr (perr, header.GetAddr2 (), m_ifIndex, header.GetAddr3 ());
+ return false;
+ }
+ case WifiMeshActionHeader::ROOT_ANNOUNCEMENT:
+ return false;
+ }
+ }
+ return true;
+}
+bool
+HwmpMacPlugin::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to)
+{
+ if(!header.IsData ())
+ return true;
+ HwmpTag tag;
+ bool tagExists = packet->RemovePacketTag(tag);
+ if (!tagExists)
+ {
+ //do it this way to silence compiler
+ NS_ASSERT (false);
+ }
+ m_stats.sentData ++;
+ m_stats.sentDataBytes += packet->GetSize ();
+ MeshHeader meshHdr;
+ meshHdr.SetMeshSeqno(tag.GetSeqno());
+ meshHdr.SetMeshTtl(tag.GetTtl());
+ packet->AddHeader(meshHdr);
+ header.SetAddr1(tag.GetAddress());
+ return true;
+}
+void
+HwmpMacPlugin::SendPreq(IePreq preq)
+{
+ m_preqQueue.push_back (preq);
+ SendOnePreq ();
+}
+void
+HwmpMacPlugin::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
+{
+ for(std::vector<IePreq>::iterator i = m_preqQueue.begin (); i != m_preqQueue.end (); i ++)
+ if(i->MayAddAddress(m_protocol->GetAddress ()))
+ {
+ i->AddDestinationAddressElement (m_protocol->GetDoFlag(), m_protocol->GetRfFlag(), dst, dst_seqno);
+ return;
+ }
+ IePreq preq;
+ //fill PREQ:
+ preq.SetHopcount (0);
+ preq.SetTTL (m_protocol->GetMaxTtl ());
+ preq.SetPreqID (m_protocol->GetNextPreqId ());
+ preq.SetOriginatorAddress (m_protocol->GetAddress ());
+ preq.SetOriginatorSeqNumber (originator_seqno);
+ preq.SetLifetime (m_protocol->GetActivePathLifetime ());
+ preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
+ m_preqQueue.push_back (preq);
+ //set iterator position to my preq:
+ SendOnePreq ();
+}
+void
+HwmpMacPlugin::SendOnePreq ()
+{
+ if(m_preqTimer.IsRunning ())
+ return;
+ if (m_preqQueue.size () == 0)
+ return;
+ //reschedule sending PREQ
+ NS_ASSERT (!m_preqTimer.IsRunning());
+ m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpMacPlugin::SendOnePreq, this);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(m_preqQueue[0]);
+ //Action header:
+ WifiMeshActionHeader actionHdr;
+ WifiMeshActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshActionHeader::PATH_REQUEST;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (actionHdr);
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ //Send Management frame
+ std::vector <Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
+ for(std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i ++)
+ {
+ hdr.SetAddr1 (*i);
+ m_stats.sentPreq ++;
+ m_stats.sentMgt ++;
+ m_stats.sentMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame(packet, hdr);
+ }
+ //erase queue
+ m_preqQueue.erase (m_preqQueue.begin());
+}
+void
+HwmpMacPlugin::SendOnePerr()
+{
+ if(m_perrTimer.IsRunning ())
+ return;
+ if(m_myPerr.receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
+ {
+ m_myPerr.receivers.clear ();
+ m_myPerr.receivers.push_back (Mac48Address::GetBroadcast ());
+ }
+ m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpMacPlugin::SendOnePerr, this);
+//Create packet
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(m_myPerr.perr);
+ //Action header:
+ WifiMeshActionHeader actionHdr;
+ WifiMeshActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshActionHeader::PATH_ERROR;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (actionHdr);
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ //Send Management frame
+ for(std::vector<Mac48Address>::const_iterator i = m_myPerr.receivers.begin (); i != m_myPerr.receivers.end (); i ++)
+ {
+ hdr.SetAddr1 (*i);
+ m_stats.sentPerr ++;
+ m_stats.sentMgt ++;
+ m_stats.sentMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame(packet, hdr);
+ }
+ m_myPerr.perr.ResetPerr ();
+ m_myPerr.receivers.clear ();
+}
+void
+HwmpMacPlugin::SendPrep (IePrep prep, Mac48Address receiver)
+{
+ //Create packet
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(prep);
+ //Action header:
+ WifiMeshActionHeader actionHdr;
+ WifiMeshActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshActionHeader::PATH_REPLY;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (actionHdr);
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr1 (receiver);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ //Send Management frame
+ m_stats.sentPrep ++;
+ m_stats.sentMgt ++;
+ m_stats.sentMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame(packet, hdr);
+}
+void
+HwmpMacPlugin::SendPerr(IePerr perr, std::vector<Mac48Address> receivers)
+{
+ m_myPerr.perr.Merge(perr);
+ for(unsigned int i = 0; i < receivers.size (); i ++)
+ {
+ bool should_add = true;
+ for (unsigned int j = 0; j < m_myPerr.receivers.size (); j ++)
+ if(receivers[j] == m_myPerr.receivers[i])
+ should_add = false;
+ if(should_add)
+ m_myPerr.receivers.push_back(receivers[i]);
+ }
+ SendOnePerr ();
+}
+uint32_t
+HwmpMacPlugin::GetLinkMetric(Mac48Address peerAddress) const
+{
+ return m_parent->GetLinkMetric(peerAddress);
+}
+uint16_t
+HwmpMacPlugin::GetChannelId () const
+{
+ return m_parent->GetFrequencyChannel ();
+}
+void
+HwmpMacPlugin::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "sentPreq= \"" << sentPreq << "\"\n"
+ "sentPrep=\"" << sentPrep << "\"\n"
+ "sentPerr=\"" << sentPerr << "\"\n"
+ "recvPreq=\"" << recvPreq << "\"\n"
+ "recvPrep=\"" << recvPrep << "\"\n"
+ "recvPerr=\"" << recvPerr << "\"\n"
+ "sentMgt=\"" << sentMgt << "\"\n"
+ "sentMgtBytes=\"" << (double)sentMgtBytes / 1024.0 << "K\"\n"
+ "recvMgt=\"" << recvMgt << "\"\n"
+ "recvMgtBytes=\"" << (double)recvMgtBytes / 1204.0 << "K\"\n"
+ "sentData=\"" << sentData << "\"\n"
+ "sentDataBytes=\"" << (double)sentDataBytes / 1024.0 << "K\"\n"
+ "recvData=\"" << recvData << "\"\n"
+ "recvDataBytes=\"" << (double)recvDataBytes / 1024.0 << "K\"/>\n";
+}
+void
+HwmpMacPlugin::Report (std::ostream & os) const
+{
+ os << "<HwmpMacPlugin\n"
+ "address =\""<< m_parent->GetAddress () <<"\">\n";
+ m_stats.Print(os);
+ os << "</HwmpMacPlugin>\n";
+}
+void
+HwmpMacPlugin::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+
+} //namespace dot11s
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_STATE_H
+#define HWMP_STATE_H
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ie-dot11s-perr.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+namespace dot11s {
+
+class HwmpProtocol;
+class IePreq;
+class IePrep;
+class IePerr;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Interface MAC plugin for HWMP -- 802.11s routing protocol
+ */
+class HwmpMacPlugin : public MeshWifiInterfaceMacPlugin
+{
+public:
+ HwmpMacPlugin (uint32_t, Ptr<HwmpProtocol>);
+ ~HwmpMacPlugin ();
+ ///\name Inherited from MAC plugin
+ //\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to);
+ /// Update beacon is empty, because HWMP does not know anything about beacons
+ void UpdateBeacon (MeshWifiBeacon & beacon) const {};
+ //\}
+
+private:
+ friend class HwmpProtocol;
+
+ ///\name Intercation with HWMP:
+ //\{
+ void SendPreq(IePreq preq);
+ void SendPrep(IePrep prep, Mac48Address receiver);
+ void SendPerr(IePerr perr, std::vector<Mac48Address> receivers);
+ ///\brief Request a destination. If can not send preq immediately -
+ //add a destination to exisying PREQ generated by me and stored in
+ //PREQ queue
+ ///\param originator_seqno is a sequence number that shall be preq
+ //originator sequenece number
+ ///\param dst_seqno is a sequence number taken from routing table
+ void RequestDestination (Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno);
+ //\}
+
+ /// Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
+ void SendOnePreq ();
+ void SendOnePerr ();
+ /// \return metric to HWMP protocol, needed only by metrics to add
+ //peer as routing entry
+ uint32_t GetLinkMetric (Mac48Address peerAddress) const;
+ uint16_t GetChannelId () const;
+ ///\brief Statistics:
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<HwmpProtocol> m_protocol;
+
+ ///\name PREQ queue and PREQ timer:
+ //\{
+ EventId m_preqTimer;
+ std::vector<IePreq> m_preqQueue;
+ //\}
+ ///\name PERR timer and stored path error
+ //{
+ EventId m_perrTimer;
+ struct MyPerr {
+ IePerr perr;
+ std::vector<Mac48Address> receivers;
+ };
+ MyPerr m_myPerr;
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t sentPreq;
+ uint16_t recvPreq;
+ uint16_t sentPrep;
+ uint16_t recvPrep;
+ uint16_t sentPerr;
+ uint16_t recvPerr;
+ uint16_t sentMgt;
+ uint32_t sentMgtBytes;
+ uint16_t recvMgt;
+ uint32_t recvMgtBytes;
+ uint16_t sentData;
+ uint32_t sentDataBytes;
+ uint16_t recvData;
+ uint32_t recvDataBytes;
+ void Print (std::ostream & os) const;
+ Statistics () :
+ sentPreq (0),
+ recvPreq (0),
+ sentPrep (0),
+ recvPrep (0),
+ sentPerr (0),
+ recvPerr (0),
+ sentMgt (0),
+ sentMgtBytes (0),
+ recvMgt (0),
+ recvMgtBytes (0),
+ sentData (0),
+ sentDataBytes (0),
+ recvData (0),
+ recvDataBytes (0)
+ {}
+ };
+ Statistics m_stats;
+ ///\}
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,986 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "hwmp-protocol.h"
+#include "hwmp-mac-plugin.h"
+#include "hwmp-tag.h"
+#include "hwmp-rtable.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/random-variable.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+#include "ie-dot11s-perr.h"
+
+NS_LOG_COMPONENT_DEFINE ("HwmpProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpProtocol);
+TypeId
+HwmpProtocol::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpProtocol")
+ .SetParent<MeshL2RoutingProtocol> ()
+ .AddConstructor<HwmpProtocol> ()
+ .AddAttribute ("RandomStart", "Random delay at first proactive PREQ",
+ TimeValue (Seconds (0.1)),
+ MakeTimeAccessor (&HwmpProtocol::m_randomStart),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("maxQueueSize",
+ "Maximum number of packets we can store when resolving route",
+ UintegerValue (255),
+ MakeUintegerAccessor (&HwmpProtocol::m_maxQueueSize),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ .AddAttribute ("dot11MeshHWMPmaxPREQretries",
+ "Maximum number of retries before we suppose the destination to be unreachable",
+ UintegerValue (3),
+ MakeUintegerAccessor (&HwmpProtocol::m_dot11MeshHWMPmaxPREQretries),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("dot11MeshHWMPnetDiameterTraversalTime",
+ "Time we suppose the packet to go from one edge of the network to another",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPnetDiameterTraversalTime),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPpreqMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPpreqMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPperrMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPperrMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPactiveRootTimeout",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPactiveRootTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPactivePathTimeout",
+ "Lifetime of reactive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPactivePathTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPpathToRootInterval",
+ "Interval between two successive proactive PREQs",
+ TimeValue (MicroSeconds (1024*2000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPpathToRootInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPrannInterval",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPrannInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("maxTtl",
+ "Initial value of Time To Live field",
+ UintegerValue (32),
+ MakeUintegerAccessor (&HwmpProtocol::m_maxTtl),
+ MakeUintegerChecker<uint8_t> (2)
+ )
+ .AddAttribute ("unicastPerrThreshold",
+ "Maximum number of PERR receivers, when we send a PERR as a chain of unicasts",
+ UintegerValue (32),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastPerrThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("unicastPreqThreshold",
+ "Maximum number of PREQ receivers, when we send a PREQ as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastPreqThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("unicastDataThreshold",
+ "Maximum number ofbroadcast receivers, when we send a broadcast as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastDataThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("doFlag",
+ "Destination only HWMP flag",
+ BooleanValue (false),
+ MakeUintegerAccessor (&HwmpProtocol::m_doFlag),
+ MakeUintegerChecker<bool> ()
+ )
+ .AddAttribute ("rfFlag",
+ "Reply and forward flag",
+ BooleanValue (true),
+ MakeUintegerAccessor (&HwmpProtocol::m_rfFlag),
+ MakeUintegerChecker<bool> ()
+ );
+ return tid;
+}
+HwmpProtocol::HwmpProtocol ():
+ m_dataSeqno (1),
+ m_hwmpSeqno (1),
+ m_preqId (0),
+ m_rtable (CreateObject<HwmpRtable> ()),
+ m_randomStart(Seconds (0.1)),
+ m_maxQueueSize (255),
+ m_dot11MeshHWMPmaxPREQretries (3),
+ m_dot11MeshHWMPnetDiameterTraversalTime (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPpreqMinInterval (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPperrMinInterval (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPactiveRootTimeout (MicroSeconds (1024*5000)),
+ m_dot11MeshHWMPactivePathTimeout (MicroSeconds (1024*5000)),
+ m_dot11MeshHWMPpathToRootInterval (MicroSeconds (1024*2000)),
+ m_dot11MeshHWMPrannInterval (MicroSeconds (1024*5000)),
+ m_isRoot (false),
+ m_maxTtl (32),
+ m_unicastPerrThreshold (32),
+ m_unicastPreqThreshold (1),
+ m_unicastDataThreshold (1),
+ m_doFlag (false),
+ m_rfFlag (false)
+{
+ if(m_isRoot)
+ SetRoot ();
+}
+
+HwmpProtocol::~HwmpProtocol ()
+{
+}
+
+void
+HwmpProtocol::DoDispose ()
+{
+ for (std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.begin (); i != m_preqTimeouts.end(); i ++)
+ i->second.Cancel ();
+ m_preqTimeouts.clear ();
+ m_lastDataSeqno.clear ();
+ m_lastHwmpSeqno.clear ();
+ m_rqueue.clear ();
+ m_rtable = 0;
+
+ //TODO: clear plugins
+}
+
+bool
+HwmpProtocol::RequestRoute (
+ uint32_t sourceIface,
+ const Mac48Address source,
+ const Mac48Address destination,
+ Ptr<Packet> packet,
+ uint16_t protocolType, //ethrnet 'Protocol' field
+ MeshL2RoutingProtocol::RouteReplyCallback routeReply
+)
+{
+ HwmpTag tag;
+ if (sourceIface == GetMeshPoint ()->GetIfIndex())
+ // packet from level 3
+ {
+ if(packet->PeekPacketTag(tag))
+ {
+ NS_ASSERT (false);
+ }
+ //Filling TAG:
+ if(destination == Mac48Address::GetBroadcast ())
+ tag.SetSeqno (m_dataSeqno++);
+ tag.SetTtl (m_maxTtl+1);
+ }
+ else
+ {
+ if(!packet->RemovePacketTag(tag))
+ {
+ NS_ASSERT(false);
+ return false;
+ }
+ if (tag.GetTtl () == 0)
+ return false;
+ tag.DecrementTtl ();
+ }
+ if (destination == Mac48Address::GetBroadcast ())
+ {
+ m_stats.forwardedBroadcast ++;
+ m_stats.forwardedBytes += packet->GetSize ();
+ //channel IDs where we have already sent broadcast:
+ std::vector<uint16_t> channels;
+ for(HwmpPluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ bool should_send = true;
+ for(std::vector<uint16_t>::const_iterator chan = channels.begin(); chan != channels.end(); chan ++)
+ if(*chan == plugin->second->GetChannelId ())
+ should_send = false;
+ if(!should_send)
+ continue;
+ channels.push_back(plugin->second->GetChannelId ());
+ std::vector<Mac48Address> receivers = GetBroadcastReceivers (plugin->first);
+ for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end(); i ++)
+ {
+ Ptr<Packet> packet_copy = packet->Copy();
+ tag.SetAddress (*i);
+ packet_copy->AddPacketTag (tag);
+ routeReply (true, packet_copy, source, destination, protocolType, plugin->first);
+ }
+ }
+ }
+ else
+ return ForwardUnicast(sourceIface, source, destination, packet, protocolType, routeReply, tag.GetTtl ());
+ return true;
+}
+bool
+HwmpProtocol::ForwardUnicast(uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl)
+{
+ NS_ASSERT(destination != Mac48Address::GetBroadcast ());
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive(destination);
+ NS_LOG_DEBUG("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ()<<", RA = "<<result.retransmitter);
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactive ();
+ HwmpTag tag;
+ tag.SetAddress (result.retransmitter);
+ tag.SetTtl (ttl);
+ //seqno and metric is not used;
+ packet->AddPacketTag(tag);
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ //reply immediately:
+ routeReply (true, packet, source, destination, protocolType, result.ifIndex);
+ m_stats.forwardedUnicast ++;
+ m_stats.forwardedBytes += packet->GetSize ();
+ return true;
+ }
+ if (sourceIface != GetMeshPoint ()->GetIfIndex())
+ {
+ //Start path error procedure:
+ NS_LOG_DEBUG ("Must Send PERR");
+ result = m_rtable->LookupReactiveExpired (destination);
+ //1. Lookup expired reactive path. If exists - start path error
+ // procedure towards a next hop of this path
+ //2. If there was no reactive path, we lookup expired proactive
+ // path. If exist - start path error procedure towards path to
+ // root
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactiveExpired ();
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (result.retransmitter);
+ MakePathError (destinations);
+ }
+ m_stats.totalDropped ++;
+ return false;
+ }
+ //Request a destination:
+ result = m_rtable->LookupReactiveExpired (destination);
+ if(ShouldSendPreq(destination))
+ {
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = 0;
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ dst_seqno = result.seqnum;
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->RequestDestination(destination, originator_seqno, dst_seqno);
+ }
+ QueuedPacket pkt;
+ pkt.pkt = packet;
+ pkt.dst = destination;
+ pkt.src = source;
+ pkt.protocol = protocolType;
+ pkt.reply = routeReply;
+ pkt.inInterface = sourceIface;
+ if(QueuePacket (pkt))
+ {
+ m_stats.totalQueued ++;
+ return true;
+ }
+ else
+ {
+ m_stats.totalDropped ++;
+ return false;
+ }
+}
+void
+HwmpProtocol::ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
+{
+ preq.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (preq.GetOriginatorAddress());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric();
+ }
+ else
+ {
+ if (i->second > preq.GetOriginatorSeqNumber ())
+ return;
+ if (i->second == preq.GetOriginatorSeqNumber ())
+ {
+ //find metric
+ std::map<Mac48Address, uint32_t>::const_iterator j = m_lastHwmpMetric.find (preq.GetOriginatorAddress());
+ NS_ASSERT (j != m_lastHwmpSeqno.end());
+ if (j->second <= preq.GetMetric ())
+ return;
+ }
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric();
+ }
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<"Accepted preq from address"<<from<<", preq:"<<preq);
+ std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
+ //Add reactive path to originator:
+ if (
+ ((m_rtable->LookupReactive(preq.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(preq.GetOriginatorAddress ())).metric > preq.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ preq.GetMetric (),
+ MicroSeconds (preq.GetLifetime () *1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ReactivePathResolved (preq.GetOriginatorAddress ());
+ }
+ //Add reactive path for precursor:
+ if (
+ ((m_rtable->LookupReactive(fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(fromMp)).metric > preq.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ fromMp,
+ from,
+ interface,
+ metric,
+ MicroSeconds (preq.GetLifetime () *1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ReactivePathResolved (fromMp);
+ }
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = destinations.begin (); i != destinations.end(); i++)
+ {
+ if ((*i)->GetDestinationAddress () == Mac48Address::GetBroadcast())
+ {
+ //only proactive PREQ contains destination
+ //address as broadcast! Proactive preq MUST
+ //have destination count equal to 1 and
+ //per destination flags DO and RF
+ NS_ASSERT (preq.GetDestCount() == 1);
+ NS_ASSERT (((*i)->IsDo()) && ((*i)->IsRf()));
+ //Add proactive path only if it is the better then existed
+ //before
+ if(
+ ((m_rtable->LookupProactive ()).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupProactive ()).metric > preq.GetMetric ())
+ )
+ m_rtable->AddProactivePath (
+ preq.GetMetric (),
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ MicroSeconds (preq.GetLifetime () * 1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ProactivePathResolved ();
+ if (!preq.IsNeedNotPrep ())
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ preq.GetMetric (),
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ break;
+ }
+ if ((*i)->GetDestinationAddress () == GetAddress ())
+ {
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ (uint32_t)0,
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ NS_ASSERT(m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter != Mac48Address::GetBroadcast ());
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress());
+ continue;
+ }
+ //check if can answer:
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive ((*i)->GetDestinationAddress());
+ if ((! ((*i)->IsDo())) && (result.retransmitter != Mac48Address::GetBroadcast()))
+ {
+ //have a valid information and can answer
+ //!NB: If there is information from peer - set lifetime as
+ //we have got from PREQ, and set the rest lifetime of the
+ //route if the information is correct
+ uint32_t lifetime = result.lifetime.GetMicroSeconds () / 1024;
+ if(lifetime > 0)
+ SendPrep (
+ (*i)->GetDestinationAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ result.metric,
+ preq.GetOriginatorSeqNumber (),
+ result.seqnum +1,
+ lifetime,
+ interface
+ );
+ if ((*i)->IsRf ())
+ (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0
+ else
+ {
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress());
+ continue;
+ }
+ }
+ }
+ //chack if must retransmit:
+ if (preq.GetDestCount () == 0)
+ return;
+ //Forward PREQ to all interfaces:
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<"retransmitting PREQ:"<<preq);
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->SendPreq (preq);
+}
+void
+HwmpProtocol::ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
+{
+ prep.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (prep.GetOriginatorAddress());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber();
+ }
+ else
+ {
+ if (i->second > prep.GetOriginatorSeqNumber ())
+ return;
+ else
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber();
+ }
+ //update routing info
+ //Now add a path to destination and add precursor to source
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", received prep from "<<prep.GetOriginatorAddress ()<<", receiver was:"<<from);
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive(prep.GetDestinationAddress());
+ //Add a reactive path only if it is better than existing:
+ if (
+ ((m_rtable->LookupReactive(prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ prep.GetOriginatorAddress (),
+ from,
+ interface,
+ prep.GetMetric (),
+ MicroSeconds(prep.GetLifetime () * 1024),
+ prep.GetOriginatorSeqNumber ());
+ m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from);
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter);
+ ReactivePathResolved (prep.GetOriginatorAddress ());
+ }
+ if (
+ ((m_rtable->LookupReactive(fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(fromMp)).metric > prep.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ fromMp,
+ from,
+ interface,
+ metric,
+ MicroSeconds(prep.GetLifetime () * 1024),
+ prep.GetOriginatorSeqNumber ());
+ ReactivePathResolved (fromMp);
+ }
+ if(prep.GetDestinationAddress () == GetAddress ())
+ {
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", resolved "<<prep.GetOriginatorAddress ());
+ return;
+ }
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ //try to look for default route
+ result = m_rtable->LookupProactive ();
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ return;
+ //Forward PREP
+ HwmpPluginMap::const_iterator prep_sender = m_interfaces.find (result.ifIndex);
+ NS_ASSERT(prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep (prep, result.retransmitter);
+}
+void
+HwmpProtocol::ReceivePerr (IePerr perr, Mac48Address from, uint32_t interface, Mac48Address fromMp)
+{
+ //Acceptance cretirea:
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", received PERR from "<<from);
+ std::vector<IePerr::FailedDestination> destinations = perr.GetAddressUnitVector ();
+ HwmpRtable::LookupResult result;
+ for(unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ result = m_rtable->LookupReactive (destinations[i].destination);
+ if (
+ (result.retransmitter != from) ||
+ (result.ifIndex != interface) ||
+ (result.seqnum > destinations[i].seqnum)
+ )
+ {
+ perr.DeleteAddressUnit(destinations[i].destination);
+ continue;
+ }
+ }
+ if(perr.GetNumOfDest () == 0)
+ return;
+ MakePathError (destinations);
+}
+void
+HwmpProtocol::SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface)
+{
+ IePrep prep;
+ prep.SetHopcount (0);
+ prep.SetTtl (m_maxTtl);
+ prep.SetDestinationAddress (dst);
+ prep.SetDestinationSeqNumber (destinationSN);
+ prep.SetLifetime (lifetime);
+ prep.SetMetric (0);
+ prep.SetOriginatorAddress (src);
+ prep.SetOriginatorSeqNumber (originatorDsn);
+ HwmpPluginMap::const_iterator prep_sender = m_interfaces.find (interface);
+ NS_ASSERT(prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep (prep, retransmitter);
+ //m_prepCallback (prep, retransmitter);
+
+}
+bool
+HwmpProtocol::Install (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end(); i++)
+ {
+ // Checking for compatible net device
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ return false;
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (mac == 0)
+ return false;
+ // Installing plugins:
+ Ptr<HwmpMacPlugin> hwmpMac = Create<HwmpMacPlugin> (wifiNetDev->GetIfIndex (), this);
+ m_interfaces[wifiNetDev->GetIfIndex ()] = hwmpMac;
+ mac->InstallPlugin (hwmpMac);
+ }
+ mp->SetRoutingProtocol (this);
+ // Mesh point aggregates all installed protocols
+ mp->AggregateObject (this);
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());//* address;
+ return true;
+}
+void
+HwmpProtocol::PeerLinkStatus(Mac48Address meshPointAddress, Mac48Address peerAddress, uint32_t interface, bool status)
+{
+ if(status)
+ return;
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (peerAddress);
+ MakePathError (destinations);
+}
+void
+HwmpProtocol::SetNeighboursCallback(Callback<std::vector<Mac48Address>, uint32_t> cb)
+{
+ m_neighboursCallback = cb;
+}
+bool
+HwmpProtocol::DropDataFrame(uint32_t seqno, Mac48Address source)
+{
+ std::map<Mac48Address, uint32_t,std::less<Mac48Address> >::const_iterator i = m_lastDataSeqno.find (source);
+ if (i == m_lastDataSeqno.end ())
+ m_lastDataSeqno[source] = seqno;
+ else
+ {
+ if (i->second >= seqno)
+ return true;
+ m_lastDataSeqno[source] = seqno;
+ }
+ return false;
+}
+void
+HwmpProtocol::MakePathError (std::vector<IePerr::FailedDestination> destinations)
+{
+ //HwmpRtable increments a sequence number as written in 11B.9.7.2
+ std::vector<std::pair<uint32_t, Mac48Address> > receivers = GetPerrReceivers (destinations);
+ if(receivers.size () == 0)
+ return;
+ IePerr perr;
+ for(unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ perr.AddAddressUnit(destinations[i]);
+ m_rtable->DeleteReactivePath(destinations[i].destination);
+ }
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ std::vector<Mac48Address> receivers_for_interface;
+ for(unsigned int j = 0; j < receivers.size(); j ++)
+ if(i->first == receivers[j].first)
+ receivers_for_interface.push_back(receivers[j].second);
+ i->second->SendPerr (perr, receivers_for_interface);
+ }
+}
+std::vector<std::pair<uint32_t, Mac48Address> >
+HwmpProtocol::GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest)
+{
+ HwmpRtable::PrecursorList retval;
+ for (unsigned int i = 0; i < failedDest.size (); i ++)
+ {
+ HwmpRtable::PrecursorList precursors = m_rtable->GetPrecursors(failedDest[i].destination);
+ m_rtable->DeleteReactivePath (failedDest[i].destination);
+ m_rtable->DeleteProactivePath(failedDest[i].destination);
+ for (unsigned int j = 0; j < precursors.size (); j ++)
+ retval.push_back(precursors[j]);
+ }
+ //Check if we have dublicates in retval and precursors:
+ for (unsigned int i = 0; i < retval.size(); i ++)
+ for (unsigned int j = i+1; j < retval.size(); j ++)
+ if(retval[i].second == retval[j].second)
+ retval.erase(retval.begin() + j);
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetPreqReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if(!m_neighboursCallback.IsNull ())
+ retval = m_neighboursCallback (interface);
+ if ((retval.size() >= m_unicastPreqThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetBroadcastReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if(!m_neighboursCallback.IsNull ())
+ retval = m_neighboursCallback (interface);
+ if ((retval.size() >= m_unicastDataThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+
+bool
+HwmpProtocol::QueuePacket (QueuedPacket packet)
+{
+ if (m_rqueue.size () > m_maxQueueSize)
+ return false;
+ m_rqueue.push_back (packet);
+ return true;
+}
+
+HwmpProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacketByDst (Mac48Address dst)
+{
+ QueuedPacket retval;
+ retval.pkt = NULL;
+ for(std::vector<QueuedPacket>::iterator i = m_rqueue.begin (); i != m_rqueue.end (); i++)
+ if((*i).dst == dst)
+ {
+ retval = (*i);
+ m_rqueue.erase (i);
+ break;
+ }
+ return retval;
+}
+
+HwmpProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacket ()
+{
+ QueuedPacket retval;
+ retval.pkt = NULL;
+ if(m_rqueue.size () != 0)
+ {
+ retval = m_rqueue[0];
+ m_rqueue.erase (m_rqueue.begin ());
+ }
+ return retval;
+}
+
+void
+HwmpProtocol::ReactivePathResolved (Mac48Address dst)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
+ //Send all packets stored for this destination
+ QueuedPacket packet;
+ while (1)
+ {
+ packet = DequeueFirstPacketByDst (dst);
+ if (packet.pkt == NULL)
+ return;
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ packet.pkt->RemovePacketTag(tag);
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ m_stats.forwardedUnicast ++;
+ m_stats.forwardedBytes += packet.pkt->GetSize ();
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+ }
+}
+void
+HwmpProtocol::ProactivePathResolved ()
+{
+ //send all packets to root
+ HwmpRtable::LookupResult result = m_rtable->LookupProactive ();
+ NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
+ QueuedPacket packet;
+ while (1)
+ {
+ packet = DequeueFirstPacket ();
+ if (packet.pkt == NULL)
+ return;
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ NS_ASSERT (packet.pkt->PeekPacketTag(tag));
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ m_stats.forwardedUnicast ++;
+ m_stats.forwardedBytes += packet.pkt->GetSize ();
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+ }
+}
+
+bool
+HwmpProtocol::ShouldSendPreq (Mac48Address dst)
+{
+ std::map<Mac48Address, EventId>::const_iterator i = m_preqTimeouts.find (dst);
+ if (i == m_preqTimeouts.end ())
+ {
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+ &HwmpProtocol::RetryPathDiscovery, this, dst, 0);
+ return true;
+ }
+ return false;
+}
+void
+HwmpProtocol::RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactive ();
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ numOfRetry++;
+ if (numOfRetry > m_dot11MeshHWMPmaxPREQretries)
+ {
+ QueuedPacket packet;
+ //purge queue and delete entry from retryDatabase
+ while (1)
+ {
+ packet = DequeueFirstPacketByDst (dst);
+ if (packet.pkt == NULL)
+ break;
+ m_stats.totalDropped ++;
+ packet.reply (false, packet.pkt, packet.src, packet.dst, packet.protocol, HwmpRtable::MAX_METRIC);
+ }
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = 0;
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ dst_seqno = result.seqnum;
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->RequestDestination(dst, originator_seqno, dst_seqno);
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+ &HwmpProtocol::RetryPathDiscovery, this, dst, numOfRetry);
+}
+//Proactive PREQ routines:
+void
+HwmpProtocol::SetRoot ()
+{
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
+ Time randomStart = Seconds (coefficient.GetValue());
+ m_proactivePreqTimer = Simulator::Schedule (randomStart, &HwmpProtocol::SendProactivePreq, this);
+ NS_LOG_UNCOND("ROOT IS: "<<m_address);
+ SendProactivePreq ();
+ m_isRoot = true;
+}
+void
+HwmpProtocol::UnsetRoot ()
+{
+ m_proactivePreqTimer.Cancel ();
+}
+void
+HwmpProtocol::SendProactivePreq ()
+{
+ IePreq preq;
+ //By default: must answer
+ preq.SetHopcount (0);
+ preq.SetTTL (m_maxTtl);
+ preq.SetLifetime (m_dot11MeshHWMPactiveRootTimeout.GetMicroSeconds () /1024);
+ //\attention: do not forget to set originator address, sequence
+ //number and preq ID in HWMP-MAC plugin
+ preq.AddDestinationAddressElement (true, true, Mac48Address::GetBroadcast (), 0);
+ preq.SetOriginatorAddress(GetAddress ());
+ preq.SetPreqID (GetNextPreqId ());
+ preq.SetOriginatorSeqNumber (GetNextHwmpSeqno ());
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->SendPreq(preq);
+ m_proactivePreqTimer = Simulator::Schedule (m_dot11MeshHWMPpathToRootInterval, &HwmpProtocol::SendProactivePreq, this);
+}
+bool
+HwmpProtocol::GetDoFlag ()
+{
+ return m_doFlag;
+}
+bool
+HwmpProtocol::GetRfFlag ()
+{
+ return m_rfFlag;
+}
+Time
+HwmpProtocol::GetPreqMinInterval ()
+{
+ return m_dot11MeshHWMPpreqMinInterval;
+}
+Time
+HwmpProtocol::GetPerrMinInterval ()
+{
+ return m_dot11MeshHWMPperrMinInterval;
+}
+uint8_t
+HwmpProtocol::GetMaxTtl ()
+{
+ return m_maxTtl;
+}
+uint32_t
+HwmpProtocol::GetNextPreqId ()
+{
+ m_preqId ++;
+ return m_preqId;
+}
+uint32_t
+HwmpProtocol::GetNextHwmpSeqno ()
+{
+ m_hwmpSeqno ++;
+ if(m_hwmpSeqno == 0xffffffff)
+ m_hwmpSeqno = 1;
+ return m_hwmpSeqno;
+}
+uint32_t
+HwmpProtocol::GetActivePathLifetime ()
+{
+ return m_dot11MeshHWMPactivePathTimeout.GetMicroSeconds () / 1024;
+}
+uint8_t
+HwmpProtocol::GetUnicastPerrThreshold()
+{
+ return m_unicastPerrThreshold;
+}
+Mac48Address
+HwmpProtocol::GetAddress ()
+{
+ return m_address;
+}
+//Statistics:
+void HwmpProtocol::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "forwardedUnicast=\"" << forwardedUnicast << "\" "
+ "forwardedBroadcast=\"" << forwardedBroadcast << "\" "
+ "forwardedBytes=\"" << forwardedBytes / 1024 << "K\" "
+ "totalQueued=\"" << totalQueued << "\" "
+ "totalDropped=\"" << totalDropped << "\"/>\n";
+}
+void
+HwmpProtocol::Report (std::ostream & os) const
+{
+ os << "<Hwmp "
+ "address=\"" << m_address << "\"\n"
+ "maxQueueSize=\"" << m_maxQueueSize << "\"\n"
+ "dot11MeshHWMPmaxPREQretries=\"" << (uint16_t)m_dot11MeshHWMPmaxPREQretries << "\"\n"
+ "dot11MeshHWMPnetDiameterTraversalTime=\"" << m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPpreqMinInterval=\"" << m_dot11MeshHWMPpreqMinInterval.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPperrMinInterval=\"" << m_dot11MeshHWMPperrMinInterval.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPactiveRootTimeout=\"" << m_dot11MeshHWMPactiveRootTimeout.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPactivePathTimeout=\"" << m_dot11MeshHWMPactivePathTimeout.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPpathToRootInterval=\"" << m_dot11MeshHWMPpathToRootInterval.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHWMPrannInterval=\"" << m_dot11MeshHWMPrannInterval.GetMilliSeconds () << "ms\"\n"
+ "isRoot=\"" << m_isRoot << "\"\n"
+ "maxTtl=\"" << (uint16_t)m_maxTtl << "\"\n"
+ "unicastPerrThreshold=\"" << (uint16_t)m_unicastPerrThreshold << "\"\n"
+ "unicastPreqThreshold=\"" << (uint16_t)m_unicastPreqThreshold << "\"\n"
+ "unicastDataThreshold=\"" << (uint16_t)m_unicastDataThreshold << "\"\n"
+ "doFlag=\"" << m_doFlag << "\"\n"
+ "rfFlag=\"" << m_rfFlag << "\">\n";
+ m_stats.Print (os);
+ for(HwmpPluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ plugin->second->Report(os);
+ }
+ os << "</Hwmp>\n";
+}
+void
+HwmpProtocol::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+ for(HwmpPluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ plugin->second->ResetStats ();
+}
+
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_PROTOCOL_H
+#define HWMP_PROTOCOL_H
+
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/nstime.h"
+#include "ns3/ie-dot11s-perr.h"
+#include "ns3/event-id.h"
+#include <vector>
+#include <map>
+
+namespace ns3 {
+class MeshPointDevice;
+class Packet;
+class Mac48Address;
+namespace dot11s {
+class HwmpMacPlugin;
+class HwmpRtable;
+class IePreq;
+class IePrep;
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hybrid wireless mesh protocol -- a routing protocol of IEEE 802.11s draft.
+ */
+class HwmpProtocol : public MeshL2RoutingProtocol
+{
+public:
+ static TypeId GetTypeId ();
+ HwmpProtocol ();
+ ~HwmpProtocol ();
+ void DoDispose ();
+
+ /// Route request, inherited from MeshL2RoutingProtocol
+ bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply);
+ /**
+ * \brief Install HWMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, HWMP protocol can be accessed
+ * via MeshPointDevice::GetObject<dot11s::HwmpProtocol>();
+ */
+ bool Install (Ptr<MeshPointDevice>);
+ void PeerLinkStatus(Mac48Address meshPontAddress, Mac48Address peerAddress, uint32_t interface,bool status);
+ ///\brief This callback is used to obtain active neighbours on a
+ //given interface
+ ///\param interface is the interface ID
+ void SetNeighboursCallback(Callback<std::vector<Mac48Address>, uint32_t> cb);
+ ///\name Proactive PREQ mechanism:
+ ///\{
+ void SetRoot ();
+ void UnsetRoot ();
+ ///\}
+ ///\brief Statistics:
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ friend class HwmpMacPlugin;
+
+ /// Like RequestRoute, but for unicast packets
+ bool ForwardUnicast (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl);
+
+ ///\name Interaction with HWMP MAC plugin
+ //\{
+ void ReceivePreq(IePreq preq, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric);
+ void ReceivePrep(IePrep prep, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric);
+ void ReceivePerr(IePerr perr, Mac48Address from, uint32_t interface, Mac48Address fromMp);
+ void SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface);
+
+ ///\brief forms a path error information element when list of destination fails on a given interface
+ void MakePathError (std::vector<IePerr::FailedDestination> destinations);
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<std::pair<uint32_t, Mac48Address> > GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest);
+
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<Mac48Address> GetPreqReceivers (uint32_t interface);
+ /// \return list of addresses where a broadcast should be
+ //retransmitted
+ std::vector<Mac48Address> GetBroadcastReceivers (uint32_t interface);
+ /**
+ * \brief MAC-plugin asks wether the frame can be dropeed. Protocol automatically updates seqno.
+ *
+ * \return true if frame can be dropped
+ * \param uint32_t is the seqno
+ * \param Mac48Address is the mesh source addrress of the frame
+ */
+ bool DropDataFrame(uint32_t, Mac48Address);
+ //\}
+private:
+ /// Packet waiting its routing information
+ struct QueuedPacket {
+ Ptr<Packet> pkt; ///< the packet
+ Mac48Address src; ///< src address
+ Mac48Address dst; ///< dst address
+ uint16_t protocol; ///< protocol number
+ uint32_t inInterface; ///< incoming device interface ID. (if packet has come from upper layers, this is Mesh point ID)
+ RouteReplyCallback reply; ///< how to reply
+
+ QueuedPacket () : pkt(0), protocol(0), inInterface(0) {}
+ };
+
+ ///\name Methods related to Queue/Dequeue procedures
+ //\{
+ bool QueuePacket (QueuedPacket packet);
+ QueuedPacket DequeueFirstPacketByDst (Mac48Address dst);
+ QueuedPacket DequeueFirstPacket ();
+ void ReactivePathResolved (Mac48Address dst);
+ void ProactivePathResolved ();
+ //\}
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t forwardedUnicast;
+ uint16_t forwardedBroadcast;
+ uint32_t forwardedBytes;
+ uint16_t totalQueued;
+ uint16_t totalDropped;
+
+ void Print (std::ostream & os) const;
+ Statistics () : forwardedUnicast (0), forwardedBroadcast (0), forwardedBytes (0), totalQueued (0), totalDropped (0) {}
+ };
+ Statistics m_stats;
+ ///\}
+ ///\name Methods responsible for path discovery retry procedure:
+ //\{
+ /**
+ * \brief checks when the last path discovery procedure was started for a given destination.
+ *
+ * If the retry counter has not achieved the maximum level - preq should not be sent
+ */
+ bool ShouldSendPreq (Mac48Address dst);
+
+ /**
+ * \brief Generates PREQ retry when retry timeout has expired and route is still unresolved.
+ *
+ * When PREQ retry has achieved the maximum level - retry mechanish should be cancelled
+ */
+ void RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry);
+ //\}
+
+ ///\name Proactive Preq routines:
+ //\{
+ void SendProactivePreq ();
+ //\}
+ ///\return address of MeshPointDevice
+ Mac48Address GetAddress ();
+private:
+ typedef std::map<uint32_t, Ptr<HwmpMacPlugin> > HwmpPluginMap;
+ HwmpPluginMap m_interfaces;
+ Mac48Address m_address;
+ uint32_t m_dataSeqno;
+ uint32_t m_hwmpSeqno;
+ uint32_t m_preqId;
+ ///\name Sequence number filters
+ //\{
+ /// Data sequence number database
+ std::map<Mac48Address, uint32_t> m_lastDataSeqno;
+ /// DSN databse
+ std::map<Mac48Address, uint32_t> m_lastHwmpSeqno;
+ /// Metric database
+ std::map<Mac48Address, uint32_t> m_lastHwmpMetric;
+ //\}
+
+ /// Routing table
+ Ptr<HwmpRtable> m_rtable;
+
+ ///\name Timers:
+ //\{
+ std::map<Mac48Address, EventId> m_preqTimeouts;
+ EventId m_proactivePreqTimer;
+ //Random start in Proactive PREQ propagation
+ Time m_randomStart;
+ //\}
+
+ /// Packet Queue
+ std::vector<QueuedPacket> m_rqueue;
+private:
+ ///\name HWMP-protocol parameters (attributes of GetTypeId)
+ //\{
+ uint16_t m_maxQueueSize;
+ uint8_t m_dot11MeshHWMPmaxPREQretries;
+ Time m_dot11MeshHWMPnetDiameterTraversalTime;
+ Time m_dot11MeshHWMPpreqMinInterval;
+ Time m_dot11MeshHWMPperrMinInterval;
+ Time m_dot11MeshHWMPactiveRootTimeout;
+ Time m_dot11MeshHWMPactivePathTimeout;
+ Time m_dot11MeshHWMPpathToRootInterval;
+ Time m_dot11MeshHWMPrannInterval;
+ bool m_isRoot;
+ uint8_t m_maxTtl;
+ uint8_t m_unicastPerrThreshold;
+ uint8_t m_unicastPreqThreshold;
+ uint8_t m_unicastDataThreshold;
+ bool m_doFlag;
+ bool m_rfFlag;
+ //\}
+
+ ///\name Methods needed by HwmpMacLugin to access protocol parameters:
+ //\{
+ bool GetDoFlag ();
+ bool GetRfFlag ();
+ Time GetPreqMinInterval ();
+ Time GetPerrMinInterval ();
+ uint8_t GetMaxTtl ();
+ uint32_t GetNextPreqId ();
+ uint32_t GetNextHwmpSeqno ();
+ uint32_t GetActivePathLifetime ();
+ uint8_t GetUnicastPerrThreshold ();
+ //\}
+ Callback <std::vector<Mac48Address>, uint32_t> m_neighboursCallback;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/object.h"
+#include "ns3/assert.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/log.h"
+
+#include "hwmp-rtable.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpRtable");
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpRtable);
+
+TypeId
+HwmpRtable::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpRtable")
+ .SetParent<Object> ()
+ .AddConstructor<HwmpRtable> ();
+ return tid;
+}
+
+HwmpRtable::HwmpRtable ()
+{
+ DeleteProactivePath ();
+}
+
+HwmpRtable::~HwmpRtable ()
+{
+ DoDispose ();
+}
+
+void
+HwmpRtable::DoDispose ()
+{
+ m_routes.clear ();
+}
+
+void
+HwmpRtable::AddReactivePath (
+ Mac48Address destination,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ uint32_t metric,
+ Time lifetime,
+ uint32_t seqnum
+)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ ReactiveRoute newroute;
+ m_routes[destination] = newroute;
+ }
+ i = m_routes.find (destination);
+ NS_ASSERT (i != m_routes.end());
+ i->second.retransmitter = retransmitter;
+ i->second.interface = interface;
+ i->second.metric = metric;
+ i->second.whenExpire = Simulator::Now() + lifetime;
+ i->second.seqnum = seqnum;
+}
+
+void
+HwmpRtable::AddProactivePath (
+ uint32_t metric,
+ Mac48Address root,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ Time lifetime,
+ uint32_t seqnum
+)
+{
+ m_root.root = root;
+ m_root.retransmitter = retransmitter;
+ m_root.metric = metric;
+ m_root.whenExpire = Simulator::Now() + lifetime;
+ m_root.seqnum = seqnum;
+ m_root.interface = interface;
+}
+
+void
+HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress)
+{
+ std::pair<uint32_t, Mac48Address> precursor;
+ precursor.first = precursorInterface;
+ precursor.second = precursorAddress;
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ {
+ bool should_add = true;
+ for (unsigned int j = 0 ; j < i->second.precursors.size (); j ++)
+ //NB: Only one active route may exist, so do not check
+ //interface ID, just address
+ if (i->second.precursors[j].second == precursorAddress)
+ {
+ should_add = false;
+ break;
+ }
+ if (should_add)
+ i->second.precursors.push_back (precursor);
+ }
+ if(m_root.root == destination)
+ for (unsigned int j = 0 ; j < m_root.precursors.size (); j ++)
+ if (m_root.precursors[j].second == precursorAddress)
+ return;
+ m_root.precursors.push_back(precursor);
+}
+
+void
+HwmpRtable::DeleteProactivePath ()
+{
+ m_root.precursors.clear ();
+ m_root.interface = INTERFACE_ANY;
+ m_root.metric = MAX_METRIC;
+ m_root.retransmitter = Mac48Address::GetBroadcast ();
+ m_root.seqnum = 0;
+ m_root.whenExpire = Simulator::Now ();
+}
+
+void
+HwmpRtable::DeleteProactivePath (Mac48Address root)
+{
+ if(m_root.root == root)
+ DeleteProactivePath ();
+}
+
+void
+HwmpRtable::DeleteReactivePath (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ m_routes.erase (i);
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactive (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ return LookupResult ();
+ if ((i->second.whenExpire < Simulator::Now ()) && (i->second.whenExpire != Seconds (0)))
+ {
+ NS_LOG_DEBUG ("Reactive route has expired, sorry.");
+ return LookupResult();
+ }
+ return LookupReactiveExpired (destination);
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactiveExpired (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ return LookupResult ();
+ return LookupResult (
+ i->second.retransmitter,
+ i->second.interface,
+ i->second.metric, i->second.seqnum,
+ i->second.whenExpire - Simulator::Now ()
+ );
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactive ()
+{
+ if (m_root.whenExpire < Simulator::Now ())
+ {
+ NS_LOG_DEBUG ("Proactive route has expired and will be deleted, sorry.");
+ DeleteProactivePath ();
+ }
+ return LookupProactiveExpired ();
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactiveExpired ()
+{
+ return LookupResult(m_root.retransmitter, m_root.interface, m_root.metric, m_root.seqnum, m_root.whenExpire - Simulator::Now ());
+}
+
+std::vector<IePerr::FailedDestination>
+HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress)
+{
+ IePerr::FailedDestination dst;
+ std::vector<IePerr::FailedDestination> retval;
+ for (std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.begin (); i != m_routes.end(); i++)
+ if (i->second.retransmitter == peerAddress)
+ {
+ dst.destination = i->first;
+ i->second.seqnum ++;
+ dst.seqnum = i->second.seqnum;
+ retval.push_back (dst);
+ }
+ //Lookup a path to root
+ if (m_root.retransmitter == peerAddress)
+ {
+ dst.destination = m_root.root;
+ dst.seqnum = m_root.seqnum;
+ retval.push_back (dst);
+ }
+ return retval;
+}
+
+HwmpRtable::PrecursorList
+HwmpRtable::GetPrecursors (Mac48Address destination)
+{
+ //We suppose that no dublicates here can be
+ PrecursorList retval;
+ std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination);
+ if (route != m_routes.end ())
+ for (unsigned int i = 0; i < route->second.precursors.size (); i ++)
+ retval.push_back(route->second.precursors[i]);
+ if (m_root.root == destination)
+ for (unsigned int i = 0; i < m_root.precursors.size (); i ++)
+ {
+ bool should_add = true;
+ for(unsigned int j = 0; j < retval.size(); j ++)
+ if(retval[j].second == m_root.precursors[i].second)
+ {
+ should_add = false;
+ break;
+ }
+ if(should_add)
+ retval.push_back(m_root.precursors[i]);
+ }
+ return retval;
+}
+
+bool HwmpRtable::LookupResult::operator==(const HwmpRtable::LookupResult & o) const
+{
+ return (retransmitter == o.retransmitter
+ && ifIndex == o.ifIndex
+ && metric == o.metric
+ && seqnum == o.seqnum
+ );
+}
+
+bool HwmpRtable::LookupResult::IsValid() const
+{
+ return !( retransmitter == Mac48Address::GetBroadcast ()
+ && ifIndex == INTERFACE_ANY
+ && metric == MAX_METRIC
+ && seqnum == 0
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Unit test for HwmpRtable
+class HwmpRtableTest : public Test
+{
+public:
+ HwmpRtableTest ();
+ virtual bool RunTests();
+
+private:
+ void Test1 ();
+ void Test2 ();
+ void Test3 ();
+ void Test4 ();
+
+private:
+ bool result;
+
+ Mac48Address dst;
+ Mac48Address hop;
+ uint32_t iface;
+ uint32_t metric;
+ uint32_t seqnum;
+ Time expire;
+ Ptr<HwmpRtable> table;
+};
+
+/// Test instance
+static HwmpRtableTest g_HwmpRtableTest;
+
+HwmpRtableTest::HwmpRtableTest () : Test ("Mesh/802.11s/HwmpRtable"),
+ result(true),
+ dst ("01:00:00:01:00:01"),
+ hop ("01:00:00:01:00:03"),
+ iface (8010),
+ metric (10),
+ seqnum (1),
+ expire (Seconds (10))
+{
+}
+
+void HwmpRtableTest::Test1 ()
+{
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+
+ // Reactive path
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupReactive (dst) == correct);
+ table->DeleteReactivePath (dst);
+ NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ());
+
+ // Proactive
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupProactive () == correct);
+ table->DeleteProactivePath (dst);
+ NS_TEST_ASSERT (! table->LookupProactive ().IsValid ());
+}
+
+void HwmpRtableTest::Test2 ()
+{
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+}
+
+void HwmpRtableTest::Test3 ()
+{
+ // this is assumed to be called when path records are already expired
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+ NS_TEST_ASSERT (table->LookupReactiveExpired (dst) == correct);
+ NS_TEST_ASSERT (table->LookupProactiveExpired () == correct);
+
+ NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ());
+ NS_TEST_ASSERT (! table->LookupProactive ().IsValid ());
+}
+
+void HwmpRtableTest::Test4 ()
+{
+ // TODO: test AddPrecursor and GetPrecursors
+}
+
+bool HwmpRtableTest::RunTests ()
+{
+ table = CreateObject<HwmpRtable> ();
+
+ Simulator::Schedule (Seconds (0), & HwmpRtableTest::Test1, this);
+ Simulator::Schedule (Seconds (1), & HwmpRtableTest::Test2, this);
+ Simulator::Schedule (expire + Seconds (2), & HwmpRtableTest::Test3, this);
+ Simulator::Schedule (expire + Seconds (3), & HwmpRtableTest::Test4, this);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_RTABLE_H
+#define HWMP_RTABLE_H
+
+#include <map>
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ie-dot11s-perr.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Routing table for HWMP -- 802.11s routing protocol
+ */
+class HwmpRtable : public Object
+{
+public:
+ /// Means all interfaces
+ const static uint32_t INTERFACE_ANY = 0xffffffff;
+ /// Maximum (the best?) path metric
+ const static uint32_t MAX_METRIC = 0xffffffff;
+
+ /// Route lookup result, return type of LookupXXX methods
+ struct LookupResult
+ {
+ Mac48Address retransmitter;
+ uint32_t ifIndex;
+ uint32_t metric;
+ uint32_t seqnum;
+ Time lifetime;
+
+ LookupResult(Mac48Address r = Mac48Address::GetBroadcast (),
+ uint32_t i = INTERFACE_ANY,
+ uint32_t m = MAX_METRIC,
+ uint32_t s = 0,
+ Time l = Seconds(0.0))
+ : retransmitter (r),
+ ifIndex (i),
+ metric (m),
+ seqnum (s),
+ lifetime (l)
+ {
+ }
+
+ /// True for valid route
+ bool IsValid() const;
+ /// Compare route lookup results, used by tests
+ bool operator==(const LookupResult & o) const;
+ };
+ /// Path precursor = {MAC, interface ID}
+ typedef std::vector<std::pair<uint32_t, Mac48Address> > PrecursorList;
+
+public:
+ static TypeId GetTypeId ();
+ HwmpRtable ();
+ ~HwmpRtable ();
+ void DoDispose ();
+
+ ///\name Add/delete paths
+ //\{
+ void AddReactivePath (
+ Mac48Address destination,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ uint32_t metric,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddProactivePath (
+ uint32_t metric,
+ Mac48Address root,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress);
+ PrecursorList GetPrecursors (Mac48Address destination);
+ void DeleteProactivePath ();
+ void DeleteProactivePath (Mac48Address root);
+ void DeleteReactivePath (Mac48Address destination);
+ //\}
+
+ ///\name Lookup
+ //\{
+ /// Lookup path to destination
+ LookupResult LookupReactive (Mac48Address destination);
+ /// Return all reactive paths, including expired
+ LookupResult LookupReactiveExpired (Mac48Address destination);
+ /// Find proactive path to tree root. Note that calling this method has side effect of deleting expired proactive path
+ LookupResult LookupProactive ();
+ /// Return all proactive paths, including expired
+ LookupResult LookupProactiveExpired ();
+ //\}
+
+ /// When peer link with a given MAC-address fails - it returns list of unreachable destination addresses
+ std::vector<IePerr::FailedDestination> GetUnreachableDestinations (Mac48Address peerAddress);
+
+private:
+ /// Route found in reactive mode
+ struct ReactiveRoute
+ {
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+ /// Route fond in proactive mode
+ struct ProactiveRoute
+ {
+ Mac48Address root;
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+
+ /// List of routes
+ std::map<Mac48Address, ReactiveRoute> m_routes;
+ /// Path to proactive tree root MP
+ ProactiveRoute m_root;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "hwmp-tag.h"
+
+namespace ns3 {
+namespace dot11s{
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpTag);
+//Class HwmpTag:
+HwmpTag::HwmpTag ():
+ m_address (Mac48Address::GetBroadcast ()),
+ m_ttl (0),
+ m_metric (0),
+ m_seqno (0)
+{
+}
+
+HwmpTag::~HwmpTag ()
+{
+}
+
+void
+HwmpTag::SetAddress (Mac48Address retransmitter)
+{
+ m_address = retransmitter;
+}
+
+Mac48Address
+HwmpTag::GetAddress ()
+{
+ return m_address;
+}
+
+void
+HwmpTag::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+
+uint8_t
+HwmpTag::GetTtl ()
+{
+ return m_ttl;
+}
+
+void
+HwmpTag::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+
+uint32_t
+HwmpTag::GetMetric ()
+{
+ return m_metric;
+}
+
+void
+HwmpTag::SetSeqno (uint32_t seqno)
+{
+ m_seqno = seqno;
+}
+
+uint32_t
+HwmpTag::GetSeqno ()
+{
+ return m_seqno;
+}
+
+TypeId
+HwmpTag::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpTag")
+ .SetParent<Tag> ()
+ .AddConstructor<HwmpTag> ();
+ return tid;
+}
+
+TypeId
+HwmpTag::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+HwmpTag::GetSerializedSize () const
+{
+ return
+ 6 //address
+ +1 //ttl
+ +4 //metric
+ +4; //seqno
+}
+
+void
+HwmpTag::Serialize (TagBuffer i) const
+{
+ uint8_t address[6];
+ int j;
+ m_address.CopyTo (address);
+ i.WriteU8 (m_ttl);
+ i.WriteU32 (m_metric);
+ i.WriteU32(m_seqno);
+ for (j = 0; j < 6; j ++)
+ i.WriteU8 (address[j]);
+}
+
+void
+HwmpTag::Deserialize (TagBuffer i)
+{
+ uint8_t address[6];
+ int j;
+ m_ttl = i.ReadU8 ();
+ m_metric = i.ReadU32 ();
+ m_seqno = i.ReadU32 ();
+ for (j = 0; j < 6; j ++)
+ address[j] = i.ReadU8 ();
+ m_address.CopyFrom (address);
+}
+
+void
+HwmpTag::Print (std::ostream &os) const
+{
+ os << "address=" << m_address;
+ os << "ttl=" << m_ttl;
+ os << "metrc=" << m_metric;
+ os << "seqno=" << m_seqno;
+}
+void
+HwmpTag::DecrementTtl ()
+{
+ m_ttl --;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef HWMP_TAG_H
+#define HWMP_TAG_H
+
+#include "ns3/tag.h"
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hwmp tag implements interaction between HWMP
+ * protocol and MeshWifiMac
+ *
+ * \details Hwmp tag keeps the following:
+ * 1. When packet is passed from Hwmp to 11sMAC:
+ * - retransmitter address,
+ * - TTL value,
+ * 2. When packet is passed to Hwmp from 11sMAC:
+ * - lasthop address,
+ * - TTL value,
+ * - metric value (metric of link is recalculated
+ * at each packet, but routing table stores metric
+ * obtained during path discovery procedure)
+ */
+class HwmpTag : public Tag
+{
+public:
+ HwmpTag ();
+ ~HwmpTag ();
+ void SetAddress (Mac48Address retransmitter);
+ Mac48Address GetAddress ();
+ void SetTtl (uint8_t ttl);
+ uint8_t GetTtl ();
+ void SetMetric (uint32_t metric);
+ uint32_t GetMetric ();
+ void SetSeqno (uint32_t seqno);
+ uint32_t GetSeqno ();
+ void DecrementTtl ();
+
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (TagBuffer i) const;
+ virtual void Deserialize (TagBuffer i);
+ virtual void Print (std::ostream &os) const;
+private:
+ Mac48Address m_address;
+ uint8_t m_ttl;
+ uint32_t m_metric;
+ uint32_t m_seqno;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-beacon-timing.h"
+#include "ns3/log.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/*******************************************
+ * IeBeaconTimingUnit
+ *******************************************/
+IeBeaconTimingUnit::IeBeaconTimingUnit ():
+ m_aid (0),
+ m_lastBeacon (0),
+ m_beaconInterval (0)
+{
+}
+
+void
+IeBeaconTimingUnit::SetAid (uint8_t aid)
+{
+ m_aid = aid;
+}
+
+void
+IeBeaconTimingUnit::SetLastBeacon (uint16_t lastBeacon)
+{
+ m_lastBeacon = lastBeacon;
+}
+
+void
+IeBeaconTimingUnit::SetBeaconInterval (uint16_t beaconInterval)
+{
+ m_beaconInterval = beaconInterval;
+}
+
+uint8_t
+IeBeaconTimingUnit::GetAid () const
+{
+ return m_aid;
+}
+
+uint16_t
+IeBeaconTimingUnit::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+
+uint16_t
+IeBeaconTimingUnit::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+/*******************************************
+ * IeBeaconTiming
+ *******************************************/
+IeBeaconTiming::IeBeaconTiming ():
+ m_numOfUnits (0)
+{
+}
+
+IeBeaconTiming::NeighboursTimingUnitsList
+IeBeaconTiming::GetNeighboursTimingElementsList ()
+{
+ return m_neighbours;
+}
+
+void
+IeBeaconTiming::AddNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon, //MicroSeconds!
+ Time beacon_interval //MicroSeconds!
+)
+{
+ if (m_numOfUnits == 50)
+ return;
+ //Firs we lookup if this element already exists
+ for (NeighboursTimingUnitsList::const_iterator i = m_neighbours.begin (); i != m_neighbours.end(); i++)
+ if (
+ ((*i)->GetAid () == AidToU8(aid))
+ && ((*i)->GetLastBeacon () == TimestampToU16(last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16(beacon_interval))
+ )
+ return;
+ Ptr<IeBeaconTimingUnit>new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (AidToU8(aid));
+ new_element->SetLastBeacon (TimestampToU16(last_beacon));
+ new_element->SetBeaconInterval (BeaconIntervalToU16(beacon_interval));
+ m_neighbours.push_back (new_element);
+ m_numOfUnits++;
+}
+
+void
+IeBeaconTiming::DelNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon, //MicroSeconds!
+ Time beacon_interval //MicroSeconds!
+)
+{
+ for (NeighboursTimingUnitsList::iterator i = m_neighbours.begin (); i != m_neighbours.end(); i++)
+ if (
+ ((*i)->GetAid () == AidToU8(aid))
+ && ((*i)->GetLastBeacon () == TimestampToU16(last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16(beacon_interval))
+ )
+ {
+ m_neighbours.erase (i);
+ m_numOfUnits--;
+ break;
+ }
+}
+
+void
+IeBeaconTiming::ClearTimingElement ()
+{
+ uint16_t to_delete = 0;
+ uint16_t i;
+ for (NeighboursTimingUnitsList::iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ {
+ to_delete++;
+ (*j) = 0;
+ }
+ for (i = 0; i < to_delete; i ++)
+ m_neighbours.pop_back ();
+ m_neighbours.clear ();
+
+}
+
+uint8_t
+IeBeaconTiming::GetInformationSize () const
+{
+ return (5*m_numOfUnits);
+}
+
+void
+IeBeaconTiming::PrintInformation (std::ostream& os) const
+{
+ os <<"Number of units: " << (uint16_t)m_numOfUnits << "\n";
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ os<< "AID=" << (uint16_t)(*j)->GetAid () << ", Last beacon was at "
+ << (*j)->GetLastBeacon ()<<", with beacon interval " << (*j)->GetBeaconInterval () << "\n";
+}
+
+void
+IeBeaconTiming::SerializeInformation (Buffer::Iterator i) const
+{
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ {
+ i.WriteU8 ((*j)->GetAid ());
+ i.WriteHtolsbU16 ((*j)->GetLastBeacon ());
+ i.WriteHtolsbU16 ((*j)->GetBeaconInterval ());
+ }
+}
+uint8_t
+IeBeaconTiming::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_numOfUnits = length/5;
+ for (int j = 0; j < m_numOfUnits; j ++)
+ {
+ Ptr<IeBeaconTimingUnit> new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (i.ReadU8());
+ new_element->SetLastBeacon (i.ReadLsbtohU16());
+ new_element->SetBeaconInterval (i.ReadLsbtohU16());
+ m_neighbours.push_back (new_element);
+ }
+ return i.GetDistanceFrom (start);
+};
+
+uint16_t
+IeBeaconTiming::TimestampToU16 (Time x)
+{
+ return ((uint16_t) ((x.GetMicroSeconds() >> 8)&0xffff));
+};
+
+uint16_t
+IeBeaconTiming::BeaconIntervalToU16 (Time x)
+{
+ return ((uint16_t) (x.GetMicroSeconds() >>10)&0xffff);
+};
+
+uint8_t
+IeBeaconTiming::AidToU8 (uint16_t x)
+{
+ return (uint8_t) (x&0xff);
+};
+
+bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b)
+{
+ return (
+ (a.GetAid () == b.GetAid ()) &&
+ (a.GetLastBeacon () == b.GetLastBeacon()) &&
+ (a.GetBeaconInterval () == b.GetBeaconInterval ())
+ );
+}
+bool operator== (const IeBeaconTiming & a, const IeBeaconTiming& b)
+{
+ if(a.m_numOfUnits != b.m_numOfUnits)
+ return false;
+ for(unsigned int i = 0; i < a.m_neighbours.size (); i ++)
+ if(!(*PeekPointer(a.m_neighbours[i]) == *PeekPointer(b.m_neighbours[i])))
+ return false;
+ return true;
+}
+
+#ifdef RUN_SELF_TESTS
+struct IeBeaconTimingBist : public IeTest
+{
+ IeBeaconTimingBist () : IeTest ("Mesh/802.11s/IE/BeaconTiming") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeBeaconTimingBist g_IePerrBist;
+
+bool IeBeaconTimingBist::RunTests ()
+{
+ bool result(true);
+ // create test information element
+ IeBeaconTiming a;
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (1,Seconds(1.0), Seconds(4.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (2,Seconds(2.0), Seconds(3.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (3,Seconds(3.0), Seconds(2.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (4,Seconds(4.0), Seconds(1.0));
+
+ result = TestRoundtripSerialization (a);
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_TIMING_ELEMENT_H
+#define WIFI_TIMING_ELEMENT_H
+
+#include <vector>
+#include "ns3/nstime.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes one unit of beacon timing element
+ */
+class IeBeaconTimingUnit : public RefCountBase
+{
+public:
+ IeBeaconTimingUnit ();
+ void SetAid (uint8_t aid);
+ void SetLastBeacon (uint16_t last_beacon);
+ void SetBeaconInterval (uint16_t beacon_interval);
+
+ uint8_t GetAid () const;
+ uint16_t GetLastBeacon () const;
+ uint16_t GetBeaconInterval () const;
+ /**
+ * \brief Least significant octet of AID:
+ */
+ uint8_t m_aid;
+ /**
+ * \brief Last time we received a beacon in accordance with a
+ * local TSF measured in 256 microseconds unit:
+ */
+ uint16_t m_lastBeacon;
+ /**
+ * \brief Beacon interval of remote mesh point:
+ */
+ uint16_t m_beaconInterval;
+ friend bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.89 of 802.11s draft 2.07
+ */
+class IeBeaconTiming : public WifiInformationElement
+{
+public:
+ /**
+ * \ingroup dot11s
+ * This type is a list of timing elements obtained from neigbours with their beacons:
+ */
+ typedef std::vector< Ptr<IeBeaconTimingUnit> > NeighboursTimingUnitsList;
+
+ IeBeaconTiming ();
+ /**
+ * This methods are needed for beacon collision
+ * avoidance module:
+ */
+ NeighboursTimingUnitsList GetNeighboursTimingElementsList ();
+ void AddNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void DelNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void ClearTimingElement ();
+private:
+ WifiElementId ElementId () const {
+ return IE11S_BEACON_TIMING;
+ }
+ uint8_t GetInformationSize () const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+ /**
+ * Converters:
+ */
+ static uint16_t TimestampToU16 (Time x);
+ static uint16_t BeaconIntervalToU16 (Time x);
+ static uint8_t AidToU8 (uint16_t x);
+
+ NeighboursTimingUnitsList m_neighbours;
+ /**
+ * Timing element parameters:
+ */
+ uint16_t m_numOfUnits;
+ friend bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+};
+bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "ie-dot11s-configuration.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+
+dot11sMeshCapability::dot11sMeshCapability ():
+ acceptPeerLinks (true),
+ MCCASupported (false),
+ MCCAEnabled (false),
+ forwarding (true),
+ beaconTimingReport (true),
+ TBTTAdjustment (true),
+ powerSaveLevel (false)
+{}
+
+uint8_t dot11sMeshCapability::GetSerializedSize () const
+{
+ return 2;
+}
+
+Buffer::Iterator dot11sMeshCapability::Serialize (Buffer::Iterator i) const
+{
+ uint16_t result = 0;
+ if (acceptPeerLinks)
+ result |= 1 << 0;
+ if (MCCASupported)
+ result |= 1 << 1;
+ if (MCCAEnabled)
+ result |= 1 << 2;
+ if (forwarding)
+ result |= 1 << 3;
+ if (beaconTimingReport)
+ result |= 1 << 4;
+ if (TBTTAdjustment)
+ result |= 1 << 5;
+ if (powerSaveLevel)
+ result |= 1 << 6;
+ i.WriteHtolsbU16 (result);
+ return i;
+}
+
+Buffer::Iterator dot11sMeshCapability::Deserialize (Buffer::Iterator i)
+{
+ uint16_t cap = i.ReadLsbtohU16 ();
+ acceptPeerLinks = Is (cap, 0);
+ MCCASupported = Is (cap, 1);
+ MCCAEnabled = Is (cap, 2);
+ forwarding = Is (cap, 3);
+ beaconTimingReport = Is (cap, 4);
+ TBTTAdjustment = Is (cap, 5);
+ powerSaveLevel = Is (cap, 6);
+ return i;
+}
+
+bool dot11sMeshCapability::Is (uint16_t cap, uint8_t n) const
+{
+ uint16_t mask = 1<<n;
+ return (cap & mask) == mask;
+}
+
+IeConfiguration::IeConfiguration ():
+ m_APSId (PROTOCOL_HWMP),
+ m_APSMId (METRIC_AIRTIME),
+ m_CCMId (CONGESTION_NULL),
+ m_SPId (SYNC_NEIGHBOUR_OFFSET),
+ m_APId (AUTH_NULL),
+ m_neighbors (0)
+{}
+
+TypeId
+IeConfiguration::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IeConfiguration")
+ .SetParent<WifiInformationElement> ();
+ return tid;
+}
+
+TypeId
+IeConfiguration::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint8_t
+IeConfiguration::GetInformationSize () const
+{
+ return 1 // Version
+ + 4 // APSPId
+ + 4 // APSMId
+ + 4 // CCMId
+ + 4 // SPId
+ + 4 // APId
+ + 1 // Mesh formation info (see 7.3.2.86.6 of 802.11s draft 3.0)
+ + m_meshCap.GetSerializedSize ();
+}
+
+void
+IeConfiguration::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (1); //Version
+ // Active Path Selection Protocol ID:
+ i.WriteHtolsbU32 (m_APSId);
+ // Active Path Metric ID:
+ i.WriteHtolsbU32 (m_APSMId);
+ // Congestion Control Mode ID:
+ i.WriteHtolsbU32 (m_CCMId);
+ // Sync:
+ i.WriteHtolsbU32 (m_SPId);
+ // Auth:
+ i.WriteHtolsbU32 (m_APId);
+ i.WriteU8 (m_neighbors << 1);
+ m_meshCap.Serialize (i);
+}
+
+uint8_t
+IeConfiguration::DeserializeInformation (Buffer::Iterator i, uint8_t length)
+{
+ Buffer::Iterator start = i;
+ uint8_t version;
+ version = i.ReadU8 ();
+ // Active Path Selection Protocol ID:
+ m_APSId = (dot11sPathSelectionProtocol)i.ReadLsbtohU32 ();
+ // Active Path Metric ID:
+ m_APSMId = (dot11sPathSelectionMetric)i.ReadLsbtohU32 ();
+ // Congestion Control Mode ID:
+ m_CCMId = (dot11sCongestionControlMode)i.ReadLsbtohU32 ();
+ m_SPId = (dot11sSynchronizationProtocolIdentifier)i.ReadLsbtohU32 ();
+ m_APId = (dot11sAuthenticationProtocol)i.ReadLsbtohU32 ();
+ m_neighbors = i.ReadU8 () / 2;
+ i = m_meshCap.Deserialize (i);
+ return i.GetDistanceFrom (start);
+}
+void
+IeConfiguration::PrintInformation (std::ostream& os) const
+{
+ //TODO: print
+}
+void
+IeConfiguration::SetRouting (dot11sPathSelectionProtocol routingId)
+{
+ m_APSId = routingId;
+}
+
+void
+IeConfiguration::SetMetric (dot11sPathSelectionMetric metricId)
+{
+ m_APSMId = metricId;
+}
+
+bool
+IeConfiguration::IsHWMP ()
+{
+ return (m_APSId == PROTOCOL_HWMP);
+}
+
+bool
+IeConfiguration::IsAirtime ()
+{
+ return (m_APSMId == METRIC_AIRTIME);
+}
+void
+IeConfiguration::SetNeighborCount (uint8_t neighbors)
+{
+ m_neighbors = (neighbors > 31) ? 31 : neighbors;
+}
+uint8_t
+IeConfiguration::GetNeighborCount ()
+{
+ return m_neighbors;
+}
+dot11sMeshCapability const& IeConfiguration::MeshCapability ()
+{
+ return m_meshCap;
+}
+bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b)
+{
+ return (
+ (a.acceptPeerLinks == b.acceptPeerLinks) &&
+ (a.MCCASupported == b.MCCASupported) &&
+ (a.MCCAEnabled == b.MCCAEnabled) &&
+ (a.forwarding == b.forwarding) &&
+ (a.beaconTimingReport == b.beaconTimingReport) &&
+ (a.TBTTAdjustment == b.TBTTAdjustment) &&
+ (a.powerSaveLevel == b.powerSaveLevel)
+ );
+}
+bool operator== (const IeConfiguration & a, const IeConfiguration & b)
+{
+ return (
+ (a.m_APSId == b.m_APSId) &&
+ (a.m_APSMId == b.m_APSMId) &&
+ (a.m_CCMId == b.m_CCMId) &&
+ (a.m_SPId == b.m_SPId) &&
+ (a.m_APId == b.m_APId) &&
+ (a.m_neighbors == b.m_neighbors) &&
+ (a.m_meshCap == b.m_meshCap)
+ );
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IeConfigurationBist : public IeTest
+{
+ IeConfigurationBist () : IeTest ("Mesh/802.11s/IE/Configuration") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeConfigurationBist g_IeConfigurationBist;
+
+bool IeConfigurationBist::RunTests ()
+{
+ bool result(true);
+ IeConfiguration a;
+
+ result = TestRoundtripSerialization (a);
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_CONFIGURATION_H
+#define MESH_CONFIGURATION_H
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.1 in 802.11s draft 3.0
+ */
+enum dot11sPathSelectionProtocol
+{
+ PROTOCOL_HWMP = 0x000fac00,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.2 in 802.11s draft 3.0
+ */
+enum dot11sPathSelectionMetric
+{
+ METRIC_AIRTIME = 0x000fac00,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.3 in 802.11s draft 3.0
+ */
+enum dot11sCongestionControlMode
+{
+ CONGESTION_SIGNALING = 0x000fac00,
+ CONGESTION_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.4 in 802.11s draft 3.0
+ */
+enum dot11sSynchronizationProtocolIdentifier
+{
+ SYNC_NEIGHBOUR_OFFSET = 0x000fac00,
+ SYNC_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.5 in 802.11s draft 3.0
+ */
+enum dot11sAuthenticationProtocol
+{
+ AUTH_NULL = 0x000fac00,
+ AUTH_SAE = 0x000fac01,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.7 in 802.11s draft 3.0
+ */
+class dot11sMeshCapability
+{
+public:
+ dot11sMeshCapability ();
+ uint8_t GetSerializedSize () const;
+ Buffer::Iterator Serialize (Buffer::Iterator i) const;
+ Buffer::Iterator Deserialize (Buffer::Iterator i);
+ bool acceptPeerLinks;
+ bool MCCASupported;
+ bool MCCAEnabled;
+ bool forwarding;
+ bool beaconTimingReport;
+ bool TBTTAdjustment;
+ bool powerSaveLevel;
+ bool Is (uint16_t cap,uint8_t n) const;
+ friend bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief Describes Mesh Configuration Element
+ * see 7.3.2.86 of 802.11s draft 3.0
+ */
+class IeConfiguration : public WifiInformationElement
+{
+public:
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+
+ IeConfiguration ();
+ void SetRouting (dot11sPathSelectionProtocol routingId);
+ void SetMetric (dot11sPathSelectionMetric metricId);
+ bool IsHWMP ();
+ bool IsAirtime ();
+ void SetNeighborCount (uint8_t neighbors);
+ uint8_t GetNeighborCount ();
+
+ dot11sMeshCapability const& MeshCapability ();
+private:
+ WifiElementId ElementId () const
+ {
+ return IE11S_MESH_CONFIGURATION;
+ }
+ uint8_t GetInformationSize () const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+private:
+ /** Active Path Selection Protocol ID */
+ dot11sPathSelectionProtocol m_APSId;
+ /** Active Path Metric ID */
+ dot11sPathSelectionMetric m_APSMId;
+ /** Congestion Control Mode ID */
+ dot11sCongestionControlMode m_CCMId;
+ /** Sync protocol ID */
+ dot11sSynchronizationProtocolIdentifier m_SPId;
+ /** Auth protocol ID */
+ dot11sAuthenticationProtocol m_APId;
+ dot11sMeshCapability m_meshCap;
+ uint8_t m_neighbors;
+ friend bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+};
+bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-id.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-id.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+namespace dot11s {
+IeMeshId::IeMeshId ()
+{
+ for (uint8_t i = 0; i < 32; i++)
+ {
+ m_meshId[i] = 0;
+ }
+}
+IeMeshId::IeMeshId (char const meshId[32], uint8_t length)
+{
+ NS_ASSERT (length <= 32);
+ uint8_t len = 0;
+ while (len < length)
+ {
+ m_meshId[len] = meshId[len];
+ len++;
+ }
+ while (len < 32)
+ {
+ m_meshId[len] = 0;
+ len++;
+ }
+}
+bool
+IeMeshId::IsEqual (IeMeshId const &o) const
+{
+ uint8_t i = 0;
+ while (i < 32 &&
+ m_meshId[i] == o.m_meshId[i] &&
+ m_meshId[i] != 0)
+ {
+ i++;
+ }
+ if (m_meshId[i] != o.m_meshId[i])
+ {
+ return false;
+ }
+ return true;
+}
+bool
+IeMeshId::IsBroadcast (void) const
+{
+ if (m_meshId[0] == 0)
+ {
+ return true;
+ }
+ return false;
+}
+char *
+IeMeshId::PeekString (void) const
+{
+ return (char *)m_meshId;
+}
+uint8_t
+IeMeshId::GetInformationSize (void) const
+{
+ uint8_t size = 0;
+ while (m_meshId[size] != 0 && size < 32)
+ {
+ size++;
+ }
+ NS_ASSERT (size <= 32);
+ return size;
+}
+void
+IeMeshId::SerializeInformation (Buffer::Iterator i) const
+{
+ uint8_t size = 0;
+ while (m_meshId[size] != 0 && size < 32)
+ {
+ i.WriteU8 (m_meshId [size]);
+ size ++;
+ }
+}
+uint8_t
+IeMeshId::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT (length <= 32);
+ i.Read (m_meshId, length);
+ m_meshId[length] = 0;
+ return i.GetDistanceFrom(start);
+}
+void
+IeMeshId::PrintInformation (std::ostream& os) const
+{
+ //TODO
+}
+bool operator== (const IeMeshId & a, const IeMeshId & b)
+{
+ bool result (true);
+ uint8_t size = 0;
+
+ while(size < 32)
+ {
+ result = result && (a.m_meshId[size] == b.m_meshId[size]);
+ if(a.m_meshId[size] == 0)
+ return result;
+ size ++;
+ }
+ return result;
+};
+
+std::ostream &
+operator << (std::ostream &os, const IeMeshId &meshId)
+{
+ os << meshId.PeekString ();
+ return os;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IeMeshId
+struct IeMeshIdBist : public IeTest
+{
+ IeMeshIdBist () : IeTest ("Mesh/802.11s/IE/MESH_ID") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeMeshIdBist g_IeMeshIdBist;
+
+bool IeMeshIdBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IeMeshId a("qwerty",6);
+ result = result && TestRoundtripSerialization (a);
+ return result;
+}
+#endif // RUN_SELF_TESTS
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-id.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef MESH_ID_H
+#define MESH_ID_H
+
+#include <stdint.h>
+#include "ns3/buffer.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \brief a IEEE 802.11s Mesh ID 7.3.287 of 802.11s draft 3.0
+ *
+ */
+class IeMeshId : public WifiInformationElement
+{
+public:
+ // broadcast meshId
+ IeMeshId ();
+ //IeMeshId (char const meshId[32]);
+ IeMeshId (char const meshId[32], uint8_t length);
+
+ bool IsEqual (IeMeshId const &o) const;
+ bool IsBroadcast (void) const;
+
+ uint32_t GetLength (void) const;
+ char *PeekString (void) const;
+private:
+ WifiElementId ElementId () const{
+ return IE11S_MESH_ID;
+ };
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+ uint8_t GetInformationSize () const;
+private:
+ uint8_t m_meshId[33];
+ friend bool operator== (const IeMeshId & a, const IeMeshId & b);
+};
+
+std::ostream &operator << (std::ostream &os, const IeMeshId &meshId);
+
+/**
+ * \class ns3::IeMeshIdValue
+ * \brief hold objects of type ns3::IeMeshId
+ */
+
+ATTRIBUTE_HELPER_HEADER (IeMeshId);
+} //namespace dot11s
+} // namespace ns3
+#endif /* MESH_ID_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "ie-dot11s-peer-management.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IePeerManagement::IePeerManagement ():
+ m_length (0),
+ m_subtype (PEER_OPEN),
+ m_localLinkId (0),
+ m_peerLinkId (0),
+ m_reasonCode (REASON11S_RESERVED)
+{}
+
+
+void
+IePeerManagement::SetPeerOpen (uint16_t localLinkId)
+{
+ m_length = 3;
+ m_subtype = PEER_OPEN;
+ m_localLinkId = localLinkId;
+}
+void
+IePeerManagement::SetPeerClose (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reasonCode)
+{
+ m_length = 7;
+ m_subtype = PEER_CLOSE;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+ m_reasonCode = reasonCode;
+}
+
+void
+IePeerManagement::SetPeerConfirm (uint16_t localLinkId, uint16_t peerLinkId)
+{
+ m_length = 5;
+ m_subtype = PEER_CONFIRM;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+}
+
+PmpReasonCode
+IePeerManagement::GetReasonCode () const
+{
+ return m_reasonCode;
+}
+
+uint16_t
+IePeerManagement::GetLocalLinkId () const
+{
+ return m_localLinkId;
+}
+
+uint16_t
+IePeerManagement::GetPeerLinkId () const
+{
+ return m_peerLinkId;
+}
+
+uint8_t
+IePeerManagement::GetInformationSize (void) const
+{
+ return m_length;
+}
+
+bool
+IePeerManagement::SubtypeIsOpen () const
+{
+ return (m_subtype == PEER_OPEN);
+}
+bool
+IePeerManagement::SubtypeIsClose () const
+{
+ return (m_subtype == PEER_CLOSE);
+}
+bool
+IePeerManagement::SubtypeIsConfirm () const
+{
+ return (m_subtype == PEER_CONFIRM);
+}
+
+void
+IePeerManagement::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_subtype);
+ i.WriteHtolsbU16 (m_localLinkId);
+ if (m_length > 3)
+ i.WriteHtolsbU16 (m_peerLinkId);
+ if (m_length > 5)
+ i.WriteHtolsbU16 (m_reasonCode);
+}
+uint8_t
+IePeerManagement::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_subtype = i.ReadU8 ();
+ m_length = length;
+ if (m_subtype == PEER_OPEN)
+ {
+ NS_ASSERT (length == 3);
+ }
+ if (m_subtype == PEER_CONFIRM)
+ {
+ NS_ASSERT (length == 5);
+ }
+ if (m_subtype == PEER_CLOSE)
+ {
+ NS_ASSERT (length == 7);
+ }
+ m_localLinkId = i.ReadLsbtohU16 ();
+ if (m_length > 3)
+ m_peerLinkId = i.ReadLsbtohU16 ();
+ if (m_length > 5)
+ m_reasonCode = (PmpReasonCode)i.ReadLsbtohU16 ();
+ return i.GetDistanceFrom (start);
+}
+void
+IePeerManagement::PrintInformation (std::ostream& os) const
+{
+
+ os << " Subtype: = " << (uint16_t)m_subtype << "\n";
+ os << " Length: = " << (uint16_t)m_length << "\n";
+ os << " LocalLinkId: = " << m_localLinkId << "\n";
+ os << " PeerLinkId: = " << m_peerLinkId << "\n";
+ os << " ReasonCode: = " << m_reasonCode << "\n";
+}
+bool operator== (const IePeerManagement & a, const IePeerManagement & b)
+{
+ return (
+ (a.m_length == b.m_length) &&
+ (a.m_subtype == b.m_subtype) &&
+ (a.m_localLinkId == b.m_localLinkId) &&
+ (a.m_peerLinkId == b.m_peerLinkId) &&
+ (a.m_reasonCode == b.m_reasonCode)
+ );
+}
+#ifdef RUN_SELF_TESTS
+struct IePeerManagementBist : public IeTest
+{
+ IePeerManagementBist () : IeTest ("Mesh/802.11s/IE/PeerManagement") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePeerManagementBist g_IePerrBist;
+
+bool IePeerManagementBist::RunTests ()
+{
+ bool result(true);
+ {
+ IePeerManagement a;
+ a.SetPeerOpen (1);
+ result = result && TestRoundtripSerialization (a);
+ }
+ {
+ IePeerManagement a;
+ a.SetPeerConfirm (1,2);
+ result = result && TestRoundtripSerialization (a);
+ }
+ {
+ IePeerManagement a;
+ a.SetPeerClose (1, 2, REASON11S_MESH_CAPABILITY_POLICY_VIOLATION);
+ result = result && TestRoundtripSerialization (a);
+ }
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_PEER_MAN_ELEMENT
+#define MESH_PEER_MAN_ELEMENT
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+
+/**
+ * \ingroup dot11s
+ * \brief Codes used by 802.11s Peer Management Protocol
+ */
+enum PmpReasonCode {
+ REASON11S_PEERING_CANCELLED = 2, // according to open80211s
+ REASON11S_MESH_MAX_PEERS,
+ REASON11S_MESH_CAPABILITY_POLICY_VIOLATION,
+ REASON11S_MESH_CLOSE_RCVD,
+ REASON11S_MESH_MAX_RETRIES,
+ REASON11S_MESH_CONFIRM_TIMEOUT,
+ REASON11S_MESH_INVALID_GTK,
+ REASON11S_MESH_INCONSISTENT_PARAMETERS,
+ REASON11S_MESH_INVALID_SECURITY_CAPABILITY,
+ REASON11S_RESERVED,
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.85 of draft 2.07
+ */
+class IePeerManagement : public WifiInformationElement
+{
+public:
+ IePeerManagement ();
+ enum Subtype {
+ PEER_OPEN = 0,
+ PEER_CONFIRM,
+ PEER_CLOSE,
+ };
+ void SetPeerOpen (uint16_t localLinkId);
+ void SetPeerClose (uint16_t localLinkID, uint16_t peerLinkId, PmpReasonCode reasonCode);
+ void SetPeerConfirm (uint16_t localLinkID, uint16_t peerLinkId);
+
+ PmpReasonCode GetReasonCode () const;
+ uint16_t GetLocalLinkId () const;
+ uint16_t GetPeerLinkId () const;
+ bool SubtypeIsOpen () const;
+ bool SubtypeIsClose () const;
+ bool SubtypeIsConfirm () const ;
+ uint8_t GetSubtype() const { return m_subtype;};
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PEERING_MANAGEMENT;
+ }
+ uint8_t GetInformationSize (void) const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+private:
+ uint8_t m_length;
+ uint8_t m_subtype;
+ uint16_t m_localLinkId;
+ /**
+ * Present within confirm and may be present in close
+ */
+ uint16_t m_peerLinkId;
+ /**
+ * Present only within close frame
+ */
+ PmpReasonCode m_reasonCode;
+ friend bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+};
+bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peering-protocol.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-peering-protocol.h"
+namespace ns3 {
+namespace dot11s {
+TypeId
+IePeeringProtocol::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePeeringProtocol")
+ .SetParent<WifiInformationElement> ();
+ return tid;
+}
+
+TypeId
+IePeeringProtocol::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint8_t
+IePeeringProtocol::GetInformationSize () const
+{
+ return 1;
+}
+IePeeringProtocol::IePeeringProtocol ():
+ m_protocol(0)
+{
+}
+void
+IePeeringProtocol::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_protocol);
+}
+
+uint8_t
+IePeeringProtocol::DeserializeInformation (Buffer::Iterator i, uint8_t length)
+{
+ Buffer::Iterator start = i;
+ m_protocol = i.ReadU8 ();
+ return i.GetDistanceFrom (start);
+}
+void
+IePeeringProtocol::PrintInformation (std::ostream& os) const
+{
+ //TODO: print
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peering-protocol.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef MESH_PERING_PROTOCOL_H
+#define MESH_PEERING_PROTOCOL_H
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+class IePeeringProtocol : public WifiInformationElement
+{
+public:
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+
+ IePeeringProtocol ();
+private:
+ WifiElementId ElementId () const
+ {
+ return IE11S_MESH_PEERING_PROTOCOL_VERSION;
+ }
+ uint8_t GetInformationSize () const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+private:
+ uint8_t m_protocol;
+};
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-perr.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+namespace ns3 {
+namespace dot11s {
+IePerr::~IePerr ()
+{
+}
+
+TypeId
+IePerr::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePerr")
+ .SetParent<Object> ();
+ return tid;
+}
+void
+IePerr::PrintInformation (std::ostream &os) const
+{
+ // FILL
+}
+TypeId
+IePerr::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IePerr::IePerr ():
+ m_numOfDest (0)
+{
+}
+uint8_t
+IePerr::GetNumOfDest ()
+{
+ return m_numOfDest;
+}
+void
+IePerr::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (0);
+ i.WriteU8 (m_numOfDest);
+ NS_ASSERT (m_numOfDest == m_addressUnits.size ());
+ for (unsigned int j = 0; j < m_numOfDest; j++)
+ {
+ WriteTo (i, m_addressUnits[j].destination);
+ i.WriteHtolsbU32 (m_addressUnits[j].seqnum);
+ }
+}
+uint8_t
+IePerr::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ i.Next (1); //Mode flags is not used now
+ m_numOfDest = i.ReadU8 ();
+ NS_ASSERT ((2+10*m_numOfDest) == length);
+ length = 0; //to avoid compiler warning in optimized builds
+ for (unsigned int j = 0; j < m_numOfDest; j++)
+ {
+ FailedDestination unit;
+ ReadFrom (i,unit.destination);
+ unit.seqnum = i.ReadLsbtohU32 ();
+ m_addressUnits.push_back (unit);
+ }
+ return i.GetDistanceFrom (start);
+}
+
+uint8_t
+IePerr::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //ModeFlags
+ +1 //NumOfDests
+ +6*m_numOfDest
+ +4*m_numOfDest;
+ return retval;
+}
+
+void
+IePerr::AddAddressUnit (FailedDestination unit)
+{
+ for (unsigned int i = 0; i < m_addressUnits.size (); i ++)
+ if (m_addressUnits[i].destination == unit.destination)
+ return;
+ m_addressUnits.push_back (unit);
+ m_numOfDest++;
+}
+
+std::vector<IePerr::FailedDestination>
+IePerr::GetAddressUnitVector () const
+{
+ return m_addressUnits;
+}
+void
+IePerr::DeleteAddressUnit (Mac48Address address)
+{
+ for (std::vector<FailedDestination>::iterator i = m_addressUnits.begin (); i != m_addressUnits.end(); i ++)
+ if (i->destination == address)
+ {
+ m_numOfDest --;
+ m_addressUnits.erase (i);
+ break;
+ }
+}
+void
+IePerr::Merge(const IePerr perr)
+{
+ std::vector<FailedDestination> to_merge = perr.GetAddressUnitVector ();
+ for (std::vector<FailedDestination>::iterator i = to_merge.begin (); i != to_merge.end(); i ++)
+ {
+ bool should_add = true;
+ for (std::vector<FailedDestination>::iterator j = m_addressUnits.begin (); j != m_addressUnits.end(); j ++)
+ if ((i->destination == j->destination) && (i->seqnum <= j->seqnum))
+ should_add = false;
+ if(should_add)
+ AddAddressUnit (*i);
+ }
+}
+void
+IePerr::ResetPerr ()
+{
+ m_numOfDest = 0;
+ m_addressUnits.clear ();
+}
+bool operator== (const IePerr & a, const IePerr & b)
+{
+ if(a.m_numOfDest != b.m_numOfDest)
+ return false;
+ for(unsigned int i = 0; i < a.m_addressUnits.size(); i ++)
+ {
+ if(a.m_addressUnits[i].destination != b.m_addressUnits[i].destination)
+ return false;
+ if(a.m_addressUnits[i].seqnum != b.m_addressUnits[i].seqnum)
+ return false;
+ }
+ return true;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IePerrBist : public IeTest
+{
+ IePerrBist () : IeTest ("Mesh/802.11s/IE/PERR") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePerrBist g_IePerrBist;
+
+bool IePerrBist::RunTests ()
+{
+ bool result(true);
+ // create test information element
+ IePerr a;
+ IePerr::FailedDestination dest;
+ dest.destination = Mac48Address("11:22:33:44:55:66");
+ dest.seqnum = 1;
+ a.AddAddressUnit(dest);
+ dest.destination = Mac48Address("10:20:30:40:50:60");
+ dest.seqnum = 2;
+ a.AddAddressUnit(dest);
+ dest.destination = Mac48Address("01:02:03:04:05:06");
+ dest.seqnum = 3;
+ a.AddAddressUnit(dest);
+
+ IePerr b = a;
+ b.Merge(a);
+ NS_TEST_ASSERT_EQUAL (a, b);
+
+ result = result && TestRoundtripSerialization (a);
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef PERR_INFORMATION_ELEMENT_H
+#define PERR_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.98 of 802.11s draft 2.07
+ */
+class IePerr : public WifiInformationElement
+{
+public:
+ IePerr ();
+ ~IePerr ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ struct FailedDestination
+ {
+ Mac48Address destination;
+ uint32_t seqnum;
+ };
+ uint8_t GetNumOfDest ();
+
+ void AddAddressUnit (struct FailedDestination unit);
+ std::vector<FailedDestination> GetAddressUnitVector () const;
+ void DeleteAddressUnit (Mac48Address address);
+ void Merge(const IePerr perr);
+ void ResetPerr ();
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PERR;
+ };
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+ uint8_t GetInformationSize () const;
+private:
+ uint8_t m_numOfDest;
+ std::vector<FailedDestination> m_addressUnits;
+ friend bool operator== (const IePerr & a, const IePerr & b);
+};
+ bool operator== (const IePerr & a, const IePerr & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-prep.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/********************************
+ * IePrep
+ *******************************/
+IePrep::~IePrep ()
+{
+}
+
+TypeId
+IePrep::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePrep")
+ .SetParent<Object> ();
+ return tid;
+}
+TypeId
+IePrep::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IePrep::IePrep ():
+ m_flags (0),
+ m_hopcount (0),
+ m_ttl (0),
+ m_destinationAddress (Mac48Address::GetBroadcast()),
+ m_destSeqNumber (0),
+ m_lifetime (0),
+ m_metric (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_originatorSeqNumber (0)
+{
+}
+void
+IePrep::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IePrep::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IePrep::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePrep::SetDestinationSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IePrep::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+void
+IePrep::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePrep::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePrep::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePrep::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+uint8_t
+IePrep::GetFlags () const
+{
+ return m_flags;
+}
+uint8_t
+IePrep::GetHopcount () const
+{
+ return m_hopcount;
+}
+uint32_t
+IePrep::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePrep::GetDestinationSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+IePrep::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+uint32_t
+IePrep::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePrep::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePrep::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePrep::GetLifetime () const
+{
+ return m_lifetime;
+}
+void
+IePrep::DecrementTtl ()
+{
+ m_ttl --;
+}
+
+void
+IePrep::IncrementMetric (uint32_t metric)
+{
+ m_metric +=metric;
+}
+
+
+void
+IePrep::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_destinationAddress);
+ i.WriteHtolsbU32 (m_destSeqNumber);
+ i.WriteHtolsbU32 (m_lifetime);
+ i.WriteHtolsbU32 (m_metric);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_originatorSeqNumber);
+}
+uint8_t
+IePrep::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_destinationAddress);
+ m_destSeqNumber = i.ReadLsbtohU32 ();
+ m_lifetime = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadLsbtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePrep::GetInformationSize () const
+{
+ uint32_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //Ttl
+ +6 //Dest address
+ +4 //Dest seqno
+ +4 //Lifetime
+ +4 //metric
+ +6 //Originator address
+ +4 //Originator seqno
+ +1; //destination count
+ return retval;
+};
+void
+IePrep::PrintInformation (std::ostream& os) const
+{
+ //TODO
+}
+bool operator== (const IePrep & a, const IePrep & b)
+{
+ return (
+ (a.m_flags == b.m_flags) &&
+ (a.m_hopcount == b.m_hopcount) &&
+ (a.m_ttl == b.m_ttl) &&
+ (a.m_destinationAddress == b.m_destinationAddress) &&
+ (a.m_destSeqNumber == b.m_destSeqNumber) &&
+ (a.m_lifetime == b.m_lifetime) &&
+ (a.m_metric == b.m_metric) &&
+ (a.m_originatorAddress == b.m_originatorAddress) &&
+ (a.m_originatorSeqNumber == b.m_originatorSeqNumber)
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePrep
+struct IePrepBist : public IeTest
+{
+ IePrepBist () : IeTest ("Mesh/802.11s/IE/PREP") {};
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePrepBist g_IePrepBist;
+
+bool IePrepBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IePrep a;
+ a.SetFlags (12);
+ a.SetHopcount (11);
+ a.SetTtl (10);
+ a.SetDestinationAddress (Mac48Address("11:22:33:44:55:66"));
+ a.SetDestinationSeqNumber (123);
+ a.SetLifetime (5000);
+ a.SetMetric (4321);
+ a.SetOriginatorAddress (Mac48Address("33:00:22:00:11:00"));
+ a.SetOriginatorSeqNumber (666);
+
+ result = result && TestRoundtripSerialization (a);
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREP_INFORMATION_ELEMENT_H
+#define WIFI_PREP_INFORMATION_ELEMENT_H
+
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.97 of 802.11s draft 2.07
+ */
+class IePrep : public WifiInformationElement
+{
+public:
+ IePrep ();
+ ~IePrep ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTtl (uint8_t ttl);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestinationSeqNumber (uint32_t dest_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+
+ uint8_t GetFlags () const;
+ uint8_t GetHopcount () const;
+ uint32_t GetTtl () const;
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestinationSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber ()const ;
+
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PREP;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream& os) const;
+private:
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ friend bool operator== (const IePrep & a, const IePrep & b);
+};
+bool operator== (const IePrep & a, const IePrep & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-preq.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+/*************************
+ * DestinationAddressUnit
+ ************************/
+DestinationAddressUnit::DestinationAddressUnit ():
+ m_do (false),
+ m_rf (false),
+ m_usn (false),
+ m_destinationAddress (Mac48Address ()),
+ m_destSeqNumber (0)
+{
+}
+void
+DestinationAddressUnit::SetFlags (bool doFlag, bool rfFlag, bool usnFlag)
+{
+ m_do = doFlag;
+ m_rf = rfFlag;
+ m_usn = usnFlag;
+}
+
+void
+DestinationAddressUnit::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+ if(m_destSeqNumber != 0)
+ m_usn = true;
+}
+void
+DestinationAddressUnit::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+bool
+DestinationAddressUnit::IsDo ()
+{
+ return m_do;
+}
+
+bool
+DestinationAddressUnit::IsRf ()
+{
+ return m_rf;
+}
+bool
+DestinationAddressUnit::IsUsn ()
+{
+ return m_usn;
+}
+uint32_t
+DestinationAddressUnit::GetDestSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+DestinationAddressUnit::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+/********************************
+ * IePreq
+ *******************************/
+IePreq::~IePreq ()
+{
+}
+
+TypeId
+IePreq::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePreq")
+ .SetParent<Object> ();
+ return tid;
+}
+TypeId
+IePreq::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+IePreq::IePreq ():
+ m_maxSize (32),
+ m_flags (0),
+ m_hopCount (0),
+ m_ttl (0),
+ m_preqId (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_originatorSeqNumber (0),
+ m_lifetime (0),
+ m_metric (0),
+ m_destCount (0)
+{
+}
+void
+IePreq::SetUnicastPreq ()
+{
+ m_flags |= 1<<1;
+}
+
+void
+IePreq::SetNeedNotPrep ()
+{
+ m_flags |= 1<<2;
+}
+//void
+//IePreq::SetFlags (uint8_t flags)
+//{
+// m_flags = flags;
+//}
+void
+IePreq::SetHopcount (uint8_t hopcount)
+{
+ m_hopCount = hopcount;
+}
+void
+IePreq::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePreq::SetPreqID (uint32_t preq_id)
+{
+ m_preqId = preq_id;
+}
+void
+IePreq::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePreq::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePreq::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePreq::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+void
+IePreq::SetDestCount (uint8_t dest_count)
+{
+ m_destCount = dest_count;
+}
+bool
+IePreq::IsUnicastPreq () const
+{
+ return (m_flags & (1<<1));
+}
+bool
+IePreq::IsNeedNotPrep () const
+{
+ return (m_flags & (1<<2));
+}
+uint8_t
+IePreq::GetHopCount () const
+{
+ return m_hopCount;
+}
+uint8_t
+IePreq::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePreq::GetPreqID () const
+{
+ return m_preqId;
+}
+uint32_t
+IePreq::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePreq::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePreq::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePreq::GetLifetime () const
+{
+ return m_lifetime;
+}
+
+uint8_t
+IePreq::GetDestCount () const
+{
+ return m_destCount;
+}
+void
+IePreq::DecrementTtl ()
+{
+ m_ttl --;
+ m_hopCount ++;
+}
+void
+IePreq::IncrementMetric (uint32_t metric)
+{
+ m_metric +=metric;
+}
+void
+IePreq::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopCount);
+ i.WriteU8 (m_ttl);
+ i.WriteHtolsbU32 (m_preqId);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_originatorSeqNumber);
+ i.WriteHtolsbU32 (m_lifetime);
+ i.WriteHtolsbU32 (m_metric);
+ i.WriteU8 (m_destCount);
+ int written = 0;
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator j = m_destinations.begin (); j != m_destinations.end(); j++)
+ {
+ uint8_t flags = 0;
+ if ((*j)->IsDo ())
+ flags += 128;
+ if ((*j)->IsRf ())
+ flags += 64;
+ if((*j)->IsUsn ())
+ flags += 32;
+ i.WriteU8 (flags);
+ WriteTo (i, (*j)->GetDestinationAddress());
+ i.WriteHtolsbU32 ((*j)->GetDestSeqNumber ());
+ written++;
+ if (written > m_maxSize)
+ break;
+ }
+}
+uint8_t
+IePreq::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopCount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ m_preqId = i.ReadLsbtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadLsbtohU32 ();
+ m_lifetime = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ m_destCount = i.ReadU8 ();
+ for (int j = 0; j < m_destCount; j++ )
+ {
+ Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
+ bool doFlag = false;
+ bool rfFlag = false;
+ bool usnFlag = false;
+ uint8_t flags = i.ReadU8 ();
+ if (flags >= 128)
+ {
+ doFlag = true;
+ flags -=128;
+ }
+ if (flags >=64)
+ {
+ rfFlag = true;
+ flags -= 64;
+ }
+ if (flags >= 32)
+ usnFlag = true;
+ new_element->SetFlags (doFlag, rfFlag, usnFlag);
+ Mac48Address addr;
+ ReadFrom (i,addr);
+ new_element->SetDestinationAddress (addr);
+ new_element->SetDestSeqNumber (i.ReadLsbtohU32());
+ m_destinations.push_back (new_element);
+ NS_ASSERT (28+j*11 < length);
+ }
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePreq::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //TTL
+ +4 //PREQ ID
+ +6 //Source address (originator)
+ +4 //Originator seqno
+ +4 //Lifetime
+ +4 //metric
+ +1; //destination count
+ if (m_destCount > m_maxSize)
+ retval += (m_maxSize*11);
+ else
+ retval += (m_destCount*11);
+ return retval;
+}
+void
+IePreq::PrintInformation (std::ostream &os) const
+{
+ os << " originator address = " << m_originatorAddress << "\n";
+ os << " TTL = " << (uint16_t)m_ttl << "\n";
+ os << " hop count = " << (uint16_t)m_hopCount << "\n";
+ os << " metric = " << m_metric << "\n";
+ os << " seqno = " << m_originatorSeqNumber << "\n";
+ os << " lifetime = " << m_lifetime << "\n";
+ os << " preq ID = " <<m_preqId << "\n";
+ os << " Destinations are:\n";
+ for (int j = 0; j < m_destCount; j++ )
+ os << " " << m_destinations[j]->GetDestinationAddress () << "\n";
+}
+std::vector<Ptr<DestinationAddressUnit> >
+IePreq::GetDestinationList ()
+{
+ return m_destinations;
+}
+void
+IePreq::AddDestinationAddressElement (
+ bool doFlag, bool rfFlag,
+ Mac48Address dest_address,
+ uint32_t dest_seq_number
+)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = m_destinations.begin (); i != m_destinations.end(); i++ )
+ if ((*i)->GetDestinationAddress () == dest_address)
+ return;
+ Ptr<DestinationAddressUnit>new_element = Create<DestinationAddressUnit> ();
+ new_element->SetFlags (doFlag, rfFlag, false);
+ new_element->SetDestinationAddress (dest_address);
+ new_element->SetDestSeqNumber (dest_seq_number);
+ m_destinations.push_back (new_element);
+ m_destCount++;
+}
+void
+IePreq::DelDestinationAddressElement (Mac48Address dest_address)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator i = m_destinations.begin (); i != m_destinations.end(); i++)
+ if ((*i)->GetDestinationAddress () == dest_address)
+ {
+ m_destinations.erase (i);
+ m_destCount--;
+ break;
+ }
+}
+void
+IePreq::ClearDestinationAddressElement ()
+{
+ int i;
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator j = m_destinations.begin (); j != m_destinations.end(); j++)
+ (*j) = 0;
+ for (i = 0; i < m_destCount; i ++)
+ m_destinations.pop_back ();
+ m_destinations.clear ();
+}
+bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b)
+{
+ return (a.m_do == b.m_do
+ && a.m_rf == b.m_rf
+ && a.m_usn == b.m_usn
+ && a.m_destinationAddress == b.m_destinationAddress
+ && a.m_destSeqNumber == b.m_destSeqNumber
+ );
+}
+bool operator== (const IePreq & a, const IePreq & b)
+{
+ bool ok = ( a.m_flags == b.m_flags
+ && a.m_hopCount == b.m_hopCount
+ && a.m_ttl == b.m_ttl
+ && a.m_preqId == b.m_preqId
+ && a.m_originatorAddress == b.m_originatorAddress
+ && a.m_originatorSeqNumber == b.m_originatorSeqNumber
+ && a.m_lifetime == b.m_lifetime
+ && a.m_metric == b.m_metric
+ && a.m_destCount == b.m_destCount
+ );
+
+ if (! ok)
+ return false;
+
+ if (a.m_destinations.size() != b.m_destinations.size())
+ return false;
+
+ for (size_t i = 0; i < a.m_destinations.size(); ++i)
+ if (!( *(PeekPointer (a.m_destinations[i])) ==
+ *(PeekPointer (b.m_destinations[i]))
+ )
+ )
+ return false;
+
+ return true;
+}
+bool
+IePreq::MayAddAddress (Mac48Address originator)
+{
+ if (m_originatorAddress != originator)
+ return false;
+ if(m_destinations[0]->GetDestinationAddress () == Mac48Address::GetBroadcast ())
+ return false;
+ return true;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IePreqBist : public IeTest
+{
+ IePreqBist () : IeTest ("Mesh/802.11s/IE/PREQ") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePreqBist g_IePreqBist;
+
+bool IePreqBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IePreq a;
+ a.SetHopcount (0);
+ a.SetTTL (1);
+ a.SetPreqID (2);
+ a.SetOriginatorAddress ( Mac48Address("11:22:33:44:55:66") );
+ a.SetOriginatorSeqNumber (3);
+ a.SetLifetime (4);
+ a.AddDestinationAddressElement (false, false, Mac48Address("11:11:11:11:11:11"), 5);
+ a.AddDestinationAddressElement (false, false, Mac48Address("22:22:22:22:22:22"), 6);
+
+ result = result && TestRoundtripSerialization (a);
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREQ_INFORMATION_ELEMENT_H
+#define WIFI_PREQ_INFORMATION_ELEMENT_H
+
+#include <vector>
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes an address unit in PREQ information element
+ * See 7.3.2.96 for more details
+ */
+class DestinationAddressUnit : public RefCountBase
+{
+public:
+ DestinationAddressUnit ();
+ void SetFlags (bool doFlag, bool rfFlag, bool usnFlag);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ bool IsDo ();
+ bool IsRf ();
+ bool IsUsn ();
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestSeqNumber () const;
+private:
+ bool m_do;
+ bool m_rf;
+ bool m_usn;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+
+ friend bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.96 of 802.11s draft 2.07
+ */
+class IePreq : public WifiInformationElement
+{
+public:
+ IePreq ();
+ ~IePreq ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void AddDestinationAddressElement (
+ bool doFlag,
+ bool rfFlag,
+ Mac48Address dest_address,
+ uint32_t dest_seq_number
+ );
+ void DelDestinationAddressElement (Mac48Address dest_address);
+ void ClearDestinationAddressElement ();
+ std::vector<Ptr<DestinationAddressUnit> > GetDestinationList ();
+ void SetUnicastPreq ();
+ /*
+ * \brief In proactive case: need we send PREP
+ */
+ void SetNeedNotPrep ();
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetPreqID (uint32_t id);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetDestCount (uint8_t dest_count);
+
+ bool IsUnicastPreq () const;
+ bool IsNeedNotPrep () const;
+ uint8_t GetHopCount () const;
+ uint8_t GetTtl ()const ;
+ uint32_t GetPreqID () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ uint8_t GetDestCount () const;
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+ /*
+ * \brief Checks that preq's originator address equals to originator, and
+ * this preq is not proactive
+ */
+ bool MayAddAddress(Mac48Address originator);
+
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PREQ;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream& os) const;
+ /**
+ * how many destinations we support
+ */
+ uint8_t m_maxSize; //TODO: make as an attrubute
+ /**
+ * Fields of information element:
+ */
+ uint8_t m_flags;
+ uint8_t m_hopCount;
+ uint8_t m_ttl;
+ uint32_t m_preqId;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ uint8_t m_destCount;
+ std::vector<Ptr<DestinationAddressUnit> > m_destinations;
+
+ friend bool operator== (const IePreq & a, const IePreq & b);
+};
+
+bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+bool operator== (const IePreq & a, const IePreq & b);
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-rann.h"
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IeRann::~IeRann ()
+{
+}
+TypeId
+IeRann::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IeRann").SetParent<Object> ();
+ return tid;
+}
+TypeId
+IeRann::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IeRann::IeRann ():
+ m_flags (0),
+ m_hopcount (0),
+ m_ttl (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_destSeqNumber (0),
+ m_metric (0)
+{
+}
+void
+IeRann::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IeRann::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IeRann::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IeRann::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IeRann::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IeRann::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+
+uint8_t
+IeRann::GetFlags ()
+{
+ return m_flags;
+}
+uint8_t
+IeRann::GetHopcount ()
+{
+ return m_hopcount;
+}
+uint8_t
+IeRann::GetTtl ()
+{
+ return m_ttl;
+}
+uint32_t
+IeRann::GetDestSeqNumber ()
+{
+ return m_destSeqNumber;
+}
+uint32_t
+IeRann::GetMetric ()
+{
+ return m_metric;
+}
+void
+IeRann::DecrementTtl ()
+{
+ m_ttl --;
+ m_hopcount ++;
+}
+
+void
+IeRann::IncrementMetric (uint32_t m)
+{
+ m_metric += m;
+}
+
+Mac48Address
+IeRann::GetOriginatorAddress ()
+{
+ return m_originatorAddress;
+}
+void
+IeRann::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_destSeqNumber);
+ i.WriteHtolsbU32 (m_metric);
+}
+uint8_t
+IeRann::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_originatorAddress);
+ m_destSeqNumber = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IeRann::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //TTL
+ +6 //OriginatorAddress
+ +4 //DestSeqNumber
+ +4;//Metric
+ return retval;
+}
+
+void
+IeRann::PrintInformation (std::ostream &os) const
+{
+ os << " flags = " << (int)m_flags << "\n";
+ os << " hop count = " << (int)m_hopcount << "\n";
+ os << " TTL = " << (int)m_ttl << "\n";
+ os << " originator address = " << m_originatorAddress<< "\n";
+ os << " dst seq. number = " << m_destSeqNumber << "\n";
+ os << " metric = " << m_metric << "\n";
+}
+
+bool
+operator== (const IeRann & a, const IeRann & b)
+{
+ return (a.m_flags == b.m_flags
+ && a.m_hopcount == b.m_hopcount
+ && a.m_ttl == b.m_ttl
+ && a.m_originatorAddress == b.m_originatorAddress
+ && a.m_destSeqNumber == b.m_destSeqNumber
+ && a.m_metric == b.m_metric
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IeRann
+struct IeRannBist : public IeTest
+{
+ IeRannBist () : IeTest ("Mesh/802.11s/IE/RANN") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeRannBist g_IeRannBist;
+
+bool IeRannBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IeRann a;
+
+ a.SetFlags (1);
+ a.SetHopcount (2);
+ a.SetTTL (4);
+ a.DecrementTtl ();
+ NS_TEST_ASSERT_EQUAL (a.GetTtl(), 3);
+ a.SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
+ a.SetDestSeqNumber (5);
+ a.SetMetric (6);
+ a.IncrementMetric (2);
+ NS_TEST_ASSERT_EQUAL (a.GetMetric(), 8);
+
+ result = result && TestRoundtripSerialization (a);
+ return result;
+}
+#endif // RUN_SELF_TESTS
+
+}} // namespace ns3::dot11s
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef RANN_INFORMATION_ELEMENT_H
+#define RANN_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.95 of 802.11s draft 2.07
+ */
+class IeRann : public WifiInformationElement
+{
+public:
+ IeRann ();
+ virtual ~IeRann ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ void SetMetric (uint32_t metric);
+ uint8_t GetFlags ();
+ uint8_t GetHopcount ();
+ uint8_t GetTtl ();
+ Mac48Address GetOriginatorAddress ();
+ uint32_t GetDestSeqNumber ();
+ uint32_t GetMetric ();
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+
+private:
+ WifiElementId ElementId () const{
+ return IE11S_RANN;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream &os) const;
+
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_originatorAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_metric;
+
+ friend bool operator== (const IeRann & a, const IeRann & b);
+};
+
+bool operator== (const IeRann & a, const IeRann & b);
+
+} // namespace dot11s
+} //namespace ns3
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,253 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "peer-link-frame.h"
+#include "ie-dot11s-peer-management.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+NS_OBJECT_ENSURE_REGISTERED (PeerLinkFrameStart);
+
+PeerLinkFrameStart::PeerLinkFrameStart ():
+ m_subtype (255),
+ m_capability (0),
+ m_aid (0),
+ m_rates (SupportedRates()),
+ m_meshId (IeMeshId()),
+ m_config(IeConfiguration ()),
+ m_reasonCode ((uint16_t)REASON11S_RESERVED)
+{
+}
+void
+PeerLinkFrameStart::SetPlinkFrameSubtype(uint8_t subtype)
+{
+ m_subtype = subtype;
+}
+void
+PeerLinkFrameStart::SetPlinkFrameStart(PeerLinkFrameStart::PlinkFrameStartFields fields)
+{
+ m_subtype = fields.subtype;
+ m_protocol = fields.protocol;
+ if(m_subtype != (uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE))
+ m_capability = fields.capability;
+ if(m_subtype == (uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM))
+ m_aid = fields.aid;
+ if(m_subtype != (uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE))
+ m_rates = fields.rates;
+ if(m_subtype != (uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM))
+ m_meshId = fields.meshId;
+ if(m_subtype != (uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE))
+ m_config = fields.config;
+ else
+ m_reasonCode = fields.reasonCode;
+}
+PeerLinkFrameStart::PlinkFrameStartFields
+PeerLinkFrameStart::GetFields ()
+{
+ PlinkFrameStartFields retval;
+ //TODO: protocol version:
+ retval.subtype = m_subtype;
+ retval.capability = m_capability;
+ retval.aid = m_aid;
+ retval.rates = m_rates;
+ retval.meshId = m_meshId;
+ retval.config = m_config;
+ retval.reasonCode = m_reasonCode;
+ return retval;
+}
+TypeId
+PeerLinkFrameStart::GetTypeId ()
+{
+ static TypeId tid =
+ TypeId ("ns3::dot11s::PeerLinkFrameStart")
+ .SetParent<Header> ()
+ .AddConstructor<PeerLinkFrameStart> ()
+ ;
+ return tid;
+}
+TypeId
+PeerLinkFrameStart::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+PeerLinkFrameStart::Print (std::ostream &os) const
+{
+ os << "subtype = " << (uint16_t)m_subtype
+ << "\ncapability = " << m_capability
+ << "\naid = " << (uint16_t)m_aid
+ << "\nrates = " << m_rates
+ << "\nmeshId = " << m_meshId
+ << "\nconfiguration = " << m_config
+ << "\nreason code = " << m_reasonCode;
+}
+uint32_t
+PeerLinkFrameStart::GetSerializedSize () const
+{
+ uint32_t size = 3; //Peering protocol
+ NS_ASSERT(m_subtype < 3);
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ size += 2; //capability
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ size += 2; //AID of remote peer
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ size += m_rates.GetSerializedSize ();
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ size += m_meshId.GetSerializedSize ();
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ size += m_config.GetSerializedSize ();
+ else
+ size += 2; //reasonCode
+ return size;
+}
+void
+PeerLinkFrameStart::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT(m_subtype < 3);
+ m_protocol.Serialize (i);
+ i.Next (m_protocol.GetSerializedSize ());
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ i.WriteHtolsbU16(m_capability);
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ i.WriteHtolsbU16 (m_aid);
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ i = m_rates.Serialize (i);
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ {
+ m_meshId.Serialize (i);
+ i.Next(m_meshId.GetSerializedSize ());
+ }
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ m_config.Serialize (i);
+ i.Next(m_config.GetSerializedSize ());
+ }
+ else
+ i.WriteHtolsbU16(m_reasonCode);
+}
+uint32_t
+PeerLinkFrameStart::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT(m_subtype < 3);
+ m_protocol.Deserialize (i);
+ i.Next (m_protocol.GetSerializedSize ());
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ m_capability = i.ReadLsbtohU16();
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ m_aid = i.ReadLsbtohU16 ();
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ i = m_rates.Deserialize (i);
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ {
+ m_meshId.Deserialize (i);
+ i.Next(m_meshId.GetSerializedSize ());
+ }
+ if ((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ m_config.Deserialize (i);
+ i.Next (m_config.GetSerializedSize ());
+ }
+ else
+ m_reasonCode = i.ReadLsbtohU16();
+ return i.GetDistanceFrom (start);
+}
+bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b)
+{
+ return (
+ (a.m_subtype == b.m_subtype) &&
+ (a.m_capability == b.m_capability) &&
+ (a.m_aid == b.m_aid) &&
+ (a.m_meshId.IsEqual(b.m_meshId)) &&
+ (a.m_config == b.m_config) &&
+ (a.m_reasonCode == b.m_reasonCode)
+ );
+}
+#ifdef RUN_SELF_TESTS
+/// Built-in self test for PeerLinkFrameStart
+struct PeerLinkFrameStartBist : public Test
+{
+ PeerLinkFrameStartBist () : Test ("Mesh/802.11s/IE/PeerLinkFrameStart") {}
+ virtual bool RunTests();
+};
+/// Test instance
+static PeerLinkFrameStartBist g_PeerLinkFrameStartBist;
+
+bool PeerLinkFrameStartBist::RunTests ()
+{
+ bool result (true);
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshActionHeader::PEER_LINK_OPEN);
+ fields.capability = 0;
+ fields.aid = 101;
+ fields.reasonCode = 12;
+ fields.meshId = IeMeshId("qwertyuiop", 10);
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshActionHeader::PEER_LINK_OPEN));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM);
+ fields.capability = 0;
+ fields.aid = 1234;
+ fields.reasonCode = 12;
+ fields.meshId = IeMeshId("qwerty", 6);
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshActionHeader::PEER_LINK_CONFIRM));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE);
+ fields.capability = 0;
+ fields.aid = 10;
+ fields.meshId = IeMeshId("qqq", 3);
+ fields.reasonCode = 12;
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshActionHeader::PEER_LINK_CLOSE));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_LINK_FRAME_START_H
+#define PEER_LINK_FRAME_START_H
+#include "ns3/header.h"
+#include "ns3/supported-rates.h"
+#include "dot11s-mac-header.h"
+#include "ie-dot11s-configuration.h"
+#include "ie-dot11s-peering-protocol.h"
+#include "ie-dot11s-id.h"
+namespace ns3 {
+class MeshWifiInterfaceMac;
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer link management frame:
+ * \details included the following (see chapters 7.4.12.1-7.4.12.3 of
+ * 802.11s):
+ * - Subtype field
+ * - Association ID field
+ * - Supported rates
+ * - Mesh ID of mesh
+ */
+class PeerLinkFrameStart : public Header
+{
+public:
+ PeerLinkFrameStart ();
+ ///\brief fields:
+ struct PlinkFrameStartFields
+ {
+ uint8_t subtype;
+ IePeeringProtocol protocol; //Peering protocol version - in all subtypes - 3 octets
+ uint16_t capability; //open and confirm
+ uint16_t aid; //confirm only
+ SupportedRates rates; //open and confirm
+ IeMeshId meshId; //open and close
+ IeConfiguration config; //open and confirm
+ uint16_t reasonCode; //close only
+ };
+ ///\attention: must be set before deserialize, before only multihop
+ //action header knows about subtype
+ void SetPlinkFrameSubtype(uint8_t subtype);
+ void SetPlinkFrameStart(PlinkFrameStartFields);
+ PlinkFrameStartFields GetFields ();
+ /** \name Inherited from header:
+ * \{
+ */
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ /**
+ * \}
+ */
+private:
+ uint8_t m_subtype;
+ IePeeringProtocol m_protocol;
+ uint16_t m_capability;
+ uint16_t m_aid;
+ SupportedRates m_rates;
+ IeMeshId m_meshId;
+ IeConfiguration m_config;
+ uint16_t m_reasonCode;
+
+ friend bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+};
+bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,595 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "peer-link.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/traced-value.h"
+
+NS_LOG_COMPONENT_DEFINE ("Dot11sPeerManagementProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED(PeerLink);
+
+TypeId
+PeerLink::GetTypeId()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerLink")
+ .SetParent<Object> ()
+ .AddConstructor<PeerLink> ()
+ .AddAttribute ("RetryTimeout", "Retry timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshRetryTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("HoldingTimeout", "Holding timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshHoldingTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("ConfirmTimeout", "Confirm timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshConfirmTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("MaxRetries", "Maximum number of retries",
+ UintegerValue (4),
+ MakeUintegerAccessor (&PeerLink::m_dot11MeshMaxRetries),
+ MakeUintegerChecker<uint16_t> ()
+ )
+ .AddAttribute ("MaxBeaconLoss", "Maximum number of lost beacons before link will be closed",
+ UintegerValue (2),
+ MakeUintegerAccessor (&PeerLink::m_maxBeaconLoss),
+ MakeUintegerChecker<uint16_t> (1)
+ );
+ return tid;
+}
+
+//-----------------------------------------------------------------------------
+// PeerLink public interface
+//-----------------------------------------------------------------------------
+PeerLink::PeerLink ():
+ m_peerAddress (Mac48Address::GetBroadcast ()),
+ m_peerMeshPointAddress (Mac48Address::GetBroadcast ()),
+ m_localLinkId (0),
+ m_peerLinkId (0),
+ m_state (IDLE),
+ m_retryCounter (0)
+{
+}
+PeerLink::~PeerLink ()
+{
+}
+void
+PeerLink::DoDispose ()
+{
+ m_retryTimer.Cancel ();
+ m_holdingTimer.Cancel ();
+ m_confirmTimer.Cancel ();
+ m_beaconLossTimer.Cancel ();
+ m_beaconTiming.ClearTimingElement ();
+}
+void
+PeerLink::SetPeerAddress (Mac48Address macaddr)
+{
+ m_peerAddress = macaddr;
+}
+void
+PeerLink::SetPeerMeshPointAddress(Mac48Address macaddr)
+{
+ m_peerMeshPointAddress = macaddr;
+}
+void
+PeerLink::SetInterface (uint32_t interface)
+{
+ m_interface = interface;
+}
+void
+PeerLink::SetLocalLinkId (uint16_t id)
+{
+ m_localLinkId = id;
+}
+void
+PeerLink::SetLocalAid (uint16_t aid)
+{
+ m_assocId = aid;
+}
+void
+PeerLink::SetBeaconInformation (Time lastBeacon, Time beaconInterval)
+{
+ m_lastBeacon = lastBeacon;
+ m_beaconInterval = beaconInterval;
+ m_beaconLossTimer.Cancel ();
+ Time delay = Seconds(beaconInterval.GetSeconds() * m_maxBeaconLoss);
+ NS_ASSERT (delay.GetMicroSeconds() != 0);
+ m_beaconLossTimer = Simulator::Schedule (delay, &PeerLink::BeaconLoss, this);
+}
+void
+PeerLink::MLMESetSignalStatusCallback (PeerLink::SignalStatusCallback cb)
+{
+ m_linkStatusCallback = cb;
+}
+void
+PeerLink::BeaconLoss ()
+{
+ StateMachine (CNCL);
+}
+void
+PeerLink::SetBeaconTimingElement (IeBeaconTiming beaconTiming)
+{
+ m_beaconTiming = beaconTiming;
+}
+Mac48Address
+PeerLink::GetPeerAddress () const
+{
+ return m_peerAddress;
+}
+uint16_t
+PeerLink::GetLocalAid () const
+{
+ return m_assocId;
+}
+Time
+PeerLink::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+Time
+PeerLink::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+IeBeaconTiming
+PeerLink::GetBeaconTimingElement () const
+{
+ return m_beaconTiming;
+}
+void
+PeerLink::MLMECancelPeerLink (PmpReasonCode reason)
+{
+ StateMachine (CNCL,reason);
+}
+void
+PeerLink::MLMEPassivePeerLinkOpen ()
+{
+ StateMachine (PASOPN);
+}
+void
+PeerLink::MLMEActivePeerLinkOpen ()
+{
+ StateMachine (ACTOPN);
+}
+void
+PeerLink::MLMEPeeringRequestReject ()
+{
+ StateMachine (REQ_RJCT, REASON11S_PEERING_CANCELLED);
+}
+void
+PeerLink::Close (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reason)
+{
+ if (peerLinkId != 0 && m_localLinkId != peerLinkId)
+ return;
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if (m_peerLinkId != localLinkId)
+ return;
+ StateMachine (CLS_ACPT, reason);
+}
+void
+PeerLink::OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp)
+{
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (OPN_ACPT);
+}
+void
+PeerLink::OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason)
+{
+ if ( m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (OPN_RJCT, reason);
+}
+void
+PeerLink::ConfirmAccept (uint16_t localLinkId, uint16_t peerLinkId, uint16_t peerAid, IeConfiguration conf, Mac48Address peerMp)
+{
+ if ( m_localLinkId != peerLinkId)
+ return;
+ if ( m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if ( m_peerLinkId != localLinkId )
+ return;
+ m_configuration = conf;
+ m_peerAssocId = peerAid;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (CNF_ACPT);
+}
+void
+PeerLink::ConfirmReject (uint16_t localLinkId, uint16_t peerLinkId,
+ IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason)
+{
+ if (m_localLinkId != peerLinkId)
+ return;
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if (m_peerLinkId != localLinkId)
+ return;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (CNF_RJCT, reason);
+}
+bool
+PeerLink::LinkIsEstab () const
+{
+ return (m_state == ESTAB);
+}
+bool
+PeerLink::LinkIsIdle () const
+{
+ return (m_state == IDLE);
+}
+void
+PeerLink::SetMacPlugin(Ptr<PeerManagerMacPlugin> plugin)
+{
+ m_macPlugin = plugin;
+}
+//-----------------------------------------------------------------------------
+// Private
+//-----------------------------------------------------------------------------
+void
+PeerLink::StateMachine (PeerEvent event,PmpReasonCode reasoncode)
+{
+ switch (m_state)
+ {
+ case IDLE:
+ switch (event)
+ {
+ case CNCL:
+ case CLS_ACPT:
+ m_state = IDLE;
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case REQ_RJCT:
+ SendPeerLinkClose (reasoncode);
+ break;
+ case ACTOPN:
+ m_state = OPN_SNT;
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ SendPeerLinkConfirm ();
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case OPN_SNT:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = CNF_RCVD;
+ ClearRetryTimer ();
+ SetConfirmTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case CNF_RCVD:
+ switch (event)
+ {
+ case CNF_ACPT:
+ break;
+ case OPN_ACPT:
+ m_state = ESTAB;
+ ClearConfirmTimer ();
+ SendPeerLinkConfirm ();
+ NS_ASSERT(m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, true);
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case CNF_RJCT:
+ case OPN_RJCT:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ case TOC:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_MESH_CONFIRM_TIMEOUT);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case OPN_RCVD:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = ESTAB;
+ ClearRetryTimer ();
+ NS_ASSERT(m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, true);
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case ESTAB:
+ switch (event)
+ {
+ case OPN_ACPT:
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ default:
+ {}
+ }
+ break;
+ case HOLDING:
+ switch (event)
+ {
+ case CLS_ACPT:
+ ClearHoldingTimer ();
+ case TOH:
+ m_state = IDLE;
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case OPN_ACPT:
+ case CNF_ACPT:
+ m_state = HOLDING;
+ // reason not spec in D2.0
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ SendPeerLinkClose (reasoncode);
+ break;
+ default:
+ {}
+ }
+ break;
+ }
+}
+void
+PeerLink::ClearRetryTimer ()
+{
+ m_retryTimer.Cancel ();
+}
+void
+PeerLink::ClearConfirmTimer ()
+{
+ m_confirmTimer.Cancel ();
+}
+void
+PeerLink::ClearHoldingTimer ()
+{
+ m_holdingTimer.Cancel ();
+}
+void
+PeerLink::SendPeerLinkClose (PmpReasonCode reasoncode)
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerClose (m_localLinkId, m_peerLinkId, reasoncode);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SendPeerLinkOpen ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerOpen (m_localLinkId);
+ NS_ASSERT (m_macPlugin != NULL);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SendPeerLinkConfirm ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerConfirm (m_localLinkId, m_peerLinkId);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SetHoldingTimer ()
+{
+ NS_ASSERT(m_dot11MeshHoldingTimeout.GetMicroSeconds() !=0);
+ m_holdingTimer = Simulator::Schedule (m_dot11MeshHoldingTimeout, &PeerLink::HoldingTimeout, this);
+}
+void
+PeerLink::HoldingTimeout ()
+{
+ StateMachine (TOH);
+}
+void
+PeerLink::SetRetryTimer ()
+{
+ NS_ASSERT(m_dot11MeshRetryTimeout.GetMicroSeconds() !=0);
+ m_retryTimer = Simulator::Schedule (m_dot11MeshRetryTimeout, &PeerLink::RetryTimeout, this);
+}
+void
+PeerLink::RetryTimeout ()
+{
+ if ( m_retryCounter < m_dot11MeshMaxRetries)
+ StateMachine (TOR1);
+ else
+ StateMachine (TOR2);
+}
+void
+PeerLink::SetConfirmTimer ()
+{
+ NS_ASSERT(m_dot11MeshConfirmTimeout.GetMicroSeconds() !=0);
+ m_confirmTimer = Simulator::Schedule (m_dot11MeshConfirmTimeout, &PeerLink::ConfirmTimeout, this);
+}
+void
+PeerLink::ConfirmTimeout ()
+{
+ StateMachine (TOC);
+}
+void
+PeerLink::Report (std::ostream & os) const
+{
+ if(m_state != ESTAB)
+ return;
+ os << "<PeerLink\n"
+ "localAddress=\"" << m_macPlugin->GetAddress () << "\"\n"
+ "peerInterfaceAddress=\"" << m_peerAddress << "\"\n"
+ "peerMeshPointAddress=\"" << m_peerMeshPointAddress << "\"\n"
+ "metricOfTheLink=\"" << m_macPlugin->GetLinkMetric(m_peerAddress) << "\"\n"
+ "m_lastBeacon=\"" << m_lastBeacon.GetMilliSeconds () << "ms\"\n"
+ "m_localLinkId=\"" << m_localLinkId << "\"\n"
+ "m_peerLinkId=\"" << m_peerLinkId << "\"\n"
+ "m_assocId=\"" << m_assocId << "\"\n"
+ "dot11MeshMaxRetries=\"" << m_dot11MeshMaxRetries << "\"\n"
+ "dot11MeshRetryTimeout=\"" << m_dot11MeshRetryTimeout.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshHoldingTimeout=\"" << m_dot11MeshHoldingTimeout.GetMilliSeconds () << "ms\"\n"
+ "dot11MeshConfirmTimeout=\"" << m_dot11MeshConfirmTimeout.GetMilliSeconds () << "ms\"\n"
+ "/>\n";
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,264 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#ifndef PEERLLINK_H_
+#define PEERLLINK_H_
+
+#include "ns3/nstime.h"
+#include "ns3/callback.h"
+#include "ns3/mac48-address.h"
+#include "ns3/event-id.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+#include "peer-management-plugin.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Peer link model for 802.11s Peer Management protocol
+ */
+class PeerLink : public Object
+{
+public:
+ friend class PeerManagementProtocol;
+ /// Support object system
+ static TypeId GetTypeId();
+ /// C-tor create empty link
+ PeerLink ();
+ ~PeerLink ();
+ void DoDispose ();
+
+ /// Process beacon received from peer
+ void SetBeaconInformation (Time lastBeacon, Time BeaconInterval);
+ /**
+ * \brief Method used to detecet peer link changes
+ *
+ * \param bool if true - opened new link, if false - link closed
+ */
+ void SetLinkStatusCallback (Callback<void, uint32_t, Mac48Address, bool> cb);
+ /**
+ * \name Peer link geeters/setters
+ * \{
+ */
+ void SetPeerAddress (Mac48Address macaddr);
+ void SetPeerMeshPointAddress (Mac48Address macaddr);
+ void SetInterface (uint32_t interface);
+ void SetLocalLinkId (uint16_t id);
+ void SetPeerLinkId (uint16_t id);
+ void SetLocalAid (uint16_t aid);
+ void SetPeerAid (uint16_t aid);
+ void SetBeaconTimingElement (IeBeaconTiming beaconTiming);
+ void SetPeerLinkDescriptorElement (IePeerManagement peerLinkElement);
+ Mac48Address GetPeerAddress () const;
+ uint16_t GetLocalAid () const;
+ Time GetLastBeacon () const;
+ Time GetBeaconInterval () const;
+ IeBeaconTiming GetBeaconTimingElement ()const;
+ IePeerManagement GetPeerLinkDescriptorElement ()const;
+ //\}
+
+ /**
+ * \name MLME
+ * \{
+ */
+ /// MLME-CancelPeerLink.request
+ void MLMECancelPeerLink (PmpReasonCode reason);
+ /// MLME-PassivePeerLinkOpen.request
+ void MLMEPassivePeerLinkOpen ();
+ /// MLME-ActivePeerLinkOpen.request
+ void MLMEActivePeerLinkOpen ();
+ /// MLME-PeeringRequestReject
+ void MLMEPeeringRequestReject ();
+ /// Callback type for MLME-SignalPeerLinkStatus event
+ typedef Callback<void, uint32_t, Mac48Address, Mac48Address, bool> SignalStatusCallback;
+ /// Set callback
+ void MLMESetSignalStatusCallback (SignalStatusCallback);
+ //\}
+ ///\brief Statistics
+ void Report (std::ostream & os) const;
+private:
+ /**
+ * \name Link response to received management frames
+ *
+ * \attention In all this methods {local/peer}LinkID correspond to _peer_ station, as written in
+ * received frame, e.g. I am peerLinkID and peer link is localLinkID .
+ *
+ * TODO is that clear?
+ *
+ * \{
+ */
+ /// Close link
+ void Close (uint16_t localLinkID, uint16_t peerLinkID, PmpReasonCode reason);
+ /// Accept open link
+ void OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp);
+ /// Reject open link
+ void OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason);
+ /// Confirm accept
+ void ConfirmAccept (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ uint16_t peerAid,
+ IeConfiguration conf,
+ Mac48Address peerMp
+ );
+ /// Confirm reject
+ void ConfirmReject (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ IeConfiguration conf,
+ Mac48Address peerMp,
+ PmpReasonCode reason
+ );
+ //\}
+
+ /// True if link is established
+ bool LinkIsEstab () const;
+ /// True if link is idle. Link can be deleted in this state
+ bool LinkIsIdle () const;
+ /**
+ * Set pointer to MAC-plugin, which is responsible for sending peer
+ * link management frames
+ */
+ void SetMacPlugin(Ptr<PeerManagerMacPlugin> plugin);
+private:
+ /// Peer link states, see 802.11s draft 11B.3.3.1
+ enum PeerState {
+ IDLE,
+ OPN_SNT,
+ CNF_RCVD,
+ OPN_RCVD,
+ ESTAB,
+ HOLDING,
+ };
+ /// Peer link events, see 802.11s draft 11B.3.3.2
+ enum PeerEvent
+ {
+ CNCL, ///< MLME-CancelPeerLink
+ PASOPN, ///< MLME-PassivePeerLinkOpen
+ ACTOPN, ///< MLME-ActivePeerLinkOpen
+ CLS_ACPT, ///< PeerLinkClose_Accept
+ OPN_ACPT, ///< PeerLinkOpen_Accept
+ OPN_RJCT, ///< PeerLinkOpen_Reject
+ REQ_RJCT, ///< PeerLinkOpenReject by internal reason
+ CNF_ACPT, ///< PeerLinkConfirm_Accept
+ CNF_RJCT, ///< PeerLinkConfirm_Reject
+ TOR1, ///< Timeout of retry timer
+ TOR2, ///< also timeout of retry timer
+ TOC, ///< Timeout of confirm timer
+ TOH, ///< Timeout of holding (gracefull closing) timer
+ };
+
+private:
+ /// State transition
+ void StateMachine (PeerEvent event, PmpReasonCode = REASON11S_RESERVED);
+
+ /**
+ * \name Event handlers
+ * \{
+ */
+ void ClearRetryTimer ();
+ void ClearConfirmTimer ();
+ void ClearHoldingTimer ();
+ void SetHoldingTimer ();
+ void SetRetryTimer ();
+ void SetConfirmTimer ();
+ //\}
+
+ /**
+ * \name Work with management frames
+ * \{
+ */
+ void SendPeerLinkClose (PmpReasonCode reasoncode);
+ void SendPeerLinkOpen ();
+ void SendPeerLinkConfirm ();
+ //\}
+
+ /**
+ * \name Timeout handlers
+ * \{
+ */
+ void HoldingTimeout ();
+ void RetryTimeout ();
+ void ConfirmTimeout ();
+ //\}
+
+private:
+ ///The number of interface I am associated with
+ uint32_t m_interface;
+ /// pointer to mac plugin, which is responsible for peer management
+ Ptr<PeerManagerMacPlugin> m_macPlugin;
+ /// Peer address
+ Mac48Address m_peerAddress;
+ /// Mesh point address, equal to peer address in case of single
+ //interface mesh point
+ Mac48Address m_peerMeshPointAddress;
+ /// My ID of this link
+ uint16_t m_localLinkId;
+ /// Peer ID of this link
+ uint16_t m_peerLinkId;
+ /// My association ID
+ uint16_t m_assocId;
+ /// Assoc Id assigned to me by peer
+ uint16_t m_peerAssocId;
+
+ /// When last beacon was sent (TODO or received?)
+ Time m_lastBeacon;
+ /// Current beacon interval on corresponding interface
+ Time m_beaconInterval;
+
+ /// Current state
+ PeerState m_state;
+ /// Mesh interface configuration
+ IeConfiguration m_configuration;
+
+ // State is a bitfield as defined as follows:
+ // This are states for a given
+ IeBeaconTiming m_beaconTiming;
+
+ /**
+ * \name Timers & counters used for internal state transitions
+ * \{
+ */
+ uint16_t m_dot11MeshMaxRetries;
+ Time m_dot11MeshRetryTimeout;
+ Time m_dot11MeshHoldingTimeout;
+ Time m_dot11MeshConfirmTimeout;
+
+ EventId m_retryTimer;
+ EventId m_holdingTimer;
+ EventId m_confirmTimer;
+ uint16_t m_retryCounter;
+ EventId m_beaconLossTimer;
+ uint16_t m_maxBeaconLoss;
+ //\}
+
+ /// ?
+ void BeaconLoss ();
+
+ /// How to report my status change
+ SignalStatusCallback m_linkStatusCallback;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif /* PEERLLINK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-plugin.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,317 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-configuration.h"
+#include "ie-dot11s-peer-management.h"
+#include "dot11s-mac-header.h"
+#include "peer-management-plugin.h"
+#include "peer-management-protocol.h"
+#include "peer-link-frame.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/simulator.h"
+#include "ns3/wifi-mac-header.h"
+namespace ns3 {
+namespace dot11s {
+PeerManagerMacPlugin::PeerManagerMacPlugin (uint32_t interface, Ptr<PeerManagementProtocol> protocol)
+{
+ m_ifIndex = interface;
+ m_protocol = protocol;
+}
+
+PeerManagerMacPlugin::~PeerManagerMacPlugin ()
+{
+}
+
+void
+PeerManagerMacPlugin::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+
+bool
+PeerManagerMacPlugin::Receive (Ptr<Packet> const_packet, const WifiMacHeader & header)
+{
+ // First of all we copy a packet, because we need to remove some
+ //headers
+ Ptr<Packet> packet = const_packet->Copy();
+ if(header.IsBeacon())
+ {
+ IeBeaconTiming beaconTiming;
+ IeMeshId meshId;
+ Ptr<Packet> myBeacon = packet->Copy();
+ MgtBeaconHeader beacon_hdr;
+ myBeacon->RemoveHeader(beacon_hdr);
+ meshId.FindFirst(myBeacon);
+ bool meshBeacon = false;
+ if (
+ (beaconTiming.FindFirst(myBeacon)) &&
+ (m_protocol->GetMeshId ()->IsEqual(meshId))
+ )
+ meshBeacon = true;
+ m_protocol->UpdatePeerBeaconTiming(
+ m_ifIndex,
+ meshBeacon,
+ beaconTiming,
+ header.GetAddr2(),
+ Simulator::Now(),
+ MicroSeconds(beacon_hdr.GetBeaconIntervalUs())
+ );
+ // Beacon shall not be dropeed. May be needed to another plugins
+ return true;
+ }
+ if(header.IsAction())
+ {
+ WifiMeshActionHeader actionHdr;
+ packet->RemoveHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ // If can not handle - just return;
+ if(actionHdr.GetCategory () != WifiMeshActionHeader::MESH_PEER_LINK_MGT)
+ return m_protocol->IsActiveLink(m_ifIndex,header.GetAddr2());
+ m_stats.recvMgt ++;
+ m_stats.recvMgtBytes += packet->GetSize ();
+ Mac48Address peerAddress = header.GetAddr2 ();
+ Mac48Address peerMpAddress = header.GetAddr3 ();
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ {
+ PeerLinkFrameStart peerFrame;
+ peerFrame.SetPlinkFrameSubtype((uint8_t)actionValue.peerLink);
+ packet->RemoveHeader (peerFrame);
+ fields = peerFrame.GetFields();
+ NS_ASSERT(fields.subtype == actionValue.peerLink);
+ }
+ if (
+ (actionValue.peerLink != WifiMeshActionHeader::PEER_LINK_CLOSE) &&
+ !(m_parent->CheckSupportedRates(fields.rates))
+ )
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ m_stats.brokenMgt ++;
+ return false;
+ }
+ if (
+ (actionValue.peerLink != WifiMeshActionHeader::PEER_LINK_CONFIRM) &&
+ !fields.meshId.IsEqual(*(m_protocol->GetMeshId()))
+ )
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ m_stats.brokenMgt ++;
+ return false;
+ }
+ IePeerManagement peerElement;
+ packet->RemoveHeader(peerElement);
+ //Check taht frame subtype corresponds peer link subtype
+ if(peerElement.SubtypeIsOpen ())
+ {
+ m_stats.recvOpen ++;
+ NS_ASSERT(actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_OPEN);
+ }
+ if(peerElement.SubtypeIsConfirm ())
+ {
+ m_stats.recvConfirm ++;
+ NS_ASSERT(actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_CONFIRM);
+ }
+ if(peerElement.SubtypeIsClose ())
+ {
+ m_stats.recvClose ++;
+ NS_ASSERT(actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_CLOSE);
+ }
+ //Deliver Peer link management frame to protocol:
+ m_protocol->ReceivePeerLinkFrame(m_ifIndex, peerAddress, peerMpAddress, fields.aid, peerElement, fields.config);
+ // if we can handle a frame - drop it
+ return false;
+ }
+ return m_protocol->IsActiveLink(m_ifIndex,header.GetAddr2());
+}
+bool
+PeerManagerMacPlugin::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to)
+{
+ if(header.IsAction ())
+ {
+ WifiMeshActionHeader actionHdr;
+ packet->PeekHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ if(actionHdr.GetCategory () == WifiMeshActionHeader::MESH_PEER_LINK_MGT)
+ return true;
+ }
+ if(header.GetAddr1 ().IsGroup ())
+ return true;
+ else
+ {
+ if(m_protocol->IsActiveLink(m_ifIndex,header.GetAddr1()))
+ return true;
+ else
+ {
+ m_stats.dropped ++;
+ return false;
+ }
+ }
+}
+void
+PeerManagerMacPlugin::UpdateBeacon (MeshWifiBeacon & beacon) const
+{
+ Ptr<IeBeaconTiming> beaconTiming = m_protocol->GetBeaconTimingElement(m_ifIndex);
+ beacon.AddInformationElement(beaconTiming);
+ beacon.AddInformationElement(m_protocol->GetMeshId ());
+}
+
+void
+PeerManagerMacPlugin::SendPeerLinkManagementFrame(
+ Mac48Address peerAddress,
+ Mac48Address peerMpAddress,
+ uint16_t aid,
+ IePeerManagement peerElement,
+ IeConfiguration meshConfig
+ )
+{
+ //Create a packet:
+ meshConfig.SetNeighborCount (m_protocol->GetNumberOfLinks ());
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (peerElement);
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.rates = m_parent->GetSupportedRates ();
+ fields.capability = 0;
+ fields.meshId = *(m_protocol->GetMeshId ());
+ fields.config = meshConfig;
+ PeerLinkFrameStart plinkFrame;
+ //Create an 802.11 frame header:
+ //Send management frame to MAC:
+ WifiMeshActionHeader actionHdr;
+ if (peerElement.SubtypeIsOpen ())
+ {
+ m_stats.sendOpen ++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_OPEN;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_OPEN;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ if (peerElement.SubtypeIsConfirm ())
+ {
+ m_stats.sendConfirm ++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_CONFIRM;
+ fields.aid = aid;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_CONFIRM;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ if (peerElement.SubtypeIsClose ())
+ {
+ m_stats.sendClose ++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_CLOSE;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_CLOSE;
+ fields.reasonCode = peerElement.GetReasonCode ();
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ plinkFrame.SetPlinkFrameStart(fields);
+ packet->AddHeader (plinkFrame);
+ packet->AddHeader (actionHdr);
+ m_stats.sentMgt ++;
+ m_stats.sentMgtBytes += packet->GetSize ();
+ // Wifi Mac header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetAddr1 (peerAddress);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ //Addr is not used here, we use it as our MP address
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ m_parent->SendManagementFrame(packet, hdr);
+}
+
+Mac48Address
+PeerManagerMacPlugin::GetAddress () const
+{
+ if(m_parent != 0)
+ return m_parent->GetAddress ();
+ else return Mac48Address::Mac48Address();
+}
+std::pair<Time, Time>
+PeerManagerMacPlugin::GetBeaconInfo() const
+{
+ std::pair<Time,Time> retval;
+ retval.first = m_parent->GetTbtt ();
+ retval.second = m_parent->GetBeaconInterval ();
+ return retval;
+}
+void
+PeerManagerMacPlugin::SetBeaconShift(Time shift)
+{
+ if(shift != Seconds (0))
+ m_stats.beaconShift ++;
+ m_parent->ShiftTbtt (shift);
+}
+PeerManagerMacPlugin::Statistics::Statistics () :
+ sendOpen (0),
+ sendConfirm (0),
+ sendClose (0),
+ recvOpen (0),
+ recvConfirm (0),
+ recvClose (0),
+ dropped (0),
+ brokenMgt (0),
+ sentMgt (0),
+ sentMgtBytes (0),
+ recvMgt (0),
+ recvMgtBytes (0),
+ beaconShift (0)
+{
+}
+void
+PeerManagerMacPlugin::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "sendOpen=\"" << sendOpen << "\"\n"
+ "sendConfirm=\"" << sendConfirm << "\"\n"
+ "sendClose=\"" << sendClose << "\"\n"
+ "recvOpen=\"" << recvOpen << "\"\n"
+ "recvConfirm=\"" << recvConfirm << "\"\n"
+ "recvClose=\"" << recvClose << "\"\n"
+ "dropped=\"" << dropped << "\"\n"
+ "brokenMgt=\"" << brokenMgt << "\"\n"
+ "sentMgt=\"" << sentMgt << "\"\n"
+ "sentMgtBytes=\"" << (double)sentMgtBytes /1024.0 << "\"\n"
+ "recvMgt=\"" << recvMgt << "\"\n"
+ "recvMgtBytes=\"" << (double)recvMgtBytes / 1024.0 << "K\"\n"
+ "beaconShift=\"" << beaconShift << "\"/>\n";
+}
+void
+PeerManagerMacPlugin::Report (std::ostream & os) const
+{
+ os << "<PeerManagerPlugin "
+ "address=\"" << m_parent->GetAddress () << "\">\n";
+ m_stats.Print (os);
+ os << "</PeerManagerPlugin>\n";
+}
+void
+PeerManagerMacPlugin::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+uint32_t
+PeerManagerMacPlugin::GetLinkMetric (Mac48Address peerAddress)
+{
+ return m_parent->GetLinkMetric (peerAddress);
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-plugin.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_MANAGER_MAC_PLUGIN_H_
+#define PEER_MANAGER_MAC_PLUGIN_H_
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+
+namespace ns3 {
+class MeshWifiInterfaceMac;
+namespace dot11s {
+class PeerManagementProtocol;
+class IeConfiguration;
+class IePeerManagement;
+class PeerManagementProtocol;
+/**
+ * \ingroup dot11s
+ *
+ * \brief This is plugin to Mesh WiFi MAC, which implements
+ * interface to dot11s peer management protocol: it takes proper
+ * frames from MAC-layer, extracts peer link management information
+ * element and mesh configuration element and passes it to main part
+ * of protocol
+ */
+class PeerManagerMacPlugin : public MeshWifiInterfaceMacPlugin
+{
+public:
+ PeerManagerMacPlugin (uint32_t interface, Ptr<PeerManagementProtocol> protocol);
+ ~PeerManagerMacPlugin ();
+ ///\name Inherited from plugin abstract class
+ ///\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to);
+ void UpdateBeacon (MeshWifiBeacon & beacon) const;
+ ///\}
+ ///\name Statistics:
+ ///\{
+ void Report (std::ostream &) const;
+ void ResetStats ();
+ uint32_t GetLinkMetric (Mac48Address peerAddress);
+ ///\}
+private:
+ friend class PeerManagementProtocol;
+ friend class PeerLink;
+ ///\name BCA functionallity:
+ ///\{
+ ///\brief Fills TBTT and beacon interval. Needed by BCA
+ ///functionallity
+ ///\param first in retval is TBTT
+ ///\param second in retval is beacon interval
+ std::pair<Time, Time> GetBeaconInfo() const;
+ void SetBeaconShift(Time shift);
+ ///\}
+ void SetPeerManagerProtcol(Ptr<PeerManagementProtocol> protocol);
+ void SendPeerLinkManagementFrame(
+ Mac48Address peerAddress,
+ Mac48Address peerMpAddress,
+ uint16_t aid,
+ IePeerManagement peerElement,
+ IeConfiguration meshConfig
+ );
+ ///\brief DUBUG only - to print established links
+ Mac48Address GetAddress () const;
+private:
+ ///\name Information about MAC and protocol:
+ ///\{
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<PeerManagementProtocol> m_protocol;
+ ///\}
+ ///\name Create peer link management frames:
+ ///\{
+ Ptr<Packet> CreatePeerLinkOpenFrame();
+ Ptr<Packet> CreatePeerLinkConfirmFrame();
+ Ptr<Packet> CreatePeerLinkCloseFrame();
+ ///This structure keeps all fields in peer link management frame,
+ ///which are not subclasses of WifiInformationElement
+ struct PlinkFrameStart {
+ uint8_t subtype;
+ uint16_t aid;
+ SupportedRates rates;
+ uint16_t qos;
+ };
+ /// \name Parses the start of the frame, where there are no
+ /// WifiInformationElements exist
+ PlinkFrameStart ParsePlinkFrame(Ptr<const Packet> packet);
+ ///\}
+ //Keeps statistics
+ struct Statistics {
+ uint16_t sendOpen;
+ uint16_t sendConfirm;
+ uint16_t sendClose;
+ uint16_t recvOpen;
+ uint16_t recvConfirm;
+ uint16_t recvClose;
+ uint16_t dropped;
+ uint16_t brokenMgt;
+ uint16_t sentMgt;
+ uint32_t sentMgtBytes;
+ uint16_t recvMgt;
+ uint32_t recvMgtBytes;
+ uint16_t beaconShift;
+
+ Statistics ();
+ void Print (std::ostream & os) const;
+ };
+ struct Statistics m_stats;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,525 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "peer-management-protocol.h"
+
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+
+#include "ns3/mesh-point-device.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/wifi-net-device.h"
+#include "peer-link.h"
+#include "peer-management-plugin.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("PeerManagementProtocol");
+namespace ns3 {
+namespace dot11s {
+/***************************************************
+ * PeerManager
+ ***************************************************/
+NS_OBJECT_ENSURE_REGISTERED (PeerManagementProtocol);
+
+TypeId
+PeerManagementProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerManagementProtocol")
+ .SetParent<Object> ()
+ .AddConstructor<PeerManagementProtocol> ()
+ // maximum number of peer links. Now we calculate the total
+ // number of peer links on all interfaces
+ .AddAttribute ("MaxNumberOfPeerLinks",
+ "Maximum number of peer links",
+ UintegerValue (32),
+ MakeUintegerAccessor (&PeerManagementProtocol::m_maxNumberOfPeerLinks),
+ MakeUintegerChecker<uint8_t> ()
+ );
+ return tid;
+}
+PeerManagementProtocol::PeerManagementProtocol ():
+ m_lastAssocId (0),
+ m_lastLocalLinkId (1),
+ m_numberOfActivePeers (0)
+{
+}
+PeerManagementProtocol::~PeerManagementProtocol ()
+{
+}
+void
+PeerManagementProtocol::DoDispose ()
+{
+ //cancel cleanup event and go through the map of peer links,
+ //deleting each
+ for (PeerLinksMap::iterator j = m_peerLinks.begin (); j != m_peerLinks.end (); j++)
+ {
+ for (PeerLinksOnInterface::iterator i = j->second.begin (); i != j->second.end(); i++)
+ (*i) = 0;
+ j->second.clear ();
+ }
+ m_peerLinks.clear ();
+ //cleaning beacon structures:
+ for(BeaconInfoMap::iterator i = m_neighbourBeacons.begin(); i != m_neighbourBeacons.end(); i ++)
+ {
+ i->second.clear();
+ }
+ m_neighbourBeacons.clear();
+}
+
+bool
+PeerManagementProtocol::Install(Ptr<MeshPointDevice> mp)
+{
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for(std::vector<Ptr<NetDevice> >::iterator i = interfaces.begin(); i != interfaces.end(); i ++)
+ {
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ return false;
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (mac == 0)
+ return false;
+ Ptr<PeerManagerMacPlugin> peerPlugin = Create<PeerManagerMacPlugin> ((*i)->GetIfIndex(), this);
+ mac->InstallPlugin(peerPlugin);
+ m_plugins[(*i)->GetIfIndex()] = peerPlugin;
+ PeerLinksOnInterface newmap;
+ m_peerLinks[(*i)->GetIfIndex()] = newmap;
+ }
+ // Mesh point aggregates all installed protocols
+ m_address = Mac48Address::ConvertFrom(mp->GetAddress ());
+ NS_LOG_UNCOND("MP address:"<<m_address);
+ mp->AggregateObject(this);
+ return true;
+}
+
+Ptr<IeBeaconTiming>
+PeerManagementProtocol::GetBeaconTimingElement(uint32_t interface)
+{
+ Ptr<IeBeaconTiming> retval = Create<IeBeaconTiming> ();
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find(interface);
+ if(i == m_neighbourBeacons.end())
+ return retval;
+ bool cleaned = false;
+ while(!cleaned)
+ {
+ for(BeaconsOnInterface::iterator j = i->second.begin(); j != i->second.end(); j++)
+ {
+ //check beacon loss and make a timing element
+ //if last beacon was 3 beacons ago - we do not put it to the
+ //timing element
+ if(
+ (j->second.referenceTbtt.GetMicroSeconds() +
+ (j->second.beaconInterval.GetMicroSeconds()* 3))
+ <
+ Simulator::Now().GetMicroSeconds()
+ )
+ {
+ i->second.erase(j);
+ break;
+ }
+ }
+ cleaned = true;
+ }
+ for(BeaconsOnInterface::const_iterator j = i->second.begin(); j != i->second.end(); j++)
+ retval->AddNeighboursTimingElementUnit(j->second.aid, j->second.referenceTbtt, j->second.beaconInterval);
+ return retval;
+}
+
+void
+PeerManagementProtocol::FillBeaconInfo(uint32_t interface, Mac48Address peerAddress, Time receivingTime, Time beaconInterval)
+{
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find(interface);
+ if(i == m_neighbourBeacons.end())
+ {
+ BeaconsOnInterface newMap;
+ m_neighbourBeacons[interface] = newMap;
+ }
+ i = m_neighbourBeacons.find(interface);
+ BeaconsOnInterface::iterator j = i->second.find(peerAddress);
+ if(j == i->second.end())
+ {
+ BeaconInfo newInfo;
+ newInfo.referenceTbtt = receivingTime;
+ newInfo.beaconInterval = beaconInterval;
+ newInfo.aid = m_lastAssocId++;
+ if(m_lastAssocId == 0xff)
+ m_lastAssocId = 0;
+ i->second[peerAddress] = newInfo;
+ }
+ else
+ {
+ j->second.referenceTbtt = receivingTime;
+ j->second.beaconInterval = beaconInterval;
+ }
+}
+
+void
+PeerManagementProtocol::UpdatePeerBeaconTiming(
+ uint32_t interface,
+ bool meshBeacon,
+ IeBeaconTiming timingElement,
+ Mac48Address peerAddress,
+ Time receivingTime,
+ Time beaconInterval)
+{
+ FillBeaconInfo(interface, peerAddress, receivingTime, beaconInterval);
+ if(!meshBeacon)
+ return;
+ //BCA:
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end ());
+ plugin->second->SetBeaconShift(GetNextBeaconShift(interface));
+ //PM STATE Machine
+ //Check that a given beacon is not from our interface
+ for(PeerManagerPluginMap::const_iterator i = m_plugins.begin (); i != m_plugins.end (); i ++)
+ if(i->second->GetAddress () == peerAddress)
+ return;
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink !=0)
+ {
+ peerLink->SetBeaconTimingElement (timingElement);
+ peerLink->SetBeaconInformation (receivingTime, beaconInterval);
+ }
+ else
+ {
+ peerLink = InitiateLink (interface, peerAddress, Mac48Address::GetBroadcast (), receivingTime, beaconInterval);
+ peerLink->SetBeaconTimingElement (timingElement);
+ if (ShouldSendOpen (interface, peerAddress))
+ peerLink->MLMEActivePeerLinkOpen ();
+ }
+}
+
+void
+PeerManagementProtocol::ReceivePeerLinkFrame (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ uint16_t aid,
+ IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig
+ )
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if (peerManagementElement.SubtypeIsOpen ())
+ {
+ PmpReasonCode reasonCode;
+ bool reject = ! (ShouldAcceptOpen (interface, peerAddress,reasonCode));
+ if (peerLink == 0)
+ peerLink = InitiateLink (interface, peerAddress, peerMeshPointAddress, Simulator::Now (), Seconds(1.0));
+ if(!reject)
+ {
+ peerLink->MLMEPassivePeerLinkOpen ();
+ peerLink->OpenAccept (peerManagementElement.GetLocalLinkId(), meshConfig, peerMeshPointAddress);
+ }
+ else
+ peerLink->OpenReject (peerManagementElement.GetLocalLinkId(), meshConfig, peerMeshPointAddress, reasonCode);
+ }
+ if (peerLink == 0)
+ return;
+ if (peerManagementElement.SubtypeIsConfirm ())
+ peerLink->ConfirmAccept (
+ peerManagementElement.GetLocalLinkId(),
+ peerManagementElement.GetPeerLinkId(),
+ aid,
+ meshConfig,
+ peerMeshPointAddress);
+ if (peerManagementElement.SubtypeIsClose ())
+ peerLink->Close (
+ peerManagementElement.GetLocalLinkId(),
+ peerManagementElement.GetPeerLinkId(),
+ peerManagementElement.GetReasonCode()
+ );
+}
+
+void
+PeerManagementProtocol::ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink != 0)
+ peerLink->MLMECancelPeerLink (REASON11S_MESH_CAPABILITY_POLICY_VIOLATION);
+}
+
+Ptr<PeerLink>
+PeerManagementProtocol::InitiateLink (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ Time lastBeacon,
+ Time beaconInterval)
+{
+ Ptr<PeerLink> new_link = CreateObject<PeerLink> ();
+ if (m_lastLocalLinkId == 0xff)
+ m_lastLocalLinkId = 0;
+ //find a beacon entry
+ BeaconInfoMap::iterator beaconsOnInterface = m_neighbourBeacons.find (interface);
+ if(beaconsOnInterface == m_neighbourBeacons.end())
+ FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+ beaconsOnInterface = m_neighbourBeacons.find (interface);
+ BeaconsOnInterface::iterator beacon = beaconsOnInterface->second.find (peerAddress);
+ if(beacon == beaconsOnInterface->second.end ())
+ FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+ beacon = beaconsOnInterface->second.find (peerAddress);
+ //find a peer link - it must not exist
+ if(FindPeerLink(interface, peerAddress) != 0)
+ {
+ NS_ASSERT (false);
+ }
+ // Plugin must exist
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end ());
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ new_link->SetLocalAid (beacon->second.aid);
+ new_link->SetInterface (interface);
+ new_link->SetLocalLinkId (m_lastLocalLinkId++);
+ new_link->SetPeerAddress (peerAddress);
+ new_link->SetPeerMeshPointAddress (peerMeshPointAddress);
+ new_link->SetBeaconInformation (lastBeacon, beaconInterval);
+ new_link->SetMacPlugin (plugin->second);
+ new_link->MLMESetSignalStatusCallback (MakeCallback(&PeerManagementProtocol::PeerLinkStatus, this));
+ iface->second.push_back (new_link);
+ return new_link;
+}
+Ptr<PeerLink>
+PeerManagementProtocol::FindPeerLink(uint32_t interface, Mac48Address peerAddress)
+{
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end(); i++)
+ if ((*i)->GetPeerAddress () == peerAddress)
+ {
+ if((*i)->LinkIsIdle ())
+ {
+ (*i) = 0;
+ (iface->second).erase(i);
+ return 0;
+ }
+ else
+ return (*i);
+ }
+ return 0;
+}
+void
+PeerManagementProtocol::SetPeerLinkStatusCallback(Callback <void, Mac48Address, Mac48Address, uint32_t, bool> cb)
+{
+ m_peerStatusCallback = cb;
+}
+std::vector<Mac48Address>
+PeerManagementProtocol::GetActiveLinks(uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end(); i++)
+ if((*i)->LinkIsEstab ())
+ retval.push_back((*i)->GetPeerAddress ());
+ return retval;
+}
+bool
+PeerManagementProtocol::IsActiveLink (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink != 0)
+ return (peerLink->LinkIsEstab ());
+ return false;
+}
+bool
+PeerManagementProtocol::ShouldSendOpen (uint32_t interface, Mac48Address peerAddress)
+{
+ if (m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+ return false;
+ return true;
+}
+bool
+PeerManagementProtocol::ShouldAcceptOpen (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ PmpReasonCode & reasonCode)
+{
+ if (m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+ {
+ reasonCode = REASON11S_MESH_MAX_PEERS;
+ return false;
+ }
+ return true;
+}
+Time
+PeerManagementProtocol::GetNextBeaconShift (uint32_t interface)
+{
+ //REMINDER:: in timing element 1) last beacon reception time is measured in units of 256 microseconds
+ // 2) beacon interval is mesured in units of 1024 microseconds
+ // 3) hereafter TU = 1024 microseconds
+ //Im my MAC everything is stored in MicroSeconds
+
+ uint32_t myNextTbttInTimeUnits = Simulator::Now().GetMicroSeconds();
+ uint32_t futureBeaconInTimeUnits = 0;
+ //Going through all my timing elements and detecting future beacon collisions
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end());
+ std::pair<Time, Time> myBeacon = plugin->second->GetBeaconInfo ();
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ IeBeaconTiming::NeighboursTimingUnitsList neighbours;
+ neighbours = (*i)->GetBeaconTimingElement ().GetNeighboursTimingElementsList();
+ //first let's form the list of all kown Tbtts
+ for (IeBeaconTiming::NeighboursTimingUnitsList::const_iterator j = neighbours.begin (); j != neighbours.end(); j++)
+ {
+ uint16_t beaconIntervalTimeUnits;
+ beaconIntervalTimeUnits = (*j)->GetBeaconInterval ();
+ //The last beacon time in timing elememt in Time Units
+ uint32_t lastBeaconInTimeUnits;
+ lastBeaconInTimeUnits = (*j)->GetLastBeacon ()/4;
+ //The time of my next beacon sending in Time Units
+ myNextTbttInTimeUnits = myBeacon.first.GetMicroSeconds ()/1024;
+ //My beacon interval in Time Units
+ uint32_t myBeaconIntervalInTimeUnits;
+ myBeaconIntervalInTimeUnits = myBeacon.second.GetMicroSeconds ()/1024;
+ //The time the beacon of other station will be sent
+ //we need the time just after my next Tbtt (or equal to my Tbtt)
+ futureBeaconInTimeUnits = lastBeaconInTimeUnits + beaconIntervalTimeUnits;
+ //We apply MBAC only if beacon Intervals are equal
+ if (beaconIntervalTimeUnits == myBeaconIntervalInTimeUnits)
+ {
+ //We know when the neighbor STA transmitted it's beacon
+ //Now we need to know when it's going to send it's beacon in the future
+ //So let's use the valuse of it's beacon interval
+ while (myNextTbttInTimeUnits >= futureBeaconInTimeUnits)
+ futureBeaconInTimeUnits = futureBeaconInTimeUnits + beaconIntervalTimeUnits;
+ //If we found that my Tbtt coincide with another STA's Tbtt
+ //break all cylce and return time shift for my next Tbtt
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ break;
+ }
+ }
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ break;
+ }
+ //Tbtts coincide, so let's calculate the shift
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ {
+ NS_LOG_DEBUG ("MBCA: Future beacon collision is detected, applying avoidance mechanism");
+ UniformVariable randomSign (-1, 1);
+ int coefficientSign = -1;
+ if (randomSign.GetValue () >= 0)
+ coefficientSign = 1;
+ UniformVariable randomShift (1, 15);
+ //So, the shift is a random integer variable uniformly distributed in [-15;-1] U [1;15]
+ int beaconShift = randomShift.GetInteger (1,15) * coefficientSign;
+ NS_LOG_DEBUG ("Shift value = " << beaconShift << " beacon TUs");
+ //We need the result not in Time Units, but in microseconds
+ //Do not shift to the past
+ if(MicroSeconds(beaconShift * 1024) + Simulator::Now() < myBeacon.first)
+ return MicroSeconds (beaconShift * 1024);
+ else
+ return MicroSeconds (0);
+ }
+ //No collision detected, hence no shift is needed
+ else
+ return MicroSeconds (0);
+}
+void
+PeerManagementProtocol::PeerLinkStatus (uint32_t interface, Mac48Address peerAddress, Mac48Address peerMeshPointAddress, bool status)
+{
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end());
+ NS_LOG_DEBUG(
+ "Link between me:" << m_address <<
+ " my interface:" << plugin->second->GetAddress() <<
+ " and peer mesh point:" << peerMeshPointAddress <<
+ " and its interface:" << peerAddress <<
+ ", at my interface ID:" << interface <<
+ ". Status:" << status);
+ if(status)
+ {
+ m_stats.linksOpened ++;
+ m_numberOfActivePeers ++;
+ }
+ else
+ {
+ m_stats.linksClosed ++;
+ m_numberOfActivePeers --;
+ }
+ if(!m_peerStatusCallback.IsNull ())
+ m_peerStatusCallback (peerMeshPointAddress, peerAddress, interface, status);
+}
+uint8_t
+PeerManagementProtocol::GetNumberOfLinks ()
+{
+ return m_numberOfActivePeers;
+}
+Ptr<IeMeshId>
+PeerManagementProtocol::GetMeshId () const
+{
+ NS_ASSERT (m_meshId != 0);
+ return m_meshId;
+}
+void
+PeerManagementProtocol::SetMeshId(char const meshId[32], uint8_t length)
+{
+ m_meshId = Create<IeMeshId> (meshId, length);
+}
+Mac48Address
+PeerManagementProtocol::GetAddress ()
+{
+ return m_address;
+}
+void
+PeerManagementProtocol::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "linksOpened=\"" << linksOpened << "\" "
+ "linksClosed=\"" << linksClosed << "\"/>\n";
+}
+void
+PeerManagementProtocol::Report (std::ostream & os) const
+{
+ os << "<PeerManagementProtocol>\n";
+ m_stats.Print (os);
+ for(PeerManagerPluginMap::const_iterator plugins = m_plugins.begin (); plugins != m_plugins.end (); plugins ++)
+ {
+ //Take statistics from plugin:
+ plugins->second->Report (os);
+ //Print all active peer links:
+ PeerLinksMap::const_iterator iface = m_peerLinks.find (plugins->second->m_ifIndex);
+ NS_ASSERT (iface != m_peerLinks.end());
+ for (PeerLinksOnInterface::const_iterator i = iface->second.begin (); i != iface->second.end(); i++)
+ (*i)->Report (os);
+ }
+ os << "</PeerManagementProtocol>\n";
+}
+void
+PeerManagementProtocol::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+ for(PeerManagerPluginMap::const_iterator plugins = m_plugins.begin (); plugins != m_plugins.end (); plugins ++)
+ plugins->second->ResetStats ();
+}
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef DOT11S_PEER_MAN_H
+#define DOT11S_PEER_MAN_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/net-device.h"
+#include "ns3/event-id.h"
+#include "ns3/nstime.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-id.h"
+
+#include <map>
+namespace ns3 {
+class MeshPointDevice;
+namespace dot11s {
+class PeerManagerMacPlugin;
+class PeerLink;
+class IePeerManagement;
+class IeConfiguration;
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer Management Protocol model
+ */
+class PeerManagementProtocol : public Object
+{
+public:
+ PeerManagementProtocol ();
+ ~PeerManagementProtocol ();
+ static TypeId GetTypeId ();
+ void DoDispose ();
+ /**
+ * \brief Install PMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, PMP protocol can be accessed
+ * via MeshPointDevice::GetObject<PeerManagementProtocol>();
+ */
+ bool Install(Ptr<MeshPointDevice>);
+ /**
+ * \brief Methods that handle beacon sending/receiving procedure.
+ *
+ * This methods interact with MAC_layer plug-in
+ * \{
+ */
+ /**
+ * \brief When we are sending a beacon - we fill beacon timing
+ * element
+ * \param IeBeaconTiming is a beacon timing element that
+ * should be present in beacon
+ * \param interface is a interface sending a beacon
+ */
+ Ptr<IeBeaconTiming> GetBeaconTimingElement(uint32_t interface);
+ /**
+ * \brief When we receive a beacon from peer-station, we remember
+ * its beacon timing element (needed for peer choosing mechanism),
+ * and remember beacon timers - last beacon and beacon interval to
+ * detect beacon loss and cancel links
+ * \param interface is a interface on which beacon was received
+ * \param timingElement is a timing element of remote beacon
+ */
+ void UpdatePeerBeaconTiming(
+ uint32_t interface,
+ bool meshBeacon,
+ IeBeaconTiming timingElement,
+ Mac48Address peerAddress,
+ Time receivingTime,
+ Time beaconInterval
+ );
+ //\}
+ /**
+ * \brief Methods that handle Peer link management frames
+ * interaction:
+ * \{
+ */
+ /**
+ * Deliver Peer link management information to the protocol-part
+ * \param void is returning value - we pass a frame and forget
+ * about it
+ * \param uint32_t - is a interface ID of a given MAC (interfaceID rather
+ * than MAC address, beacause many interfaces may have the same MAC)
+ * \param Mac48Address is address of peer
+ * \param Mac48Address is address of peer mesh point device (equal
+ * to peer address when only one interface)
+ * \param uint16_t is association ID, which peer has assigned to
+ * us
+ * \param IeConfiguration is mesh configuration element
+ * taken from the peer management frame
+ * \param IePeerManagement is peer link management element
+ */
+ void ReceivePeerLinkFrame(
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ uint16_t aid,
+ IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig
+ );
+ /**
+ * Cancell peer link due to broken configuration (SSID or Supported
+ * rates)
+ */
+ void ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress);
+ /**
+ * Checks if there is established link
+ */
+ bool IsActiveLink (uint32_t interface, Mac48Address peerAddress);
+ //\}
+ ///\brief Needed by external module to do MLME
+ Ptr<PeerLink> FindPeerLink(uint32_t interface, Mac48Address peerAddress);
+ void SetPeerLinkStatusCallback (Callback<void, Mac48Address, Mac48Address, uint32_t, bool> cb);
+ std::vector<Mac48Address> GetActiveLinks(uint32_t interface);
+ ///\brief needed by plugins to set global source address
+ Mac48Address GetAddress ();
+ ///\Needed to fill mesh configuration
+ uint8_t GetNumberOfLinks ();
+ void SetMeshId (char const meshId[32], uint8_t length);
+ Ptr<IeMeshId> GetMeshId() const;
+ ///\brief: Report statistics
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ /** \name Private structures
+ * \{
+ */
+ /// Keeps information about beacon of peer station: beacon interval, association ID, last time we have received a beacon
+ struct BeaconInfo
+ {
+ uint16_t aid; //Assoc ID
+ Time referenceTbtt; //When one of my station's beacons was put into a beacon queue;
+ Time beaconInterval; //Beacon interval of my station;
+ };
+ /// We keep a vector of pointers to PeerLink class. This vector
+ /// keeps all peer links at a given interface.
+ typedef std::vector<Ptr<PeerLink> > PeerLinksOnInterface;
+ /// This map keeps all peer links.
+ ///\param uint32_t is interface ID
+ typedef std::map<uint32_t, PeerLinksOnInterface> PeerLinksMap;
+ ///\brief This map keeps relationship between peer address and its
+ /// beacon information
+ typedef std::map<Mac48Address, BeaconInfo> BeaconsOnInterface;
+ ///\brief This map keeps beacon information on all intefaces
+ typedef std::map<uint32_t, BeaconsOnInterface> BeaconInfoMap;
+ ///\brief this vector keeps pointers to MAC-plugins
+ typedef std::map<uint32_t, Ptr<PeerManagerMacPlugin> > PeerManagerPluginMap;
+ ///\}
+private:
+ /**
+ * Return a position in beacon-storage for a given remote station
+ */
+ void FillBeaconInfo(uint32_t interface, Mac48Address peerAddress, Time receivingTime, Time beaconInterval);
+ Ptr<PeerLink> InitiateLink (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ Time lastBeacon,
+ Time beaconInterval
+ );
+ /**
+ * \name External peer-chooser
+ * \{
+ */
+ bool ShouldSendOpen (uint32_t interface, Mac48Address peerAddress);
+ bool ShouldAcceptOpen (uint32_t interface, Mac48Address peerAddress, PmpReasonCode & reasonCode);
+ /**
+ * \}
+ * \brief Indicates changes in peer links
+ */
+ void PeerLinkStatus (uint32_t interface, Mac48Address peerAddress, Mac48Address peerMeshPointAddres, bool status);
+ ///\brief BCA
+ Time GetNextBeaconShift (uint32_t interface);
+private:
+ PeerManagerPluginMap m_plugins;
+ Mac48Address m_address;
+ Ptr<IeMeshId> m_meshId;
+ /**
+ * \name Information related to beacons:
+ * \{
+ */
+ BeaconInfoMap m_neighbourBeacons;
+ ///\}
+ uint16_t m_lastAssocId;
+ uint16_t m_lastLocalLinkId;
+ uint8_t m_numberOfActivePeers; //number of established peer links
+ uint8_t m_maxNumberOfPeerLinks;
+ /**
+ * Peer Links
+ * \{
+ */
+ PeerLinksMap m_peerLinks;
+ /**
+ * \}
+ */
+ ///\brief Callback to notify about peer link changes:
+ ///\param Mac48Address is peer address of mesh point
+ ///\param Mac48Address is peer address of interface
+ ///\param uint32_t - interface ID
+ ///\param bool is staus - true when new link has appeared, false -
+ //when link was closed
+ Callback <void, Mac48Address, Mac48Address, uint32_t, bool> m_peerStatusCallback;
+ ///\}
+ //Keeps statistics
+ struct Statistics {
+ uint16_t linksOpened;
+ uint16_t linksClosed;
+
+ Statistics () : linksOpened (0), linksClosed (0) {};
+ void Print (std::ostream & os) const;
+ };
+ struct Statistics m_stats;
+
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/waf Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/wscript Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,38 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('dot11s', ['wifi'])
+ obj.source = [
+ 'ie-dot11s-beacon-timing.cc',
+ 'ie-dot11s-configuration.cc',
+ 'ie-dot11s-id.cc',
+ 'ie-dot11s-peer-management.cc',
+ 'ie-dot11s-preq.cc',
+ 'ie-dot11s-prep.cc',
+ 'ie-dot11s-perr.cc',
+ 'ie-dot11s-rann.cc',
+ 'ie-dot11s-peering-protocol.cc',
+ 'dot11s-mac-header.cc',
+ 'peer-link-frame.cc',
+ 'peer-link.cc',
+ 'peer-management-plugin.cc',
+ 'peer-management-protocol.cc',
+ 'hwmp-tag.cc',
+ 'hwmp-rtable.cc',
+ 'hwmp-mac-plugin.cc',
+ 'hwmp-protocol.cc',
+ 'airtime-metric.cc',
+ 'dot11s-helper.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'dot11s'
+ headers.source = [
+ 'peer-management-protocol.h',
+ 'ie-dot11s-beacon-timing.h',
+ 'ie-dot11s-id.h',
+ 'ie-dot11s-peer-management.h',
+ 'ie-dot11s-perr.h',
+ 'hwmp-protocol.h',
+ 'dot11s-helper.h',
+ 'dot11s-mac-header.h',
+ ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/log.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/mesh-point-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshL2RoutingProtocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshL2RoutingProtocol);
+
+TypeId
+MeshL2RoutingProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::MeshL2RoutingProtocol")
+ .SetParent<Object> ();
+ return tid;
+}
+
+MeshL2RoutingProtocol::~MeshL2RoutingProtocol ()
+{
+}
+
+void
+MeshL2RoutingProtocol::SetMeshPoint (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+}
+
+Ptr<MeshPointDevice> MeshL2RoutingProtocol::GetMeshPoint () const
+{
+ return m_mp;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESH_L2_ROUTING_PROTOCOL_H
+#define MESH_L2_ROUTING_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+class Packet;
+class MeshPointDevice;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Interface for L2 mesh routing protocol and mesh point communication.
+ *
+ * Every mesh routing protocol must implement this interface. Each mesh point (MeshPointDevice) is supposed
+ * to know single L2RoutingProtocol to work with, see MeshPointDevice::SetRoutingProtocol ().
+ *
+ * This interface is similar to ipv4 routiong protocol base class.
+ */
+class MeshL2RoutingProtocol : public Object
+{
+public:
+ /// Never forget to support NS3 object model
+ static TypeId GetTypeId ();
+ /// virtual D-tor for subclasses
+ virtual ~MeshL2RoutingProtocol ();
+ /**
+ * Callback to be invoked when route discovery procedure is completed.
+ *
+ * \param flag indicating whether a route was actually found and all needed information is
+ * added to the packet succesfully
+ *
+ * \param packet for which the route was resolved. All routing information for MAC layer
+ * must be stored in proper tags (like in case of HWMP, when WifiMacHeader
+ * needs address of next hop), or must be added as a packet header (if MAC
+ * does not need any additional information). So, the packet is returned back
+ * to MeshPointDevice looks like a pure packet with ethernet header
+ * (i.e data + src +dst + protocol). The only special information addressed
+ * to MeshPointDevice is an outcoming interface ID.
+ *
+ * \param src source address of the packet
+ *
+ * \param dst destiation address of the packet
+ *
+ * \param protocol ethernet 'Protocol' field, needed to form a proper MAC-layer header
+ *
+ * \param uint32_t outcoming interface to use or 0xffffffff if packet should be sent by ALL interfaces
+ */
+ typedef Callback<void,/* return type */
+ bool, /* flag */
+ Ptr<Packet>, /* packet */
+ Mac48Address,/* src */
+ Mac48Address,/* dst */
+ uint16_t, /* protocol */
+ uint32_t /* out interface ID */
+ > RouteReplyCallback;
+ /**
+ * Request routing information, all packets must go through this request.
+ *
+ * Note that route discobery works async. -- RequestRoute returns immediately, while
+ * reply callback will be called when routing information will be avaliable.
+ * \return true if valid route is already known
+ * \param sourceIface the incoming interface of the packet
+ * \param source source address
+ * \param destination destination address
+ * \param packet the packet to be resolved (needed the whole packet, because
+ * routing information is added as tags or headers). The packet
+ * will be retutned to reply callback.
+ * \param protocolType protocol ID, needed to form a proper MAC-layer header
+ * \param routeReply callback to be invoked after route discovery procedure, supposed
+ * to really send packetusing routing information.
+ */
+ virtual bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply ) = 0;
+ /// Set host mesh point, analog of SetNode (...) methods for upper layer protocols.
+ void SetMeshPoint (Ptr<MeshPointDevice> mp);
+ /// Each mesh protocol must be installed on the mesh point to work.
+ Ptr<MeshPointDevice> GetMeshPoint () const;
+protected:
+ /// Host mesh point
+ Ptr<MeshPointDevice> m_mp;
+};
+}//namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,390 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshPointDevice");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshPointDevice);
+
+TypeId
+MeshPointDevice::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshPointDevice")
+ .SetParent<NetDevice> ()
+ .AddConstructor<MeshPointDevice> ()
+ .AddAttribute ("RoutingProtocol", "The mesh routing protocol used by this mesh point.",
+ PointerValue (),
+ MakePointerAccessor (&MeshPointDevice::GetRoutingProtocol,
+ &MeshPointDevice::SetRoutingProtocol),
+ MakePointerChecker<MeshL2RoutingProtocol> ())
+ ;
+ return tid;
+}
+
+MeshPointDevice::MeshPointDevice () : m_ifIndex (0), m_mtu(1500)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_channel = CreateObject<BridgeChannel> ();
+}
+
+MeshPointDevice::~MeshPointDevice ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+MeshPointDevice::DoDispose ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (std::vector< Ptr<NetDevice> >::iterator iter = m_ifaces.begin (); iter != m_ifaces.end (); iter++)
+ *iter = 0;
+ m_ifaces.clear ();
+ m_node = 0;
+ NetDevice::DoDispose ();
+
+}
+
+//-----------------------------------------------------------------------------
+// NetDevice interface implementation
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &src, Address const &dst, PacketType packetType)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_DEBUG ("UID is " << packet->GetUid ());
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
+ NS_LOG_DEBUG ("SRC="<<src48<<", DST = "<<dst48<<", I am: "<<m_address);
+ if (!m_promiscRxCallback.IsNull ())
+ m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
+ if(dst48.IsBroadcast () || dst48.IsGroup ())
+ {
+ m_rxCallback (this, packet, protocol, src);
+ Forward (incomingPort, packet->Copy (), protocol, src48, dst48);
+ return;
+ }
+ if(dst48 == m_address)
+ m_rxCallback (this, packet, protocol, src);
+ else
+ Forward (incomingPort, packet->Copy (), protocol, src48, dst48);
+}
+
+void
+MeshPointDevice::Forward (Ptr<NetDevice> inport, Ptr<Packet> packet,
+ uint16_t protocol, const Mac48Address src, const Mac48Address dst)
+{
+ // pass through routing protocol
+ m_requestRoute (inport->GetIfIndex(), src, dst, packet, protocol, m_myResponse);
+}
+
+void
+MeshPointDevice::SetName (const std::string name)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_name = name;
+}
+
+std::string
+MeshPointDevice::GetName () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_name;
+}
+
+void
+MeshPointDevice::SetIfIndex (const uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_ifIndex = index;
+}
+
+uint32_t
+MeshPointDevice::GetIfIndex () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifIndex;
+}
+
+Ptr<Channel>
+MeshPointDevice::GetChannel () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_channel;
+}
+
+Address
+MeshPointDevice::GetAddress () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_address;
+}
+
+bool
+MeshPointDevice::SetMtu (const uint16_t mtu)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_mtu = mtu;
+ return true;
+}
+
+uint16_t
+MeshPointDevice::GetMtu () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_mtu;
+}
+
+bool
+MeshPointDevice::IsLinkUp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+ // do nothing
+}
+
+bool
+MeshPointDevice::IsBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+MeshPointDevice::IsMulticast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+ NS_LOG_FUNCTION (this << multicastGroup);
+ Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
+ return multicast;
+}
+
+bool
+MeshPointDevice::IsPointToPoint () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+bool
+MeshPointDevice::IsBridge () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+
+bool
+MeshPointDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ NS_LOG_DEBUG("SEND:, DST = "<<dst48<<", I am: "<<m_address);
+ return m_requestRoute (m_ifIndex, m_address, dst48, packet, protocolNumber, m_myResponse);
+}
+
+bool
+MeshPointDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
+{
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ return m_requestRoute (m_ifIndex, src48, dst48, packet, protocolNumber, m_myResponse);
+}
+
+Ptr<Node>
+MeshPointDevice::GetNode () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+MeshPointDevice::SetNode (Ptr<Node> node)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = node;
+}
+
+bool
+MeshPointDevice::NeedsArp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_rxCallback = cb;
+}
+
+void
+MeshPointDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_promiscRxCallback = cb;
+}
+
+bool
+MeshPointDevice::SupportsSendFrom () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false; // don't allow to bridge mesh network with something else.
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv6Address addr) const
+{
+ NS_LOG_FUNCTION (this << addr);
+ return Mac48Address::GetMulticast (addr);
+}
+
+//-----------------------------------------------------------------------------
+// Interfaces
+//-----------------------------------------------------------------------------
+uint32_t
+MeshPointDevice::GetNInterfaces () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifaces.size ();
+}
+
+Ptr<NetDevice>
+MeshPointDevice::GetInterface (uint32_t n) const
+{
+ for(std::vector< Ptr<NetDevice> >::const_iterator i = m_ifaces.begin (); i != m_ifaces.end (); i ++)
+ if((*i)->GetIfIndex() == n)
+ return (*i);
+ NS_ASSERT(false);
+ return 0;
+}
+std::vector<Ptr<NetDevice> >
+MeshPointDevice::GetInterfaces () const
+{
+ return m_ifaces;
+}
+void
+MeshPointDevice::AddInterface (Ptr<NetDevice> iface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ NS_ASSERT (iface != this);
+ if (!Mac48Address::IsMatchingType (iface->GetAddress ()))
+ {
+ NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be used as a mesh point interface.");
+ }
+ if (!iface->SupportsSendFrom ())
+ {
+ NS_FATAL_ERROR ("Device does not support SendFrom: cannot be used as a mesh point interface.");
+ }
+
+ // Mesh point has MAC address of it's first interface
+ if (m_ifaces.empty())
+ m_address = Mac48Address::ConvertFrom (iface->GetAddress ());
+
+ const WifiNetDevice * wifiNetDev = dynamic_cast<const WifiNetDevice *> (PeekPointer (iface));
+ if (wifiNetDev == 0)
+ NS_FATAL_ERROR ("Device is not a WiFi NIC: cannot be used as a mesh point interface.");
+
+ MeshWifiInterfaceMac * ifaceMac = dynamic_cast<MeshWifiInterfaceMac *> (PeekPointer (wifiNetDev->GetMac ()));
+ if (ifaceMac == 0)
+ NS_FATAL_ERROR ("WiFi device doesn't have correct MAC installed: cannot be used as a mesh point interface.");
+
+ ifaceMac->SetMeshPointAddress (m_address);
+
+ // Receive frames from this interface
+ m_node->RegisterProtocolHandler (MakeCallback (&MeshPointDevice::ReceiveFromDevice, this),
+ 0, iface, /*promiscuous = */true);
+
+ m_ifaces.push_back (iface);
+ m_channel->AddChannel (iface->GetChannel ());
+}
+
+//-----------------------------------------------------------------------------
+// Protocols
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ NS_ASSERT_MSG (PeekPointer(protocol->GetMeshPoint()) == this, "Routing protocol must be installed on mesh point to be useful.");
+
+ m_routingProtocol = protocol;
+ m_requestRoute = MakeCallback (&MeshL2RoutingProtocol::RequestRoute, protocol);
+ m_myResponse = MakeCallback (&MeshPointDevice::DoSend, this);
+
+ return;
+}
+
+Ptr<MeshL2RoutingProtocol>
+MeshPointDevice::GetRoutingProtocol () const
+{
+ return m_routingProtocol;
+}
+
+void
+MeshPointDevice::DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst, uint16_t protocol, uint32_t outIface)
+{
+ if (!success)
+ {
+ NS_LOG_DEBUG ("Resolve failed");
+ return;
+ }
+ // Ok, now I know the route, just SendFrom
+ if (outIface != 0xffffffff)
+ GetInterface (outIface)->SendFrom(packet, src, dst, protocol);
+ else
+ for (std::vector<Ptr<NetDevice> >::iterator i = m_ifaces.begin (); i != m_ifaces.end(); i++)
+ (*i) -> SendFrom (packet, src, dst, protocol);
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef L2ROUTING_NET_DEVICE_H
+#define L2ROUTING_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include "ns3/bridge-channel.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+
+namespace ns3 {
+
+class Node;
+/**
+ * \ingroup mesh
+ *
+ * \brief Virtual net device modeling mesh point.
+ *
+ * Mesh point is a virtual net device which is responsible for
+ * - Aggreagating and coordinating 1..* real devices -- mesh interfaces, see MeshInterfaceDevice class.
+ * - Hosting all mesh-related level 2 protocols.
+ *
+ * One of hosted L2 protocols must inplement L2RoutingProtocol interface and is used for packets forwarding.
+ *
+ * From the level 3 point of view MeshPointDevice is similar to BridgeNetDevice, but the packets,
+ * which going through may be changed (because L2 protocols may require their own headers or tags).
+ *
+ * Attributes: TODO
+ */
+class MeshPointDevice : public NetDevice
+{
+public:
+ /// Object type ID for NS3 object system
+ static TypeId GetTypeId ();
+ /// C-tor create empty (without interfaces and protocols) mesh point
+ MeshPointDevice ();
+ /// D-tor
+ virtual ~MeshPointDevice ();
+
+ ///\name Interfaces
+ //\{
+ /**
+ * \brief Attach new interface to the station. Interface must support 48-bit MAC address and SendFrom method.
+ *
+ * \attention Only MeshPointDevice can have IP address, but not individual interfaces.
+ */
+ void AddInterface (Ptr<NetDevice> port);
+ /**
+ * \return number of interfaces
+ */
+ uint32_t GetNInterfaces () const;
+ /**
+ * \return interface device by its index (aka ID)
+ * \param id is interface id, 0 <= id < GetNInterfaces
+ */
+ Ptr<NetDevice> GetInterface (uint32_t id) const;
+ /**
+ * \return vector of interfaces
+ */
+ std::vector<Ptr<NetDevice> > GetInterfaces () const;
+ //\}
+
+ ///\name Protocols
+ //\{
+ /// Register routing protocol to be used. Protocol must be alredy installed on this mesh point.
+ void SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol);
+ /// Access current routing protocol
+ Ptr<MeshL2RoutingProtocol> GetRoutingProtocol() const;
+ //\}
+
+ ///\name NetDevice interface for upper layers
+ //\{
+ virtual void SetName (const std::string name);
+ virtual std::string GetName () const;
+ virtual void SetIfIndex (const uint32_t index);
+ virtual uint32_t GetIfIndex () const;
+ virtual Ptr<Channel> GetChannel () const;
+ virtual Address GetAddress () const;
+ virtual bool SetMtu (const uint16_t mtu);
+ virtual uint16_t GetMtu () const;
+ virtual bool IsLinkUp () const;
+ virtual void SetLinkChangeCallback (Callback<void> callback);
+ virtual bool IsBroadcast () const;
+ virtual Address GetBroadcast () const;
+ virtual bool IsMulticast () const;
+ virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+ virtual bool IsPointToPoint () const;
+ virtual bool IsBridge () const;
+ virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+ virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+ virtual Ptr<Node> GetNode () const;
+ virtual void SetNode (Ptr<Node> node);
+ virtual bool NeedsArp () const;
+ virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+ virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
+ virtual bool SupportsSendFrom () const;
+ virtual Address GetMulticast (Ipv6Address addr) const;
+ virtual void DoDispose ();
+ //\}
+
+private:
+ /// Receive packet from interface
+ void ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &source, Address const &destination, PacketType packetType);
+ /// Forward packet down to interfaces
+ void Forward (Ptr<NetDevice> incomingPort, Ptr<Packet> packet,
+ uint16_t protocol, const Mac48Address src, const Mac48Address dst);
+ /**
+ * Response callback for L2 routing protocol. This will be executed when routing information is ready.
+ *
+ * \param success True is route found. TODO: diagnose routing errors
+ * \param packet Packet to send
+ * \param src Source MAC address
+ * \param dst Destination MAC address
+ * \param protocol Protocol ID
+ * \param outIface Interface to use (ID) for send (decided by routing protocol). All interfaces will be used if outIface = 0xffffffff
+ */
+ void DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst, uint16_t protocol, uint32_t iface);
+
+private:
+ /// Receive action
+ NetDevice::ReceiveCallback m_rxCallback;
+ /// Promisc receive action
+ NetDevice::PromiscReceiveCallback m_promiscRxCallback;
+ /// Mesh point MAC address, supposed to be the address of the first added interface
+ Mac48Address m_address;
+ /// Parent node
+ Ptr<Node> m_node;
+ /// Station name
+ std::string m_name;
+ /// List of interfaces
+ std::vector< Ptr<NetDevice> > m_ifaces;
+ /// If index
+ uint32_t m_ifIndex;
+ /// MTU in bytes
+ uint16_t m_mtu;
+ /// Virtual channel for upper layers
+ Ptr<BridgeChannel> m_channel;
+
+ /// Routing request callback
+ Callback<bool,
+ uint32_t,
+ Mac48Address,
+ Mac48Address,
+ Ptr<Packet>,
+ uint16_t,
+ MeshL2RoutingProtocol::RouteReplyCallback> m_requestRoute;
+
+ /// Routing response callback, this is supplied to mesh routing protocol
+ MeshL2RoutingProtocol::RouteReplyCallback m_myResponse;
+ /// Current routing protocol, used mainly by GetRoutingProtocol
+ Ptr<MeshL2RoutingProtocol> m_routingProtocol;
+};
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-beacon.h"
+#include <algorithm>
+
+namespace ns3 {
+
+MeshWifiBeacon::MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us)
+{
+ m_header.SetSsid (ssid);
+ m_header.SetSupportedRates (rates);
+ m_header.SetBeaconIntervalUs (us);
+}
+
+void MeshWifiBeacon::AddInformationElement (Ptr<WifiInformationElement> ie)
+{
+ m_elements.push_back (ie);
+}
+
+namespace {
+/// aux sorter for Ptr<WifiInformationElement>
+struct PIEComparator
+{
+ bool operator () (Ptr<WifiInformationElement> a, Ptr<WifiInformationElement> b) const
+ {
+ return ((*PeekPointer (a)) < (*PeekPointer(b)));
+ }
+};
+}
+
+Ptr<Packet> MeshWifiBeacon::CreatePacket ()
+{
+ Ptr<Packet> packet = Create<Packet> ();
+
+ std::sort (m_elements.begin(), m_elements.end(), PIEComparator());
+
+ std::vector< Ptr<WifiInformationElement> >::const_reverse_iterator i;
+ for (i = m_elements.rbegin(); i != m_elements.rend(); ++i)
+ {
+ packet->AddHeader (**i);
+ }
+
+ packet->AddHeader (BeaconHeader());
+
+ return packet;
+}
+
+WifiMacHeader MeshWifiBeacon::CreateHeader (Mac48Address address, Mac48Address mpAddress)
+{
+ WifiMacHeader hdr;
+
+ hdr.SetBeacon ();
+ hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+ hdr.SetAddr2 (address);
+ hdr.SetAddr3 (mpAddress);
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+
+ return hdr;
+}
+
+} // namespace
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIBEACON_H_
+#define MESHWIFIBEACON_H_
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/wifi-information-element.h"
+#include "ns3/mgt-headers.h" // from wifi module
+#include "ns3/wifi-mac-header.h"
+
+#include <vector>
+
+namespace ns3 {
+
+/**
+ * \brief Beacon is beacon header + list of arbitrary information elements
+ *
+ * It is supposed that distinct mesh protocols can use beacons to transport
+ * their own information elements.
+ */
+class MeshWifiBeacon
+{
+public:
+ /**
+ * C-tor
+ *
+ * \param ssid is SSID for beacon header
+ * \param rates is a set of supported rates
+ * \param us beacon interval in microseconds
+ */
+ MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us);
+ /// Read standard Wifi beacon header
+ MgtBeaconHeader BeaconHeader () const { return m_header; }
+ /// Add information element
+ void AddInformationElement (Ptr<WifiInformationElement> ie);
+
+ /// Create wifi header for beacon frame. \param address is sender address \param mpAddress is mesh point address
+ WifiMacHeader CreateHeader (Mac48Address address, Mac48Address mpAddress);
+ /// Create frame = { beacon header + all information elements sorted by ElementId () }
+ Ptr<Packet> CreatePacket ();
+
+private:
+ /// Beacon header
+ MgtBeaconHeader m_header;
+ /// List of information elements added
+ std::vector< Ptr<WifiInformationElement> > m_elements;
+};
+
+}
+
+
+#endif /* MESHWIFIBEACON_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMACPLUGIN_H_
+#define MESHWIFIINTERFACEMACPLUGIN_H_
+
+#include "ns3/wifi-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Common interface for mesh point interface MAC plugins
+ *
+ * TODO: plugins description
+ */
+class MeshWifiInterfaceMacPlugin : public RefCountBase
+{
+public:
+ /// This is for subclasses
+ virtual ~MeshWifiInterfaceMacPlugin (){};
+ /// Each plugin must be installed on interface to work
+ virtual void SetParent (Ptr<MeshWifiInterfaceMac> parent) = 0;
+ /**
+ * \brief Process received frame
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this
+ */
+ virtual bool Receive (Ptr<Packet> packet, const WifiMacHeader & header) = 0;
+ /**
+ * \brief Update frame before it will be forwarded down
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this, preconditions & postconditions
+ */
+ virtual bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) = 0;
+ /**
+ * \brief Update beacon before it will be formed and sent
+ *
+ * TODO define when MAC call this
+ */
+ virtual void UpdateBeacon (MeshWifiBeacon & beacon) const = 0;
+};
+
+} // namespace ns3
+#endif /* MESHWIFIINTERFACEMACPLUGIN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,668 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/log.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/dcf-manager.h"
+#include "ns3/mac-rx-middle.h"
+#include "ns3/mac-low.h"
+#include "ns3/dca-txop.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+#include "ns3/yans-wifi-phy.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshWifiInterfaceMac);
+
+TypeId
+MeshWifiInterfaceMac::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshWifiInterfaceMac")
+ .SetParent<WifiMac> ()
+ .AddConstructor<MeshWifiInterfaceMac> ()
+ .AddAttribute ("BeaconInterval", "Beacon Interval",
+ TimeValue (Seconds (1.0)),
+ MakeTimeAccessor (&MeshWifiInterfaceMac::m_beaconInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("RandomStart", "Window when beacon generating starts (uniform random) in seconds",
+ TimeValue (Seconds (0.1)),
+ MakeTimeAccessor (&MeshWifiInterfaceMac::m_randomStart),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("BeaconGeneration", "Enable/Disable Beaconing.",
+ BooleanValue (true),
+ MakeBooleanAccessor (
+ &MeshWifiInterfaceMac::SetBeaconGeneration,
+ &MeshWifiInterfaceMac::GetBeaconGeneration
+ ),
+ MakeBooleanChecker ()
+ );
+ return tid;
+}
+
+MeshWifiInterfaceMac::MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+
+ m_rxMiddle = new MacRxMiddle ();
+ m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiInterfaceMac::Receive, this));
+
+ m_low = CreateObject<MacLow> ();
+ m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+ m_dcfManager = new DcfManager ();
+ m_dcfManager->SetupLowListener (m_low);
+
+ m_beaconDca = CreateObject<DcaTxop> ();
+ m_beaconDca->SetLow (m_low);
+ m_beaconDca->SetMinCw (0);
+ m_beaconDca->SetMaxCw (0);
+ m_beaconDca->SetAifsn (1);
+ m_beaconDca->SetManager (m_dcfManager);
+
+ m_VO = CreateObject<DcaTxop> ();
+ m_VO->SetLow (m_low);
+ m_VO->SetMinCw (3);
+ m_VO->SetMaxCw (7);
+ m_VO->SetManager (m_dcfManager);
+
+ m_BE = CreateObject<DcaTxop> ();
+ m_BE->SetLow (m_low);
+ m_BE->SetManager (m_dcfManager);
+}
+
+MeshWifiInterfaceMac::~MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+//-----------------------------------------------------------------------------
+// WifiMac inherited
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetSlot (Time slotTime)
+{
+ NS_LOG_FUNCTION (this << slotTime);
+ m_dcfManager->SetSlot (slotTime);
+ m_slot = slotTime;
+}
+
+void
+MeshWifiInterfaceMac::SetSifs (Time sifs)
+{
+ NS_LOG_FUNCTION (this << sifs);
+ m_dcfManager->SetSifs (sifs);
+ m_sifs = sifs;
+}
+void
+MeshWifiInterfaceMac::SetAckTimeout (Time ackTimeout)
+{
+ m_low->SetAckTimeout (ackTimeout);
+}
+
+void
+MeshWifiInterfaceMac::SetCtsTimeout (Time ctsTimeout)
+{
+ m_low->SetCtsTimeout (ctsTimeout);
+}
+
+void
+MeshWifiInterfaceMac::SetPifs (Time pifs)
+{
+ NS_LOG_FUNCTION (this << pifs);
+ m_pifs = pifs;
+}
+void
+MeshWifiInterfaceMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+ NS_LOG_FUNCTION (this << eifsNoDifs);
+ m_dcfManager->SetEifsNoDifs (eifsNoDifs);
+ m_eifsNoDifs = eifsNoDifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetSlot () const
+{
+ return m_slot;
+}
+
+Time
+MeshWifiInterfaceMac::GetSifs () const
+{
+ return m_sifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetEifsNoDifs () const
+{
+ return m_eifsNoDifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetAckTimeout () const
+{
+ return m_low->GetAckTimeout ();
+}
+
+Time
+MeshWifiInterfaceMac::GetCtsTimeout () const
+{
+ return m_low->GetCtsTimeout ();
+}
+
+Time
+MeshWifiInterfaceMac::GetPifs () const
+{
+ return m_low->GetPifs ();
+}
+
+void
+MeshWifiInterfaceMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+ NS_LOG_FUNCTION (this << phy);
+ m_phy = phy;
+ m_dcfManager->SetupPhyListener (phy);
+ m_low->SetPhy (phy);
+
+ NS_LOG_DEBUG("SetWifiPhy: Can switch channel now: " << CanSwitchChannel() ); // TMP
+}
+
+void
+MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+ NS_LOG_FUNCTION (this << stationManager);
+ m_stationManager = stationManager;
+ m_BE->SetWifiRemoteStationManager (stationManager);
+ m_VO->SetWifiRemoteStationManager (stationManager);
+ m_beaconDca->SetWifiRemoteStationManager (stationManager);
+ m_low->SetWifiRemoteStationManager (stationManager);
+}
+
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from)
+{
+ NS_LOG_FUNCTION (this << packet << to << from);
+ ForwardDown (packet, from, to);
+}
+
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+ NS_LOG_FUNCTION (this << packet << to);
+ ForwardDown (packet, m_low->GetAddress (), to);
+}
+
+bool
+MeshWifiInterfaceMac::SupportsSendFrom () const
+{
+ return true;
+}
+
+void
+MeshWifiInterfaceMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback)
+{
+ NS_LOG_FUNCTION (this);
+ m_upCallback = upCallback;
+}
+
+void
+MeshWifiInterfaceMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+ NS_LOG_FUNCTION (this);
+ if (!linkUp.IsNull ())
+ {
+ linkUp ();
+ }
+}
+
+void
+MeshWifiInterfaceMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+Mac48Address
+MeshWifiInterfaceMac::GetAddress () const
+{
+ return m_address;
+}
+Mac48Address
+MeshWifiInterfaceMac::GetBssid () const
+{
+ return m_address;
+}
+
+Ssid
+MeshWifiInterfaceMac::GetSsid () const
+{
+ return m_meshId;
+}
+
+void
+MeshWifiInterfaceMac::SetAddress (Mac48Address address)
+{
+ NS_LOG_FUNCTION (address);
+ m_low->SetAddress (address);
+ m_address = address;
+}
+
+void
+MeshWifiInterfaceMac::SetSsid (Ssid ssid)
+{
+ NS_LOG_FUNCTION (ssid);
+ m_meshId = ssid;
+}
+
+void
+MeshWifiInterfaceMac::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_rxMiddle;
+ delete m_dcfManager;
+ //Delete smart pointers:
+ m_rxMiddle = 0;
+ m_low = 0;
+ m_dcfManager = 0;
+ m_phy = 0;
+ m_BE = 0;
+ m_VO = 0;
+ m_beaconSendEvent.Cancel ();
+ m_beaconDca = 0;
+
+ WifiMac::DoDispose ();
+}
+
+//-----------------------------------------------------------------------------
+// Plugins
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::InstallPlugin ( Ptr<MeshWifiInterfaceMacPlugin> plugin)
+{
+ NS_LOG_FUNCTION (this);
+
+ plugin->SetParent (this);
+ m_plugins.push_back (plugin);
+}
+
+//-----------------------------------------------------------------------------
+// Switch channels
+//-----------------------------------------------------------------------------
+bool MeshWifiInterfaceMac::CanSwitchChannel () const
+{
+ NS_LOG_FUNCTION (this);
+
+ // now only YansWifiPhy can switch channels runtime
+ if (m_phy != 0)
+ {
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ return (phy != 0);
+ }
+ else
+ return false;
+}
+
+uint16_t MeshWifiInterfaceMac::GetFrequencyChannel () const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ if (phy != 0)
+ return phy->GetFrequencyChannel ();
+ else
+ return 0;
+}
+
+void MeshWifiInterfaceMac::SwitchFrequencyChannel (uint16_t new_id)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+ /* TODO
+ *
+ * Correct channel switching is:
+ *
+ * 1. Interface down, e.g. to stop packets from layer 3
+ * 2. Wait before all output queues will be empty
+ * 3. Switch PHY channel
+ * 4. Interface up
+ *
+ * Now we use dirty channel switch -- just change frequency
+ */
+ NS_ASSERT(CanSwitchChannel());
+
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ phy->SetFrequencyChannel (new_id);
+ // Don't know NAV on new channel
+ m_dcfManager->NotifyNavResetNow (Seconds (0));
+}
+
+//-----------------------------------------------------------------------------
+// Forward frame up/down
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst)
+{
+ NS_LOG_FUNCTION (this << packet << src);
+ m_upCallback (packet, src, dst);
+}
+
+void
+MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> const_packet, Mac48Address from, Mac48Address to)
+{
+ // copy packet to allow modifications
+ Ptr<Packet> packet = const_packet->Copy ();
+ WifiMacHeader hdr;
+ hdr.SetTypeData ();
+ hdr.SetAddr2 (GetAddress ());
+ hdr.SetAddr3 (to);
+ hdr.SetAddr4 (from);
+ hdr.SetDsFrom ();
+ hdr.SetDsTo ();
+
+ // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
+ hdr.SetAddr1 (Mac48Address ());
+
+ // Filter packet through all installed plugins
+ for (PluginList::const_iterator i = m_plugins.end()-1; i != m_plugins.begin()-1; i--)
+ {
+ bool drop = ! ((*i)->UpdateOutcomingFrame(packet, hdr, from, to));
+ if (drop) return; // plugin drops frame
+ }
+
+ // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
+ NS_ASSERT (hdr.GetAddr1() != Mac48Address() );
+
+ // Queue frame
+ WifiRemoteStation *destination = m_stationManager->Lookup (to);
+
+ if (destination->IsBrandNew ())
+ {
+ // in adhoc mode, we assume that every destination
+ // supports all the rates we support.
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ destination->AddSupportedMode (m_phy->GetMode (i));
+ }
+ destination->RecordDisassociated ();
+ }
+ m_stats.sentFrames ++;
+ m_stats.sentBytes += packet->GetSize ();
+ m_BE->Queue (packet, hdr);
+}
+
+void
+MeshWifiInterfaceMac::SendManagementFrame (Ptr<Packet> packet, const WifiMacHeader& hdr)
+{
+ //Filter management frames:
+ WifiMacHeader header = hdr;
+ for (PluginList::const_iterator i = m_plugins.end()-1; i != m_plugins.begin()-1; i--)
+ {
+ bool drop = ! ((*i)->UpdateOutcomingFrame(packet, header, Mac48Address (), Mac48Address ()));
+ if (drop) return; // plugin drops frame
+ }
+ m_stats.sentFrames ++;
+ m_stats.sentBytes += packet->GetSize ();
+ m_VO->Queue (packet, header);
+}
+
+SupportedRates
+MeshWifiInterfaceMac::GetSupportedRates () const
+{
+ // set the set of supported rates and make sure that we indicate
+ // the Basic Rate set in this set of supported rates.
+ SupportedRates rates;
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ rates.AddSupportedRate (mode.GetDataRate ());
+ }
+ // set the basic rates
+ for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (j);
+ rates.SetBasicRate (mode.GetDataRate ());
+ }
+ return rates;
+}
+bool
+MeshWifiInterfaceMac::CheckSupportedRates(SupportedRates rates) const
+{
+ for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (i);
+ if (!rates.IsSupportedRate (mode.GetDataRate ()))
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Beacons
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetRandomStartDelay (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_randomStart = interval;
+}
+
+void
+MeshWifiInterfaceMac::SetBeaconInterval (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_beaconInterval = interval;
+}
+
+Time
+MeshWifiInterfaceMac::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+
+void
+MeshWifiInterfaceMac::SetBeaconGeneration (bool enable)
+{
+ NS_LOG_FUNCTION (this << enable);
+ if (enable)
+ {
+ // Now start sending beacons after some random delay (to avoid collisions)
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
+ Time randomStart = Seconds (coefficient.GetValue());
+
+ m_beaconSendEvent = Simulator::Schedule (randomStart, &MeshWifiInterfaceMac::SendBeacon, this);
+ m_tbtt = Simulator::Now() + randomStart;
+ }
+ else
+ // stop sending beacons
+ m_beaconSendEvent.Cancel ();
+}
+
+bool
+MeshWifiInterfaceMac::GetBeaconGeneration () const
+{
+ return m_beaconSendEvent.IsRunning ();
+}
+
+Time
+MeshWifiInterfaceMac::GetTbtt () const
+{
+ return m_tbtt;
+}
+
+void MeshWifiInterfaceMac::ShiftTbtt (Time shift)
+{
+ // User of ShiftTbtt () must take care don't shift it to the past
+ NS_ASSERT (GetTbtt() + shift > Simulator::Now());
+
+ m_tbtt += shift;
+ // Shift scheduled event
+ Simulator::Cancel (m_beaconSendEvent);
+ m_beaconSendEvent = Simulator::Schedule (GetTbtt () - Simulator::Now(), &MeshWifiInterfaceMac::SendBeacon, this);
+}
+
+void
+MeshWifiInterfaceMac::ScheduleNextBeacon ()
+{
+ m_tbtt += GetBeaconInterval ();
+ m_beaconSendEvent = Simulator::Schedule (GetBeaconInterval(), &MeshWifiInterfaceMac::SendBeacon, this);
+}
+
+void
+MeshWifiInterfaceMac::SendBeacon ()
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG (GetAddress() <<" is sending beacon");
+
+ NS_ASSERT (! m_beaconSendEvent.IsRunning());
+ NS_ASSERT (Simulator::Now().GetMicroSeconds() == GetTbtt().GetMicroSeconds()); // assert that beacon is just on time
+
+ // Form & send beacon
+ MeshWifiBeacon beacon (GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ());
+
+ // Ask all plugins to add their specific information elements to beacon
+ for (PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
+ (*i)->UpdateBeacon (beacon);
+
+ m_beaconDca->Queue (beacon.CreatePacket(), beacon.CreateHeader(GetAddress (), GetMeshPointAddress ()));
+
+ ScheduleNextBeacon ();
+}
+
+void
+MeshWifiInterfaceMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+ // Process beacon
+ if((hdr->GetAddr1() != GetAddress()) && (hdr->GetAddr1() != Mac48Address::GetBroadcast()))
+ return;
+ if (hdr->IsBeacon ())
+ {
+ m_stats.recvBeacons ++;
+ MgtBeaconHeader beacon_hdr;
+ Mac48Address from = hdr->GetAddr2 ();
+
+ packet->PeekHeader (beacon_hdr);
+
+ NS_LOG_DEBUG ("Beacon received from "<<hdr->GetAddr2()<<
+ " I am "<<GetAddress ()<<
+ " at "<<Simulator::Now ().GetMicroSeconds ()<<
+ " microseconds");
+
+ // update supported rates
+ if (beacon_hdr.GetSsid ().IsEqual(GetSsid()))
+ {
+ SupportedRates rates = beacon_hdr.GetSupportedRates ();
+ WifiRemoteStation * peerSta = m_stationManager->Lookup (hdr->GetAddr2 ());
+
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ if (rates.IsSupportedRate (mode.GetDataRate ()))
+ {
+ peerSta->AddSupportedMode (mode);
+ if (rates.IsBasicRate (mode.GetDataRate ()))
+ m_stationManager->AddBasicMode (mode);
+ }
+ }
+ }
+ }
+ else
+ {
+ m_stats.recvBytes += packet->GetSize ();
+ m_stats.recvFrames ++;
+ }
+ // Filter frame through all installed plugins
+ for (PluginList::iterator i = m_plugins.begin (); i != m_plugins.end(); ++i)
+ {
+ bool drop = ! ((*i)->Receive(packet, *hdr));
+ if (drop) return; // plugin drops frame
+ }
+
+ // Forward data up
+ if (hdr->IsData ())
+ ForwardUp (packet, hdr->GetAddr4(), hdr->GetAddr3());
+}
+
+uint32_t
+MeshWifiInterfaceMac::GetLinkMetric (Mac48Address peerAddress)
+{
+ uint32_t metric = 1;
+ if(!m_linkMetricCallback.IsNull ())
+ metric = m_linkMetricCallback(peerAddress, this);
+ return metric;
+}
+
+void
+MeshWifiInterfaceMac::SetLinkMetricCallback (Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb)
+{
+ m_linkMetricCallback = cb;
+}
+
+Ptr<WifiRemoteStationManager>
+MeshWifiInterfaceMac::GetStationManager()
+{
+ return m_stationManager;
+}
+
+void
+MeshWifiInterfaceMac::SetMeshPointAddress (Mac48Address a)
+{
+ m_mpAddress = a;
+}
+
+Mac48Address
+MeshWifiInterfaceMac::GetMeshPointAddress () const
+{
+ return m_mpAddress;
+}
+//Statistics:
+void
+MeshWifiInterfaceMac::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "recvBeacons=\"" << recvBeacons << "\" "
+ "sentFrames=\"" << sentFrames << "\" "
+ "sentBytes=\"" << (double)sentBytes / 1024.0 << "K\" "
+ "recvFrames=\"" << recvFrames << "\" "
+ "recvBytes=\"" << (double)recvBytes / 1024.0 << "K\"/>\n";
+}
+void
+MeshWifiInterfaceMac::Report (std::ostream & os) const
+{
+ os << "<Interface "
+ "BeaconInterval=\"" << GetBeaconInterval ().GetSeconds() << "s\" "
+ "Channel=\"" << GetFrequencyChannel () << "\" "
+ "Address = \"" << GetAddress () << "\">\n";
+ m_stats.Print (os);
+ os << "</Interface>\n";
+}
+void
+MeshWifiInterfaceMac::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,257 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMAC_H_
+#define MESHWIFIINTERFACEMAC_H_
+
+#include <stdint.h>
+#include <map>
+#include "ns3/mac48-address.h"
+#include "ns3/mgt-headers.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/event-id.h"
+
+namespace ns3 {
+
+class WifiMacHeader;
+class DcaTxop;
+class WifiPhy;
+class DcfManager;
+class MacRxMiddle;
+class MacLow;
+/**
+ * \ingroup mesh
+ *
+ * \brief Basic MAC of mesh point Wi-Fi interface. Its function is extendable through plugins mechanism.
+ *
+ * Now only three output queues are used:
+ * - beacons (PIFS and no backoff),
+ * - background traffic,
+ * - management and priority traffic.
+ *
+ */
+class MeshWifiInterfaceMac : public WifiMac
+{
+public:
+ /// Never forget to support typeid
+ static TypeId GetTypeId ();
+ /// C-tor
+ MeshWifiInterfaceMac ();
+ /// D-tor
+ virtual ~MeshWifiInterfaceMac ();
+
+ ///\name Inherited from WifiMac
+ //\{
+ virtual void SetSlot (Time slotTime);
+ virtual void SetSifs (Time sifs);
+ virtual void SetPifs (Time pifs);
+ virtual void SetCtsTimeout (Time ctsTimeout);
+ virtual void SetAckTimeout (Time ackTimeout);
+ virtual void SetEifsNoDifs (Time eifsNoDifs);
+ virtual Time GetSlot () const;
+ virtual Time GetSifs () const;
+ virtual Time GetPifs () const;
+ virtual Time GetCtsTimeout () const;
+ virtual Time GetAckTimeout () const;
+ virtual Time GetEifsNoDifs () const;
+ virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+ virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+ virtual bool SupportsSendFrom () const;
+ virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback);
+ virtual void SetLinkUpCallback (Callback<void> linkUp);
+ virtual void SetLinkDownCallback (Callback<void> linkDown);
+ virtual Mac48Address GetAddress () const;
+ virtual Mac48Address GetBssid () const;
+ virtual Ssid GetSsid () const;
+ virtual void SetAddress (Mac48Address address);
+ virtual void SetSsid (Ssid ssid);
+ //\}
+
+ ///\name Each mesh point interfaces must know the mesh point address
+ //\{
+ void SetMeshPointAddress (Mac48Address);
+ Mac48Address GetMeshPointAddress () const;
+ //\}
+ ///\name Beacons
+ //\{
+ /// Set maximum initial random delay before first beacon
+ void SetRandomStartDelay (Time interval);
+ /// Set interval between two successive beacons
+ void SetBeaconInterval (Time interval);
+ /// \return interval between two beacons
+ Time GetBeaconInterval () const;
+ /**
+ * \brief Next beacon frame time
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ */
+ Time GetTbtt () const;
+ /**
+ * \brief Shift TBTT.
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ *
+ * \attention User of ShiftTbtt () must take care to not shift it to the past.
+ */
+ void ShiftTbtt (Time shift);
+ //\}
+
+ ///\name Plugins
+ //\{
+ /// Install plugin. TODO return unique ID to allow unregister plugins
+ void InstallPlugin (Ptr<MeshWifiInterfaceMacPlugin> plugin);
+ //\}
+
+ /** \name Channel switching
+ *
+ * Channel center frequency = Channel starting frequency + 5 * channel_id (MHz),
+ * where Starting channel frequency is standard-dependent as defined in IEEE 802.11-2007 17.3.8.3.2.
+ *
+ * Number of channels to use must be limited elsewhere.
+ */
+ //\{
+ /// Return true if PHY layer can switch channels
+ bool CanSwitchChannel () const;
+ /// Current channel Id
+ uint16_t GetFrequencyChannel () const;
+ /// Switch channel
+ void SwitchFrequencyChannel (uint16_t new_id);
+ //\}
+
+ /// To be used by plugins sending management frames.
+ void SendManagementFrame(Ptr<Packet> frame, const WifiMacHeader& hdr);
+ /// \return true if rates are supported
+ bool CheckSupportedRates(SupportedRates rates) const;
+ /// \return list of supported bitrates
+ SupportedRates GetSupportedRates () const;
+ ///\ name Metric Calculation routines:
+ ///\{
+ void SetLinkMetricCallback(Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb);
+ uint32_t GetLinkMetric(Mac48Address peerAddress);
+ Ptr<WifiRemoteStationManager> GetStationManager ();
+ ///\}
+ ///\brief Statistics:
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ /// Frame receive handler
+ void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+ /// Forward frame to mesh point
+ virtual void ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst);
+ /// Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point
+ void ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to);
+ /// Send beacon
+ void SendBeacon ();
+ /// Schedule next beacon
+ void ScheduleNextBeacon ();
+ /// Enable/disable beacons
+ void SetBeaconGeneration (bool enable);
+ /// Get current beaconing status
+ bool GetBeaconGeneration () const;
+ /// Real d-tor
+ virtual void DoDispose ();
+
+private:
+ ///\name Wifi MAC internals
+ //\{
+ Ptr<DcaTxop> m_BE;
+ Ptr<DcaTxop> m_BK;
+ Ptr<DcaTxop> m_VI;
+ Ptr<DcaTxop> m_VO;
+ Ptr<DcaTxop> m_beaconDca;
+ Ptr<WifiRemoteStationManager> m_stationManager;
+ Ptr<WifiPhy> m_phy;
+ Callback<void, Ptr<Packet>, Mac48Address, Mac48Address> m_upCallback;
+ //\}
+
+ ///\name Wifi timing intervals
+ //\{
+ Time m_slot;
+ Time m_sifs;
+ Time m_pifs;
+ Time m_ackTimeout;
+ Time m_ctsTimeout;
+ Time m_eifsNoDifs;
+ //\}
+
+ ///\name Mesh timing intervals
+ //\{
+ /// Beaconing interval.
+ Time m_beaconInterval;
+ /// Maximum delay before first beacon
+ Time m_randomStart;
+ /// Time for the next frame
+ Time m_tbtt;
+ //\}
+
+ /// DCF implementation
+ DcfManager* m_dcfManager;
+ /// Middle MAC sublayer
+ MacRxMiddle* m_rxMiddle;
+ /// Low MAC sublayer
+ Ptr<MacLow> m_low;
+ /// My address
+ Mac48Address m_address;
+ /// Mesh point address
+ Mac48Address m_mpAddress;
+ /// SSID
+ Ssid m_meshId;
+
+ /// "Timer" for the next beacon
+ EventId m_beaconSendEvent;
+
+ typedef std::vector< Ptr<MeshWifiInterfaceMacPlugin> > PluginList;
+ /// List of all installed plugins
+ PluginList m_plugins;
+ Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > m_linkMetricCallback;
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t recvBeacons;
+ uint32_t sentFrames;
+ uint32_t sentBytes;
+ uint32_t recvFrames;
+ uint32_t recvBytes;
+ void Print (std::ostream & os) const;
+ Statistics () :
+ recvBeacons (0),
+ sentFrames (0),
+ sentBytes (0),
+ recvFrames (0),
+ recvBytes (0)
+ {}
+ };
+ Statistics m_stats;
+ ///\}
+
+};
+
+} // namespace ns3
+
+#endif /* MESHWIFIINTERFACEMAC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is toplevel mesh module description
+ */
+
+/**
+ * \ingroup devices
+ * \defgroup mesh Mesh
+ *
+ * \brief Layer 2 mobile ad hoc wireless (aka mesh) networking
+ *
+ * see http://www.nsnam.org/wiki/index.php/Mesh for module architectural description.
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/waf Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element.cc Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/wifi-information-element.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+
+namespace ns3 {
+
+TypeId
+WifiInformationElement::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiInformationElement")
+ .SetParent<Header> ();
+ return tid;
+}
+
+TypeId
+WifiInformationElement::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint32_t WifiInformationElement::GetSerializedSize () const
+{
+ return (GetInformationSize () + 2);
+}
+
+void WifiInformationElement::Serialize (Buffer::Iterator i) const
+{
+ i.WriteU8 (ElementId ());
+ i.WriteU8 (GetInformationSize ());
+ SerializeInformation (i);
+}
+
+uint32_t WifiInformationElement::Deserialize (Buffer::Iterator i)
+{
+ if(i.ReadU8 () != ElementId())
+ return 0;
+ uint8_t length = i.ReadU8 ();
+
+ return (DeserializeInformation (i, length) + 2);
+}
+
+void WifiInformationElement::Print (std::ostream &os) const
+{
+ os << "\n<information_element id=" << ElementId () << ">\n";
+ PrintInformation (os);
+ os << "</information_element>\n";
+}
+
+bool WifiInformationElement::FindFirst(Ptr<Packet> packet)
+{
+ const uint8_t * data = packet->PeekData();
+ uint32_t position = 0;
+ while(position < packet->GetSize ())
+ {
+ if(data[position] == ElementId())
+ {
+ Ptr<Packet> myIe = packet->CreateFragment(position, data[position+1]+2);
+ NS_ASSERT(myIe->GetSize() == (uint32_t)(data[position+1]+2));
+ myIe->RemoveHeader(*this);
+ return true;
+ }
+ else
+ {
+ if(data[position] > ElementId())
+ return false;
+ position +=data[position+1]+2;
+ }
+ }
+ return false;
+}
+
+bool operator< (WifiInformationElement const & a, WifiInformationElement const & b)
+{
+ return (a.ElementId () < b.ElementId());
+}
+
+
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element.h Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,201 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef WIFIINFORMATIONELEMENT_H_
+#define WIFIINFORMATIONELEMENT_H_
+
+#include "ns3/header.h"
+#include "ns3/ref-count-base.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+class Packet;
+/**
+ * \ingroup mesh
+ *
+ * \brief Enum of all known information element id (aka tags).
+ *
+ * For now only 802.11s (mesh) related elements are supported here (so 11S prefix),
+ * but this can change in future.
+ *
+ * Note that 802.11s element ids are not yet officially assigned, we use ones
+ * compatible with open80211s (http://o11s.org/) implementation.
+ */
+enum WifiElementId {
+ /* begin of open80211s-compatible IDs */
+ IE11S_MESH_CONFIGURATION = 51,
+ IE11S_MESH_ID = 52,
+ /* end of open80211s-compatible IDs */
+ IE11S_LINK_METRIC_REPORT = 20,
+ IE11S_CONGESTION_NOTIFICATION,
+ /* begin of open80211s-compatible IDs */
+ IE11S_PEERING_MANAGEMENT = 55,
+ /* end of open80211s-compatible IDs */
+ IE11S_SUPP_MBSS_REG_CLASSES_CHANNELS = 23,
+ IE11S_MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+ IE11S_MESH_TIM,
+ IE11S_AWAKE_WINDOW,
+ IE11S_BEACON_TIMING,
+ IE11S_MCCAOP_SETUP_REQUEST,
+ IE11S_MCCAOP_SETUP_REPLY,
+ IE11S_MCCAOP_ADVERTISEMENT,
+ IE11S_MCCAOP_RESERVATION_TEARDOWN,
+ IE11S_PORTAL_ANNOUNCEMENT,
+ IE11S_RANN = 67,
+ /* begin of open80211s-compatible IDs */
+ IE11S_PREQ = 68,
+ IE11S_PREP = 69,
+ IE11S_PERR = 70,
+ /* end of open80211s-compatible IDs */
+ IE11S_PROXY_UPDATE = 37,
+ IE11S_PROXY_UPDATE_CONFIRMATION,
+ IE11S_ABBREVIATED_HANDSHAKE,
+ IE11S_MESH_PEERING_PROTOCOL_VERSION = 74,
+};
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Information element, as defined in 802.11-2007 standard
+ *
+ * Elements are defined to have a common general format consisting of a 1 octet Element ID field, a 1 octet
+ * length field, and a variable-length element-specific information field. Each element is assigned a unique
+ * Element ID as defined in this standard. The Length field specifies the number of octets in the Information
+ * field.
+ */
+class WifiInformationElement : public Header,
+ public RefCountBase // need this to use Ptr<WifiInformationElement>
+{
+public:
+ /// Support object system
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+
+ /// virtual d-tor for subclasses
+ virtual ~WifiInformationElement () {}
+
+ ///\name Inherited from Header
+ //\{
+ /**
+ * \return the expected size of the header.
+ *
+ * This method is used by Packet::AddHeader
+ * to store a header into the byte buffer of a packet. This method
+ * should return the number of bytes which are needed to store
+ * the full header data by Serialize.
+ */
+ virtual uint32_t GetSerializedSize () const;
+ /**
+ * \param start an iterator which points to where the header should
+ * be written.
+ *
+ * This method is used by Packet::AddHeader to
+ * store a header into the byte buffer of a packet.
+ * The data written
+ * is expected to match bit-for-bit the representation of this
+ * header in a real network.
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+ /**
+ * \param start an iterator which points to where the header should
+ * written.
+ * \return the number of bytes read.
+ *
+ * This method is used by Packet::RemoveHeader to
+ * re-create a header from the byte buffer of a packet.
+ * The data read is expected to
+ * match bit-for-bit the representation of this header in real
+ * networks.
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ /**
+ * This method is used by Packet::Print to print the
+ * content of a trailer as ascii data to a c++ output stream.
+ * Although the trailer is free to format its output as it
+ * wishes, it is recommended to follow a few rules to integrate
+ * with the packet pretty printer: start with flags, small field
+ * values located between a pair of parens. Values should be separated
+ * by whitespace. Follow the parens with the important fields,
+ * separated by whitespace.
+ * i.e.: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
+ */
+ virtual void Print (std::ostream &os) const;
+ /**
+ * This method takes a packet which must be a list of information
+ * elements and looks for an information element of MINE Element ID
+ */
+ bool FindFirst(Ptr<Packet> packet);
+ //\}
+
+protected:
+ ///\name Each subclass must implement
+ //\{
+ /// Own unique Element ID
+ virtual WifiElementId ElementId () const = 0;
+ /// Length of serialized information
+ virtual uint8_t GetInformationSize () const = 0;
+ /// Serialize information
+ virtual void SerializeInformation (Buffer::Iterator start) const = 0;
+ /// Deserialize information
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length) = 0;
+ /// Print information
+ virtual void PrintInformation (std::ostream &os) const = 0;
+ //\}
+
+ /// Compare information elements using Element ID
+ friend bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+};
+
+/// Compare information elements using Element ID
+bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+
+#ifdef RUN_SELF_TESTS
+/// Generic test of information element
+class IeTest : public Test
+{
+public:
+ IeTest (const char * name) : Test (name) {}
+ /// Test roundtrip serialization
+ template <typename IE> bool TestRoundtripSerialization (IE a);
+};
+
+template <typename IE> bool
+IeTest::TestRoundtripSerialization (IE a)
+{
+ bool result (true);
+
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IE b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ packet->AddHeader (a);
+ IE c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+
+ return result;
+}
+#endif
+
+} // namespace ns3
+#endif /* WIFIINFORMATIONELEMENT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wscript Fri May 29 10:15:19 2009 +0400
@@ -0,0 +1,21 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('mesh', ['wifi', 'dot11s'])
+ obj.source = [
+ 'wifi-information-element.cc',
+ 'mesh-point-device.cc',
+ 'mesh-l2-routing-protocol.cc',
+ 'mesh-wifi-beacon.cc',
+ 'mesh-wifi-interface-mac.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'mesh'
+ headers.source = [
+ 'wifi-information-element.h',
+ 'mesh-point-device.h',
+ 'mesh-l2-routing-protocol.h',
+ 'mesh-wifi-beacon.h',
+ 'mesh-wifi-interface-mac.h',
+ 'mesh-wifi-interface-mac-plugin.h',
+ ]
--- a/src/devices/wifi/dca-txop.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/dca-txop.h Fri May 29 10:15:19 2009 +0400
@@ -164,6 +164,7 @@
bool m_accessOngoing;
Ptr<const Packet> m_currentPacket;
WifiMacHeader m_currentHdr;
+ uint8_t m_currentRetry;
uint8_t m_fragmentNumber;
};
--- a/src/devices/wifi/dcf-manager.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/dcf-manager.cc Fri May 29 10:15:19 2009 +0400
@@ -160,17 +160,29 @@
* Listener for Nav events. Forwards to DcfManager
***************************************************************/
-class LowNavListener : public ns3::MacLowNavListener {
+class LowDcfListener : public ns3::MacLowDcfListener {
public:
- LowNavListener (ns3::DcfManager *dcf)
+ LowDcfListener (ns3::DcfManager *dcf)
: m_dcf (dcf) {}
- virtual ~LowNavListener () {}
+ virtual ~LowDcfListener () {}
virtual void NavStart (Time duration) {
m_dcf->NotifyNavStartNow (duration);
}
virtual void NavReset (Time duration) {
m_dcf->NotifyNavResetNow (duration);
}
+ virtual void AckTimeoutStart (Time duration) {
+ m_dcf->NotifyAckTimeoutStartNow (duration);
+ }
+ virtual void AckTimeoutReset () {
+ m_dcf->NotifyAckTimeoutResetNow ();
+ }
+ virtual void CtsTimeoutStart (Time duration) {
+ m_dcf->NotifyCtsTimeoutStartNow (duration);
+ }
+ virtual void CtsTimeoutReset () {
+ m_dcf->NotifyCtsTimeoutResetNow ();
+ }
private:
ns3::DcfManager *m_dcf;
};
@@ -208,7 +220,9 @@
****************************************************************/
DcfManager::DcfManager ()
- : m_lastNavStart (MicroSeconds (0)),
+ : m_lastAckTimeoutEnd (MicroSeconds (0)),
+ m_lastCtsTimeoutEnd (MicroSeconds (0)),
+ m_lastNavStart (MicroSeconds (0)),
m_lastNavDuration (MicroSeconds (0)),
m_lastRxStart (MicroSeconds (0)),
m_lastRxDuration (MicroSeconds (0)),
@@ -242,8 +256,8 @@
void
DcfManager::SetupLowListener (Ptr<MacLow> low)
{
- m_lowListener = new LowNavListener (this);
- low->RegisterNavListener (m_lowListener);
+ m_lowListener = new LowDcfListener (this);
+ low->RegisterDcfListener (m_lowListener);
}
void
@@ -294,6 +308,16 @@
Time retval = Max (e, f);
return retval;
}
+Time
+DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f) const
+{
+ Time g = Max (a, b);
+ Time h = Max (c, d);
+ Time i = Max (e, f);
+ Time k = Max (g, h);
+ Time retval = Max (k, i);
+ return retval;
+}
bool
DcfManager::IsBusy (void) const
@@ -351,7 +375,7 @@
{
DcfState *state = *i;
if (state->IsAccessRequested () &&
- GetBackoffEndFor (state) <= Simulator::Now ())
+ GetBackoffEndFor (state).GetTimeStep() <= Simulator::Now ().GetTimeStep ())
{
/**
* This is the first dcf we find with an expired backoff and which
@@ -431,7 +455,10 @@
Time accessGrantedStart = MostRecent (rxAccessStart,
busyAccessStart,
txAccessStart,
- navAccessStart);
+ navAccessStart,
+ m_lastAckTimeoutEnd,
+ m_lastCtsTimeoutEnd
+ );
NS_LOG_INFO ("access grant start=" << accessGrantedStart <<
", rx access start=" << rxAccessStart <<
", busy access start=" << busyAccessStart <<
@@ -491,8 +518,9 @@
if (state->IsAccessRequested ())
{
Time tmp = GetBackoffEndFor (state);
- if (tmp > Simulator::Now ())
+ if (tmp.GetTimeStep () > Simulator::Now ().GetTimeStep ())
{
+ //NS_LOG_UNCOND("Now:"<<Simulator::Now ().GetTimeStep ());
accessTimeoutNeeded = true;
expectedBackoffEnd = std::min (expectedBackoffEnd, tmp);
}
@@ -586,5 +614,26 @@
m_lastNavDuration = duration;
}
}
-
+void
+DcfManager::NotifyAckTimeoutStartNow (Time duration)
+{
+ m_lastAckTimeoutEnd = Simulator::Now () + duration;
+}
+void
+DcfManager::NotifyAckTimeoutResetNow ()
+{
+ m_lastAckTimeoutEnd = Simulator::Now ();
+ DoRestartAccessTimeoutIfNeeded ();
+}
+void
+DcfManager::NotifyCtsTimeoutStartNow (Time duration)
+{
+ m_lastCtsTimeoutEnd = Simulator::Now () + duration;
+}
+void
+DcfManager::NotifyCtsTimeoutResetNow ()
+{
+ m_lastCtsTimeoutEnd = Simulator::Now ();
+ DoRestartAccessTimeoutIfNeeded ();
+}
} // namespace ns3
--- a/src/devices/wifi/dcf-manager.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/dcf-manager.h Fri May 29 10:15:19 2009 +0400
@@ -238,12 +238,17 @@
* Called at end of rx
*/
void NotifyNavStartNow (Time duration);
-
+ void NotifyAckTimeoutStartNow (Time duration);
+ void NotifyAckTimeoutResetNow ();
+ void NotifyCtsTimeoutStartNow (Time duration);
+ void NotifyCtsTimeoutResetNow ();
+ void NotifyAckTimeoutEnd (Time duration);
private:
void UpdateBackoff (void);
Time MostRecent (Time a, Time b) const;
Time MostRecent (Time a, Time b, Time c) const;
Time MostRecent (Time a, Time b, Time c, Time d) const;
+ Time MostRecent (Time a, Time b, Time c, Time d, Time e, Time f) const;
/**
* Access will never be granted to the medium _before_
* the time returned by this method.
@@ -262,6 +267,8 @@
typedef std::vector<DcfState *> States;
States m_states;
+ Time m_lastAckTimeoutEnd;
+ Time m_lastCtsTimeoutEnd;
Time m_lastNavStart;
Time m_lastNavDuration;
Time m_lastRxStart;
@@ -279,7 +286,7 @@
Time m_slotTime;
Time m_sifs;
class PhyListener *m_phyListener;
- class LowNavListener *m_lowListener;
+ class LowDcfListener *m_lowListener;
};
} // namespace ns3
--- a/src/devices/wifi/mac-low.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/mac-low.cc Fri May 29 10:15:19 2009 +0400
@@ -110,9 +110,9 @@
{}
MacLowTransmissionListener::~MacLowTransmissionListener ()
{}
-MacLowNavListener::MacLowNavListener ()
+MacLowDcfListener::MacLowDcfListener ()
{}
-MacLowNavListener::~MacLowNavListener ()
+MacLowDcfListener::~MacLowDcfListener ()
{}
MacLowTransmissionParameters::MacLowTransmissionParameters ()
@@ -271,6 +271,7 @@
MacLow::DoDispose (void)
{
NS_LOG_FUNCTION (this);
+ m_listener = 0;
CancelAllEvents ();
m_phy = 0;
m_stationManager = 0;
@@ -423,9 +424,9 @@
m_rxCallback = callback;
}
void
-MacLow::RegisterNavListener (MacLowNavListener *listener)
+MacLow::RegisterDcfListener (MacLowDcfListener *listener)
{
- m_navListeners.push_back (listener);
+ m_dcfListeners.push_back (listener);
}
@@ -537,12 +538,13 @@
{
NS_LOG_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
SnrTag tag;
- packet->FindFirstMatchingTag (tag);
+ packet->RemovePacketTag (tag);
WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
station->ReportRxOk (rxSnr, txMode);
station->ReportRtsOk (rxSnr, txMode, tag.Get ());
m_ctsTimeoutEvent.Cancel ();
+ NotifyCtsTimeoutResetNow ();
m_listener->GotCts (rxSnr, txMode);
NS_ASSERT (m_sendDataEvent.IsExpired ());
m_sendDataEvent = Simulator::Schedule (GetSifs (),
@@ -560,7 +562,7 @@
{
NS_LOG_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
SnrTag tag;
- packet->FindFirstMatchingTag (tag);
+ packet->RemovePacketTag (tag);
WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
station->ReportRxOk (rxSnr, txMode);
station->ReportDataOk (rxSnr, txMode, tag.Get ());
@@ -569,12 +571,14 @@
m_normalAckTimeoutEvent.IsRunning ())
{
m_normalAckTimeoutEvent.Cancel ();
+ NotifyAckTimeoutResetNow ();
gotAck = true;
}
if (m_txParams.MustWaitFastAck () &&
m_fastAckTimeoutEvent.IsRunning ())
{
m_fastAckTimeoutEvent.Cancel ();
+ NotifyAckTimeoutResetNow ();
gotAck = true;
}
if (gotAck)
@@ -796,7 +800,7 @@
void
MacLow::DoNavResetNow (Time duration)
{
- for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
{
(*i)->NavReset (duration);
}
@@ -806,7 +810,7 @@
bool
MacLow::DoNavStartNow (Time duration)
{
- for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
{
(*i)->NavStart (duration);
}
@@ -820,6 +824,38 @@
}
return false;
}
+void
+MacLow::NotifyAckTimeoutStartNow (Time duration)
+{
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
+ {
+ (*i)->AckTimeoutStart (duration);
+ }
+}
+void
+MacLow::NotifyAckTimeoutResetNow ()
+{
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
+ {
+ (*i)->AckTimeoutReset ();
+ }
+}
+void
+MacLow::NotifyCtsTimeoutStartNow (Time duration)
+{
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
+ {
+ (*i)->CtsTimeoutStart (duration);
+ }
+}
+void
+MacLow::NotifyCtsTimeoutResetNow ()
+{
+ for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++)
+ {
+ (*i)->CtsTimeoutReset ();
+ }
+}
void
MacLow::ForwardDown (Ptr<const Packet> packet, WifiMacHeader const* hdr,
@@ -945,6 +981,7 @@
Time timerDelay = txDuration + GetCtsTimeout ();
NS_ASSERT (m_ctsTimeoutEvent.IsExpired ());
+ NotifyCtsTimeoutStartNow (timerDelay);
m_ctsTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::CtsTimeout, this);
Ptr<Packet> packet = Create<Packet> ();
@@ -964,18 +1001,21 @@
{
Time timerDelay = txDuration + GetAckTimeout ();
NS_ASSERT (m_normalAckTimeoutEvent.IsExpired ());
+ NotifyAckTimeoutStartNow (timerDelay);
m_normalAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::NormalAckTimeout, this);
}
else if (m_txParams.MustWaitFastAck ())
{
Time timerDelay = txDuration + GetPifs ();
NS_ASSERT (m_fastAckTimeoutEvent.IsExpired ());
+ NotifyAckTimeoutStartNow (timerDelay);
m_fastAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::FastAckTimeout, this);
}
else if (m_txParams.MustWaitSuperFastAck ())
{
Time timerDelay = txDuration + GetPifs ();
NS_ASSERT (m_superFastAckTimeoutEvent.IsExpired ());
+ NotifyAckTimeoutStartNow (timerDelay);
m_superFastAckTimeoutEvent = Simulator::Schedule (timerDelay,
&MacLow::SuperFastAckTimeout, this);
}
@@ -1080,7 +1120,7 @@
struct SnrTag tag;
tag.Set (rtsSnr);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
ForwardDown (packet, &cts, ctsTxMode);
}
@@ -1159,7 +1199,7 @@
struct SnrTag tag;
tag.Set (dataSnr);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
ForwardDown (packet, &ack, ackTxMode);
}
--- a/src/devices/wifi/mac-low.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/mac-low.h Fri May 29 10:15:19 2009 +0400
@@ -100,10 +100,10 @@
* and calls to its methods are forwards to the corresponding
* ns3::Dcf methods.
*/
-class MacLowNavListener {
+class MacLowDcfListener {
public:
- MacLowNavListener ();
- virtual ~MacLowNavListener ();
+ MacLowDcfListener ();
+ virtual ~MacLowDcfListener ();
/**
* \param duration duration of NAV timer
*/
@@ -112,6 +112,10 @@
* \param duration duration of NAV timer
*/
virtual void NavReset (Time duration) = 0;
+ virtual void AckTimeoutStart (Time duration) = 0;
+ virtual void AckTimeoutReset () = 0;
+ virtual void CtsTimeoutStart (Time duration) = 0;
+ virtual void CtsTimeoutReset () = 0;
};
/**
@@ -306,7 +310,7 @@
* \param listener listen to NAV events for every incoming
* and outgoing packet.
*/
- void RegisterNavListener (MacLowNavListener *listener);
+ void RegisterDcfListener (MacLowDcfListener *listener);
/**
* \param packet to send (does not include the 802.11 MAC header and checksum)
@@ -375,6 +379,10 @@
void DoNavResetNow (Time duration);
bool DoNavStartNow (Time duration);
bool IsNavZero (void) const;
+ void NotifyAckTimeoutStartNow (Time duration);
+ void NotifyAckTimeoutResetNow ();
+ void NotifyCtsTimeoutStartNow (Time duration);
+ void NotifyCtsTimeoutResetNow ();
void MaybeCancelPrevious (void);
void NavCounterResetCtsMissed (Time rtsEndRxTime);
@@ -397,9 +405,9 @@
Ptr<WifiPhy> m_phy;
Ptr<WifiRemoteStationManager> m_stationManager;
MacLowRxCallback m_rxCallback;
- typedef std::vector<MacLowNavListener *>::const_iterator NavListenersCI;
- typedef std::vector<MacLowNavListener *> NavListeners;
- NavListeners m_navListeners;
+ typedef std::vector<MacLowDcfListener *>::const_iterator DcfListenersCI;
+ typedef std::vector<MacLowDcfListener *> DcfListeners;
+ DcfListeners m_dcfListeners;
EventId m_normalAckTimeoutEvent;
EventId m_fastAckTimeoutEvent;
--- a/src/devices/wifi/mgt-headers.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/mgt-headers.cc Fri May 29 10:15:19 2009 +0400
@@ -109,6 +109,11 @@
MgtProbeResponseHeader::~MgtProbeResponseHeader ()
{}
+uint64_t
+MgtProbeResponseHeader::GetTimestamp()
+{
+ return m_timestamp;
+}
Ssid
MgtProbeResponseHeader::GetSsid (void) const
{
@@ -198,7 +203,7 @@
MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
- i.Next (8); // timestamp
+ m_timestamp = i.ReadNtohU64();
m_beaconInterval = i.ReadNtohU16 ();
m_beaconInterval *= 1024;
i = m_capability.Deserialize (i);
--- a/src/devices/wifi/mgt-headers.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/mgt-headers.h Fri May 29 10:15:19 2009 +0400
@@ -21,6 +21,7 @@
#define MGT_HEADERS_H
#include <stdint.h>
+//#include <vector>
#include "ns3/header.h"
#include "status-code.h"
@@ -117,6 +118,8 @@
void SetBeaconIntervalUs (uint64_t us);
void SetSupportedRates (SupportedRates rates);
+ uint64_t GetTimestamp();
+
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
virtual void Print (std::ostream &os) const;
@@ -125,6 +128,7 @@
virtual uint32_t Deserialize (Buffer::Iterator start);
private:
+ uint64_t m_timestamp;
Ssid m_ssid;
uint64_t m_beaconInterval;
SupportedRates m_rates;
--- a/src/devices/wifi/qos-utils.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/qos-utils.cc Fri May 29 10:15:19 2009 +0400
@@ -59,7 +59,7 @@
{
QosTag qos;
uint8_t tid = 8;
- if (packet->FindFirstMatchingTag (qos))
+ if (packet->PeekPacketTag (qos))
{
if (qos.Get () < 8)
{
--- a/src/devices/wifi/wifi-mac-header.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wifi-mac-header.cc Fri May 29 10:15:19 2009 +0400
@@ -128,6 +128,21 @@
m_ctrlType = TYPE_DATA;
m_ctrlSubtype = 0;
}
+
+void
+WifiMacHeader::SetAction (void)
+{
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 0x0D;
+}
+
+void
+WifiMacHeader::SetMultihopAction (void)
+{
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 0x0F;
+}
+
void
WifiMacHeader::SetType (enum WifiMacType type)
{
@@ -191,6 +206,15 @@
case WIFI_MAC_MGT_DEAUTHENTICATION:
m_ctrlType = TYPE_MGT;
m_ctrlSubtype = 12;
+ case WIFI_MAC_MGT_ACTION:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 13;
+ case WIFI_MAC_MGT_ACTION_NO_ACK:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 14;
+ case WIFI_MAC_MGT_MULTIHOP_ACTION:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 15;
break;
case WIFI_MAC_DATA:
@@ -397,6 +421,15 @@
case 12:
return WIFI_MAC_MGT_DEAUTHENTICATION;
break;
+ case 13:
+ return WIFI_MAC_MGT_ACTION;
+ break;
+ case 14:
+ return WIFI_MAC_MGT_ACTION_NO_ACK;
+ break;
+ case 15:
+ return WIFI_MAC_MGT_MULTIHOP_ACTION;
+ break;
}
break;
@@ -590,6 +623,16 @@
{
return (GetType () == WIFI_MAC_MGT_DEAUTHENTICATION)?true:false;
}
+bool
+WifiMacHeader::IsAction (void) const
+{
+ return (GetType () == WIFI_MAC_MGT_ACTION)?true:false;
+}
+bool
+WifiMacHeader::IsMultihopAction (void) const
+{
+ return (GetType () == WIFI_MAC_MGT_MULTIHOP_ACTION)?true:false;
+}
uint16_t
@@ -810,6 +853,9 @@
FOO (MGT_PROBE_RESPONSE);
FOO (MGT_AUTHENTICATION);
FOO (MGT_DEAUTHENTICATION);
+ FOO (MGT_ACTION);
+ FOO (MGT_ACTION_NO_ACK);
+ FOO (MGT_MULTIHOP_ACTION);
FOO (DATA);
FOO (DATA_CFACK);
@@ -895,6 +941,12 @@
<< ", BSSID=" << m_addr3 << ", FragNumber=" << m_seqFrag
<< ", SeqNumber=" << m_seqSeq;
break;
+ case WIFI_MAC_MGT_ACTION:
+ // TODO
+ case WIFI_MAC_MGT_ACTION_NO_ACK:
+ // TODO
+ case WIFI_MAC_MGT_MULTIHOP_ACTION:
+ // TODO
case WIFI_MAC_DATA:
PrintFrameControl (os);
os << " Duration/ID=" << m_duration << "us";
--- a/src/devices/wifi/wifi-mac-header.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wifi-mac-header.h Fri May 29 10:15:19 2009 +0400
@@ -46,6 +46,9 @@
WIFI_MAC_MGT_PROBE_RESPONSE,
WIFI_MAC_MGT_AUTHENTICATION,
WIFI_MAC_MGT_DEAUTHENTICATION,
+ WIFI_MAC_MGT_ACTION,
+ WIFI_MAC_MGT_ACTION_NO_ACK,
+ WIFI_MAC_MGT_MULTIHOP_ACTION,
WIFI_MAC_DATA,
WIFI_MAC_DATA_CFACK,
@@ -98,6 +101,8 @@
void SetProbeResp (void);
void SetBeacon (void);
void SetTypeData (void);
+ void SetAction ();
+ void SetMultihopAction();
void SetDsFrom (void);
void SetDsNotFrom (void);
void SetDsTo (void);
@@ -150,6 +155,8 @@
bool IsDisassociation (void) const;
bool IsAuthentication (void) const;
bool IsDeauthentication (void) const;
+ bool IsAction () const;
+ bool IsMultihopAction () const;
uint16_t GetRawDuration (void) const;
Time GetDuration (void) const;
uint16_t GetSequenceControl (void) const;
--- a/src/devices/wifi/wifi-phy-test.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wifi-phy-test.cc Fri May 29 10:15:19 2009 +0400
@@ -167,7 +167,7 @@
CollisionExperiment::SendA (void) const
{
Ptr<Packet> p = Create<Packet> (m_input.packetSizeA);
- p->AddTag (FlowIdTag (m_flowIdA));
+ p->AddByteTag (FlowIdTag (m_flowIdA));
m_txA->SendPacket (p, WifiMode (m_input.txModeA),
WIFI_PREAMBLE_SHORT, m_input.txPowerLevelA);
}
@@ -176,7 +176,7 @@
CollisionExperiment::SendB (void) const
{
Ptr<Packet> p = Create<Packet> (m_input.packetSizeB);
- p->AddTag (FlowIdTag (m_flowIdB));
+ p->AddByteTag (FlowIdTag (m_flowIdB));
m_txB->SendPacket (p, WifiMode (m_input.txModeB),
WIFI_PREAMBLE_SHORT, m_input.txPowerLevelB);
}
@@ -185,7 +185,7 @@
CollisionExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
{
FlowIdTag tag;
- p->FindFirstMatchingTag (tag);
+ p->FindFirstMatchingByteTag (tag);
if (tag.GetFlowId () == m_flowIdA)
{
m_output.receivedA++;
--- a/src/devices/wifi/wifi-remote-station-manager.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wifi-remote-station-manager.cc Fri May 29 10:15:19 2009 +0400
@@ -433,7 +433,9 @@
WifiRemoteStation::WifiRemoteStation ()
: m_state (BRAND_NEW),
m_ssrc (0),
- m_slrc (0)
+ m_slrc (0),
+ m_avgSlrcCoefficient(0.9),
+ m_avgSlrc (0.0)
{}
WifiRemoteStation::~WifiRemoteStation ()
{}
@@ -557,7 +559,11 @@
{
return GetControlAnswerMode (dataMode);
}
-
+double
+WifiRemoteStation::GetAvgSlrc ()
+{
+ return m_avgSlrc;
+}
uint32_t
WifiRemoteStation::GetNSupportedModes (void) const
{
@@ -577,7 +583,7 @@
return;
}
TxModeTag tag = TxModeTag (DoGetRtsMode (), DoGetDataMode (fullPacketSize));
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
}
WifiMode
WifiRemoteStation::GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize)
@@ -588,7 +594,7 @@
}
TxModeTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
NS_ASSERT (found);
return tag.GetDataMode ();
}
@@ -601,7 +607,7 @@
}
TxModeTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
NS_ASSERT (found);
return tag.GetRtsMode ();
}
@@ -712,6 +718,7 @@
void
WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
{
+ m_avgSlrc = m_avgSlrc * m_avgSlrcCoefficient + (double) m_slrc * (1 - m_avgSlrcCoefficient);
m_slrc = 0;
DoReportDataOk (ackSnr, ackMode, dataSnr);
}
--- a/src/devices/wifi/wifi-remote-station-manager.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wifi-remote-station-manager.h Fri May 29 10:15:19 2009 +0400
@@ -260,7 +260,7 @@
* handshake.
*/
WifiMode GetAckMode (WifiMode dataMode);
-
+ double GetAvgSlrc ();
private:
virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
virtual WifiMode DoGetDataMode (uint32_t size) = 0;
@@ -289,6 +289,13 @@
SupportedModes m_modes;
TracedValue<uint32_t> m_ssrc;
TracedValue<uint32_t> m_slrc;
+ ///\name needed to calculate average SLRC
+ ///\{
+ ///\brief the coefficient: we valculate averages slrc as
+ //m_avgSlrc = m_avgSlr*coefficient + m_slrc*(1-coefficient);
+ double m_avgSlrcCoefficient;
+ double m_avgSlrc;
+ ///\}
};
} // namespace ns3
--- a/src/devices/wifi/wscript Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/wscript Fri May 29 10:15:19 2009 +0400
@@ -105,6 +105,13 @@
'msdu-aggregator.h',
'amsdu-subframe-header.h',
'qos-tag.h',
+# Need this for module devices/mesh
+ 'mgt-headers.h',
+ 'status-code.h',
+ 'capability-information.h',
+ 'dcf-manager.h',
+ 'mac-rx-middle.h',
+ 'mac-low.h',
]
if bld.env['ENABLE_GSL']:
--- a/src/devices/wifi/yans-wifi-channel.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/yans-wifi-channel.cc Fri May 29 10:15:19 2009 +0400
@@ -74,13 +74,25 @@
YansWifiChannel::Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
WifiMode wifiMode, WifiPreamble preamble) const
{
+ NS_LOG_DEBUG ("I am on channel " << sender->GetFrequencyChannel()
+ << " : sending " << packet->GetUid ());
+
Ptr<MobilityModel> senderMobility = sender->GetMobility ()->GetObject<MobilityModel> ();
NS_ASSERT (senderMobility != 0);
uint32_t j = 0;
- for (PhyList::const_iterator i = m_phyList.begin (); i != m_phyList.end (); i++)
- {
+ for (PhyList::const_iterator i = m_phyList.begin (); i != m_phyList.end (); i++, j++)
+ {
if (sender != (*i))
{
+ // For now don't account for interchannel interference
+ if ((*i)->GetFrequencyChannel() != sender->GetFrequencyChannel())
+ {
+ NS_LOG_DEBUG ("Dropped: " << (*i)->GetFrequencyChannel()
+ << " != " << sender->GetFrequencyChannel() );
+ continue;
+ }
+ NS_LOG_DEBUG ("Passed to receiver");
+
Ptr<MobilityModel> receiverMobility = (*i)->GetMobility ()->GetObject<MobilityModel> ();
Time delay = m_delay->GetDelay (senderMobility, receiverMobility);
double rxPowerDbm = m_loss->CalcRxPower (txPowerDbm, senderMobility, receiverMobility);
@@ -90,7 +102,6 @@
Simulator::Schedule (delay, &YansWifiChannel::Receive, this,
j, copy, rxPowerDbm, wifiMode, preamble);
}
- j++;
}
}
--- a/src/devices/wifi/yans-wifi-phy.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/yans-wifi-phy.cc Fri May 29 10:15:19 2009 +0400
@@ -116,13 +116,21 @@
PointerValue (),
MakePointerAccessor (&YansWifiPhy::m_state),
MakePointerChecker<WifiPhyStateHelper> ())
+ .AddAttribute ("ChannelSwitchDelay",
+ "Delay between two short frames transmitted on different frequencies",
+ TimeValue (MicroSeconds (250)),
+ MakeTimeAccessor (&YansWifiPhy::m_channelSwitchDelay),
+ MakeTimeChecker ())
+
;
return tid;
}
YansWifiPhy::YansWifiPhy ()
- : m_endSyncEvent (),
- m_random (0.0, 1.0)
+ : m_channelId(0),
+ m_endSyncEvent (),
+ m_random (0.0, 1.0),
+ m_channelStartingFrequency(0.0)
{
NS_LOG_FUNCTION (this);
m_state = CreateObject<WifiPhyStateHelper> ();
@@ -298,6 +306,32 @@
{
m_channel = channel;
m_channel->Add (this);
+ m_channelId = 0; // always start on channel starting frequency
+}
+
+void
+YansWifiPhy::SetFrequencyChannel (uint16_t nch)
+{
+ Simulator::Schedule (m_channelSwitchDelay, &YansWifiPhy::DoSetChannelId, this, nch);
+}
+
+void
+YansWifiPhy::DoSetChannelId (uint16_t nch)
+{
+ NS_LOG_DEBUG("switching channel " << m_channelId << " -> " << nch);
+ m_channelId = nch;
+}
+
+uint16_t
+YansWifiPhy::GetFrequencyChannel() const
+{
+ return m_channelId;
+}
+
+double
+YansWifiPhy::GetChannelCenterFrequency() const
+{
+ return m_channelStartingFrequency + 5e6 * GetFrequencyChannel();
}
void
@@ -434,6 +468,7 @@
{
NS_LOG_FUNCTION (this);
m_interference.Configure80211aParameters ();
+ m_channelStartingFrequency = 5e9; // 5 GHz
m_modes.push_back (WifiPhy::Get6mba ());
m_modes.push_back (WifiPhy::Get9mba ());
m_modes.push_back (WifiPhy::Get12mba ());
--- a/src/devices/wifi/yans-wifi-phy.h Thu May 28 21:41:45 2009 -0700
+++ b/src/devices/wifi/yans-wifi-phy.h Fri May 29 10:15:19 2009 +0400
@@ -69,6 +69,21 @@
virtual ~YansWifiPhy ();
void SetChannel (Ptr<YansWifiChannel> channel);
+
+ /**
+ * \brief Set channel number.
+ *
+ * Channel center frequency = Channel starting frequency + 5 × nch (MHz)
+ *
+ * where Starting channel frequency is standard-dependent, see SetStandard()
+ * as defined in IEEE 802.11-2007 17.3.8.3.2.
+ */
+ void SetFrequencyChannel (uint16_t id);
+ /// Return current channel ID, see SetChannelId()
+ uint16_t GetFrequencyChannel () const;
+ /// Return current center channel frequency in Hz, see SetChannelId()
+ double GetChannelCenterFrequency() const;
+
void StartReceivePacket (Ptr<Packet> packet,
double rxPowerDbm,
WifiMode mode,
@@ -94,6 +109,8 @@
Ptr<ErrorRateModel> GetErrorRateModel (void) const;
Ptr<Object> GetDevice (void) const;
Ptr<Object> GetMobility (void);
+
+
virtual double GetTxPowerStart (void) const;
@@ -133,6 +150,7 @@
double RatioToDb (double ratio) const;
double GetPowerDbm (uint8_t power) const;
void EndSync (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
+ void DoSetChannelId(uint16_t id);
private:
double m_edThresholdW;
@@ -144,14 +162,18 @@
uint32_t m_nTxPower;
Ptr<YansWifiChannel> m_channel;
+ uint16_t m_channelId;
Ptr<Object> m_device;
Ptr<Object> m_mobility;
Modes m_modes;
EventId m_endSyncEvent;
UniformVariable m_random;
WifiPhyStandard m_standard;
+ /// Standard-dependent center frequency of 0-th channel
+ double m_channelStartingFrequency;
Ptr<WifiPhyStateHelper> m_state;
InterferenceHelper m_interference;
+ Time m_channelSwitchDelay;
};
--- a/src/internet-stack/ipv4-l3-protocol.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/internet-stack/ipv4-l3-protocol.cc Fri May 29 10:15:19 2009 +0400
@@ -31,16 +31,14 @@
#include "ns3/object-vector.h"
#include "ns3/ipv4-header.h"
#include "ns3/boolean.h"
-#include "ns3/ipv4-routing-table-entry.h"
-#include "ns3/ipv4-static-routing.h"
+#include "arp-l3-protocol.h"
-#include "loopback-net-device.h"
-#include "arp-l3-protocol.h"
#include "ipv4-l3-protocol.h"
#include "ipv4-l4-protocol.h"
-#include "ipv4-list-routing-impl.h"
#include "icmpv4-l4-protocol.h"
#include "ipv4-interface.h"
+#include "ipv4-loopback-interface.h"
+#include "arp-ipv4-interface.h"
#include "ipv4-raw-socket-impl.h"
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
@@ -85,6 +83,8 @@
m_identification (0)
{
NS_LOG_FUNCTION_NOARGS ();
+ m_staticRouting = CreateObject<Ipv4StaticRouting> ();
+ AddRoutingProtocol (m_staticRouting, 0);
}
Ipv4L3Protocol::~Ipv4L3Protocol ()
@@ -119,7 +119,6 @@
Ipv4L3Protocol::SetNode (Ptr<Node> node)
{
m_node = node;
- // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
SetupLoopback ();
}
@@ -146,48 +145,18 @@
}
return;
}
-/*
- * This method is called by AddAgregate and completes the aggregation
- * by setting the node in the ipv4 stack
- */
-void
-Ipv4L3Protocol::NotifyNewAggregate ()
-{
- Ptr<Node>node = this->GetObject<Node>();
- // verify that it's a valid node and that
- // the node has not been set before
- if (node!= 0 && m_node == 0)
- {
- this->SetNode (node);
- }
- Object::NotifyNewAggregate ();
-}
-
-void
-Ipv4L3Protocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routing)
-{
- NS_LOG_FUNCTION (this);
- m_routingProtocol = routing;
- // XXX should check all interfaces to see if any were set to Up state
- // prior to a routing protocol being added
- if (GetStaticRouting () != 0)
- {
- GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), 0);
- }
-}
-
-
-Ptr<Ipv4RoutingProtocol>
-Ipv4L3Protocol::GetRoutingProtocol (void) const
-{
- return m_routingProtocol;
-}
void
Ipv4L3Protocol::DoDispose (void)
{
NS_LOG_FUNCTION (this);
- for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+
+ for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
+ {
+ *i = 0;
+ }
+
+ for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
*i = 0;
}
@@ -198,12 +167,10 @@
*i = 0;
}
m_interfaces.clear ();
+ m_routingProtocols.clear ();
m_node = 0;
- if (m_routingProtocol)
- {
- m_routingProtocol->Dispose ();
- m_routingProtocol = 0;
- }
+ m_staticRouting->Dispose ();
+ m_staticRouting = 0;
Object::DoDispose ();
}
@@ -212,33 +179,12 @@
{
NS_LOG_FUNCTION_NOARGS ();
- Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
- Ptr<LoopbackNetDevice> device = 0;
- // First check whether an existing LoopbackNetDevice exists on the node
- for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
- {
- if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
- {
- break;
- }
- }
- if (device == 0)
- {
- device = CreateObject<LoopbackNetDevice> ();
- m_node->AddDevice (device);
- }
- interface->SetDevice (device);
+ Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
interface->SetNode (m_node);
Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
interface->AddAddress (ifaceAddr);
uint32_t index = AddIpv4Interface (interface);
- Ptr<Node> node = GetObject<Node> ();
- node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
- Ipv4L3Protocol::PROT_NUMBER, device);
- if (GetStaticRouting () != 0)
- {
- GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), index);
- }
+ AddHostRouteTo (Ipv4Address::GetLoopback (), index);
interface->SetUp ();
}
@@ -249,24 +195,192 @@
m_defaultTtl = ttl;
}
-// XXX need to remove dependencies on Ipv4StaticRouting from this class
-Ptr<Ipv4StaticRouting>
-Ipv4L3Protocol::GetStaticRouting (void) const
+
+void
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << dest << nextHop << interface);
+ m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << dest << interface);
+ m_staticRouting->AddHostRouteTo (dest, interface);
+}
+
+void
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
+ m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
+ Ipv4Mask networkMask,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << network << networkMask << interface);
+ m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
+}
+
+void
+Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop,
+ uint32_t interface)
+{
+ NS_LOG_FUNCTION (this << nextHop << interface);
+ m_staticRouting->SetDefaultRoute (nextHop, interface);
+}
+
+void
+Ipv4L3Protocol::Lookup (
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply)
+{
+ NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
+
+ Lookup (Ipv4RoutingProtocol::INTERFACE_ANY, ipHeader, packet, routeReply);
+}
+
+void
+Ipv4L3Protocol::Lookup (
+ uint32_t interface,
+ Ipv4Header const &ipHeader,
+ Ptr<Packet> packet,
+ Ipv4RoutingProtocol::RouteReplyCallback routeReply)
+{
+ NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
+
+ for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
+ m_routingProtocols.begin ();
+ rprotoIter != m_routingProtocols.end ();
+ rprotoIter++)
+ {
+ NS_LOG_LOGIC ("Requesting route");
+ if ((*rprotoIter).second->RequestRoute (interface, ipHeader, packet,
+ routeReply))
+ return;
+ }
+
+ if (ipHeader.GetDestination ().IsMulticast () &&
+ interface == Ipv4RoutingProtocol::INTERFACE_ANY)
+ {
+ NS_LOG_LOGIC ("Multicast destination with local source");
+//
+// We have a multicast packet originating from the current node and were not
+// able to send it using the usual RequestRoute process. Since the usual
+// process includes trying to use a default multicast route, this means that
+// there was no specific route out of the node found, and there was no default
+// multicast route set.
+//
+// The fallback position is to look for a default unicast route and use that
+// to get the packet off the node if we have one.
+//
+ Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
+
+ if (route)
+ {
+ NS_LOG_LOGIC ("Local source. Using unicast default route for "
+ "multicast packet");
+
+ routeReply (true, *route, packet, ipHeader);
+ return;
+ }
+ }
+//
+// No route found
+//
+ routeReply (false, Ipv4Route (), packet, ipHeader);
+}
+
+void
+Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+ int16_t priority)
+{
+ NS_LOG_FUNCTION (this << &routingProtocol << priority);
+ m_routingProtocols.push_back
+ (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
+ m_routingProtocols.sort ();
+}
+
+uint32_t
+Ipv4L3Protocol::GetNRoutes (void)
{
NS_LOG_FUNCTION_NOARGS ();
- Ptr<Ipv4StaticRouting> staticRouting;
- if (m_routingProtocol != 0)
- {
- Ptr<Ipv4StaticRoutingImpl> sr = DynamicCast<Ipv4StaticRoutingImpl> (m_routingProtocol);
- if (sr != 0)
- {
- return sr;
- }
- Ptr<Ipv4ListRoutingImpl> lr = DynamicCast<Ipv4ListRoutingImpl> (m_routingProtocol);
- NS_ASSERT (lr);
- staticRouting = lr->GetStaticRouting ();
- }
- return staticRouting;
+ return m_staticRouting->GetNRoutes ();
+}
+
+Ipv4Route
+Ipv4L3Protocol::GetRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return *m_staticRouting->GetRoute (index);
+}
+
+void
+Ipv4L3Protocol::RemoveRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION (this << index);
+ m_staticRouting->RemoveRoute (index);
+}
+
+void
+Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface,
+ std::vector<uint32_t> outputInterfaces)
+{
+ NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
+
+ m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
+ outputInterfaces);
+}
+
+void
+Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
+{
+ NS_LOG_FUNCTION (this << outputInterface);
+
+ m_staticRouting->SetDefaultMulticastRoute (outputInterface);
+}
+
+uint32_t
+Ipv4L3Protocol::GetNMulticastRoutes (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_staticRouting->GetNMulticastRoutes ();
+}
+
+Ipv4MulticastRoute
+Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
+{
+ NS_LOG_FUNCTION (this << index);
+ return *m_staticRouting->GetMulticastRoute (index);
+}
+
+void
+Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
+ Ipv4Address group,
+ uint32_t inputInterface)
+{
+ NS_LOG_FUNCTION (this << origin << group << inputInterface);
+ m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
+}
+
+void
+Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
+{
+ NS_LOG_FUNCTION (this << index);
+ m_staticRouting->RemoveMulticastRoute (index);
}
uint32_t
@@ -280,7 +394,7 @@
node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
ArpL3Protocol::PROT_NUMBER, device);
- Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
+ Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
interface->SetNode (m_node);
interface->SetDevice (device);
return AddIpv4Interface (interface);
@@ -319,60 +433,60 @@
return m_nInterfaces;
}
-int32_t
-Ipv4L3Protocol::GetInterfaceForAddress (
- Ipv4Address address) const
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
{
- NS_LOG_FUNCTION (this << address);
+ NS_LOG_FUNCTION (this << addr);
- int32_t interface = 0;
+ uint32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
{
- for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
+ for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
- if ((*i)->GetAddress (j).GetLocal () == address)
+ if ((*i)->GetAddress (j).GetLocal () == addr)
{
return interface;
}
}
}
- return -1;
+ NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for IP address " << addr);
+ return 0;
}
-int32_t
-Ipv4L3Protocol::GetInterfaceForPrefix (
- Ipv4Address address,
- Ipv4Mask mask) const
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
{
- NS_LOG_FUNCTION (this << address << mask);
+ NS_LOG_FUNCTION (this << addr << mask);
- int32_t interface = 0;
+ uint32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
{
for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
- if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
+ if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == addr.CombineMask (mask))
{
return interface;
}
}
}
- return -1;
+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for masked IP address");
+ return 0;
}
int32_t
-Ipv4L3Protocol::GetInterfaceForDevice (
- Ptr<const NetDevice> device) const
+Ipv4L3Protocol::FindInterfaceForDevice (Ptr<NetDevice> device) const
{
- NS_LOG_FUNCTION (this << device->GetIfIndex());
+ NS_LOG_FUNCTION (this << device);
- int32_t interface = 0;
+ uint32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
@@ -386,18 +500,31 @@
return -1;
}
+Ptr<Ipv4Interface>
+Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
+{
+ NS_LOG_FUNCTION (this << &device);
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+ {
+ if ((*i)->GetDevice () == device)
+ {
+ return *i;
+ }
+ }
+ return 0;
+}
+
void
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION (this << &device << p << protocol << from);
- NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
- m_node->GetId ());
+ NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
- uint32_t interface = 0;
Ptr<Packet> packet = p->Copy ();
+ uint32_t index = 0;
Ptr<Ipv4Interface> ipv4Interface;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
@@ -408,9 +535,9 @@
{
if (ipv4Interface->IsUp ())
{
- m_rxTrace (packet, interface);
+ m_rxTrace (packet, index);
break;
- }
+ }
else
{
NS_LOG_LOGIC ("Dropping received packet-- interface is down");
@@ -418,9 +545,8 @@
return;
}
}
- interface++;
+ index++;
}
-
Ipv4Header ipHeader;
if (m_calcChecksum)
{
@@ -440,13 +566,12 @@
socket->ForwardUp (packet, ipHeader, device);
}
- m_routingProtocol->RouteInput (packet, ipHeader, device,
- MakeCallback (&Ipv4L3Protocol::IpForward, this),
- MakeCallback (&Ipv4L3Protocol::IpMulticastForward, this),
- MakeCallback (&Ipv4L3Protocol::LocalDeliver, this),
- MakeNullCallback <void, Ptr<const Packet>, const Ipv4Header &> ()
- );
+ if (Forwarding (index, packet, ipHeader, device))
+ {
+ return;
+ }
+ ForwardUp (packet, ipHeader, ipv4Interface);
}
Ptr<Icmpv4L4Protocol>
@@ -473,35 +598,74 @@
Ipv4L3Protocol::Send (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
- uint8_t protocol,
- Ptr<Ipv4Route> route)
+ uint8_t protocol)
{
- NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
+ NS_LOG_FUNCTION (this << packet << source << destination << protocol);
Ipv4Header ipHeader;
- bool mayFragment = true;
- uint8_t ttl = m_defaultTtl;
- SocketIpTtlTag tag;
- bool found = packet->FindFirstMatchingTag (tag);
+
+ if (m_calcChecksum)
+ {
+ ipHeader.EnableChecksum ();
+ }
+
+ ipHeader.SetSource (source);
+ ipHeader.SetDestination (destination);
+ ipHeader.SetProtocol (protocol);
+ ipHeader.SetPayloadSize (packet->GetSize ());
+ ipHeader.SetIdentification (m_identification);
+
+ m_identification ++;
+
+ SocketSetDontFragmentTag dfTag;
+ bool found = packet->RemovePacketTag (dfTag);
if (found)
{
- ttl = tag.GetTtl ();
- // XXX remove tag here?
+ if (dfTag.IsEnabled ())
+ {
+ ipHeader.SetDontFragment ();
+ }
+ else
+ {
+ ipHeader.SetMayFragment ();
+ }
}
+
- // Handle a few cases:
- // 1) packet is destined to limited broadcast address
- // 2) packet is destined to a subnet-directed broadcast address
- // 3) packet is not broadcast, and is passed in with a route entry
- // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
- // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
-
- // 1) packet is destined to limited broadcast address
+ // Set TTL to 1 if it is a broadcast packet of any type. Otherwise,
+ // possibly override the default TTL if the packet is tagged
+ SocketIpTtlTag tag;
+ found = packet->RemovePacketTag (tag);
+
if (destination.IsBroadcast ())
{
- NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
- ttl = 1;
- ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+ ipHeader.SetTtl (1);
+ }
+ else if (found)
+ {
+ ipHeader.SetTtl (tag.GetTtl ());
+ }
+ else
+ {
+ ipHeader.SetTtl (m_defaultTtl);
+ uint32_t ifaceIndex = 0;
+ for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+ ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+ {
+ Ptr<Ipv4Interface> outInterface = *ifaceIter;
+ // XXX this logic might not be completely correct for multi-addressed interface
+ for (uint32_t j = 0; j < outInterface->GetNAddresses(); j++)
+ {
+ if (destination.IsSubnetDirectedBroadcast (
+ outInterface->GetAddress (j).GetMask ()))
+ {
+ ipHeader.SetTtl (1);
+ }
+ }
+ }
+ }
+ if (destination.IsBroadcast ())
+ {
uint32_t ifaceIndex = 0;
for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
@@ -509,216 +673,209 @@
Ptr<Ipv4Interface> outInterface = *ifaceIter;
Ptr<Packet> packetCopy = packet->Copy ();
- NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
packetCopy->AddHeader (ipHeader);
- m_txTrace (packetCopy, ifaceIndex);
- outInterface->Send (packetCopy, destination);
- }
- return;
- }
-
- // 2) check: packet is destined to a subnet-directed broadcast address
- uint32_t ifaceIndex = 0;
- for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
- ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
- {
- Ptr<Ipv4Interface> outInterface = *ifaceIter;
- for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
- {
- Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
- NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
- if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
- destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
+ // XXX Handle multiple address on interface
+ if (packetCopy->GetSize () > outInterface->GetMtu () &&
+ ipHeader.IsDontFragment () &&
+ IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
+ {
+ Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
+ NS_ASSERT (icmp != 0);
+ icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ());
+ m_dropTrace (packetCopy);
+ }
+ else if (packet->GetSize () > outInterface->GetMtu () &&
+ !ipHeader.IsDontFragment ())
{
- NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
- ttl = 1;
- ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
- Ptr<Packet> packetCopy = packet->Copy ();
- packetCopy->AddHeader (ipHeader);
- m_txTrace (packetCopy, ifaceIndex);
- outInterface->Send (packetCopy, destination);
- return;
+ NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
+ m_dropTrace (packet);
+ }
+ else
+ {
+ NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
+ if (outInterface->IsUp ())
+ {
+ m_txTrace (packetCopy, ifaceIndex);
+ outInterface->Send (packetCopy, destination);
+ }
+ else
+ {
+ m_dropTrace (packetCopy);
+ }
}
}
}
-
- // 3) packet is not broadcast, and is passed in with a route entry
- // with a valid Ipv4Address as the gateway
- if (route && route->GetGateway () != Ipv4Address ())
- {
- NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
- ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
- SendRealOut (route, packet, ipHeader);
- return;
- }
- // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
- if (route && route->GetGateway () != Ipv4Address ())
- {
- // This could arise because the synchronous RouteOutput() call
- // returned to the transport protocol with a source address but
- // there was no next hop available yet (since a route may need
- // to be queried). So, call asynchronous version of RouteOutput?
- NS_FATAL_ERROR("XXX This case not yet implemented");
- }
- // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
- NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: passed in with no route " << destination);
- Socket::SocketErrno errno;
- uint32_t oif = 0; // unused for now
- ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
- Ptr<Ipv4Route> newRoute = m_routingProtocol->RouteOutput (ipHeader, oif, errno);
- if (newRoute)
- {
- SendRealOut (newRoute, packet, ipHeader);
- }
else
{
- NS_LOG_WARN ("No route to host. Drop.");
- m_dropTrace (packet);
+ // XXX Note here that in most ipv4 stacks in the world,
+ // the route calculation for an outgoing packet is not
+ // done in the ip layer. It is done within the application
+ // socket when the first packet is sent to avoid this
+ // costly lookup on a per-packet basis.
+ // That would require us to get the route from the packet,
+ // most likely with a packet tag. The higher layers do not
+ // do this yet for us.
+ Lookup (ipHeader, packet,
+ MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
}
}
-// XXX when should we set ip_id? check whether we are incrementing
-// m_identification on packets that may later be dropped in this stack
-// and whether that deviates from Linux
-Ipv4Header
-Ipv4L3Protocol::BuildHeader (
- Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol,
- uint16_t payloadSize,
- uint8_t ttl,
- bool mayFragment)
-{
- NS_LOG_FUNCTION_NOARGS ();
- Ipv4Header ipHeader;
- ipHeader.SetSource (source);
- ipHeader.SetDestination (destination);
- ipHeader.SetProtocol (protocol);
- ipHeader.SetPayloadSize (payloadSize);
- ipHeader.SetTtl (ttl);
- if (mayFragment == true)
- {
- ipHeader.SetMayFragment ();
- ipHeader.SetIdentification (m_identification);
- m_identification ++;
- }
- else
- {
- ipHeader.SetDontFragment ();
- // TBD: set to zero here; will cause traces to change
- ipHeader.SetIdentification (m_identification);
- m_identification ++;
- }
- if (m_calcChecksum)
- {
- ipHeader.EnableChecksum ();
- }
- return ipHeader;
-}
-
void
-Ipv4L3Protocol::SendRealOut (Ptr<Ipv4Route> route,
+Ipv4L3Protocol::SendRealOut (bool found,
+ Ipv4Route const &route,
Ptr<Packet> packet,
Ipv4Header const &ipHeader)
{
- NS_LOG_FUNCTION (this << packet << &ipHeader);
+ NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
- // We add a header regardless of whether there is a route, since
- // we may want to drop trace
packet->AddHeader (ipHeader);
- if (route == 0)
+ if (!found)
{
NS_LOG_WARN ("No route to host. Drop.");
m_dropTrace (packet);
return;
}
- Ptr<NetDevice> outDev = route->GetOutputDevice ();
- int32_t interface = GetInterfaceForDevice (outDev);
- NS_ASSERT (interface >= 0);
- Ptr<Ipv4Interface> outInterface = GetInterface (interface);
- NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
+ NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
- NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
- if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
+ Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
+ // XXX handle multiple address on interface
+ if (packet->GetSize () > outInterface->GetMtu () &&
+ ipHeader.IsDontFragment () &&
+ IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
{
- if (outInterface->IsUp ())
- {
- NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
- m_txTrace (packet, interface);
- outInterface->Send (packet, route->GetGateway ());
- }
- else
+ NS_LOG_LOGIC ("Too big: need fragmentation but not allowed");
+ Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
+ NS_ASSERT (icmp != 0);
+ Ptr<Packet> copyNoHeader = packet->Copy ();
+ Ipv4Header tmp;
+ copyNoHeader->RemoveHeader (tmp);
+ icmp->SendDestUnreachFragNeeded (ipHeader, copyNoHeader, outInterface->GetMtu ());
+ m_dropTrace (packet);
+ }
+ else if (packet->GetSize () > outInterface->GetMtu () &&
+ !ipHeader.IsDontFragment ())
+ {
+ NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
+ m_dropTrace (packet);
+ }
+ else
+ {
+ if (route.IsGateway ())
{
- NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
- m_dropTrace (packet);
- }
- }
- else
- {
- if (outInterface->IsUp ())
+ if (outInterface->IsUp ())
+ {
+ NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
+ m_txTrace (packet, route.GetInterface ());
+ outInterface->Send (packet, route.GetGateway ());
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
+ m_dropTrace (packet);
+ }
+ }
+ else
{
- NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
- m_txTrace (packet, interface);
- outInterface->Send (packet, ipHeader.GetDestination ());
- }
- else
- {
- NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
- m_dropTrace (packet);
+ if (outInterface->IsUp ())
+ {
+ NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
+ m_txTrace (packet, route.GetInterface ());
+ outInterface->Send (packet, ipHeader.GetDestination ());
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
+ m_dropTrace (packet);
+ }
}
}
}
-// This function analogous to Linux ip_mr_forward()
-void
-Ipv4L3Protocol::IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv4Header &header)
+bool
+Ipv4L3Protocol::Forwarding (
+ uint32_t interface,
+ Ptr<Packet> packet,
+ Ipv4Header &ipHeader,
+ Ptr<NetDevice> device)
{
- NS_LOG_FUNCTION (mrtentry << p << header);
- NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
- // The output interfaces we could forward this onto are encoded
- // in the OutputTtl of the Ipv4MulticastRoute
- for (uint32_t i = 0; i < Ipv4MulticastRoute::MAX_INTERFACES; i++)
+ NS_LOG_FUNCTION (interface << packet << &ipHeader<< device);
+ NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
+
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end (); i++)
{
- if (mrtentry->GetOutputTtl (i) < Ipv4MulticastRoute::MAX_TTL)
+ for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
- Ptr<Packet> packet = p->Copy ();
- Ipv4Header h = header;
- h.SetTtl (header.GetTtl () - 1);
- if (h.GetTtl () == 0)
+ if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ()))
{
- NS_LOG_WARN ("TTL exceeded. Drop.");
- m_dropTrace (packet);
- return;
+ NS_LOG_LOGIC ("For me (destination match)");
+ return false;
}
- NS_LOG_LOGIC ("Forward multicast via interface " << i);
- Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
- rtentry->SetSource (h.GetSource ());
- rtentry->SetDestination (h.GetDestination ());
- rtentry->SetGateway (Ipv4Address::GetAny ());
- rtentry->SetOutputDevice (GetNetDevice (i));
- SendRealOut (rtentry, packet, h);
- return;
}
}
+
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end (); i++)
+ {
+ Ptr<Ipv4Interface> interface = *i;
+ if (interface->GetDevice () == device)
+ {
+ // XXX multi-address case
+ if (ipHeader.GetDestination ().IsEqual (interface->GetAddress (0).GetBroadcast ()))
+ {
+ NS_LOG_LOGIC ("For me (interface broadcast address)");
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (ipHeader.GetDestination ().IsBroadcast ())
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
+ return false;
+ }
+
+ if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ()))
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
+ return false;
+ }
+//
+// If this is a to a multicast address and this node is a member of the
+// indicated group we need to return false so the multicast is forwarded up.
+//
+ for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
+ i != m_multicastGroups.end (); i++)
+ {
+ if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
+ (*i).second.IsEqual (ipHeader.GetDestination ()))
+ {
+ NS_LOG_LOGIC ("For me (Joined multicast group)");
+ // We forward with a packet copy, since forwarding may change
+ // the packet, affecting our local delivery
+ NS_LOG_LOGIC ("Forwarding (multicast).");
+ DoForward (interface, packet->Copy (), ipHeader);
+ return false;
+ }
+ }
+
+ DoForward (interface, packet, ipHeader);
+ return true;
}
-// This function analogous to Linux ip_forward()
void
-Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ipv4Header &header)
+Ipv4L3Protocol::DoForward (uint32_t interface,
+ Ptr<Packet> packet,
+ Ipv4Header ipHeader)
{
- NS_LOG_FUNCTION (rtentry << p << header);
- NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
- // Forwarding
- Ipv4Header ipHeader = header;
- Ptr<Packet> packet = p->Copy ();
+ NS_LOG_FUNCTION (this << interface << packet << ipHeader);
+
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
// XXX handle multi-interfaces
if (ipHeader.GetTtl () == 0)
{
- Ptr<NetDevice> outDev = rtentry->GetOutputDevice ();
- int32_t interface = GetInterfaceForDevice (outDev);
- NS_ASSERT (interface >= 0);
if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ()))
{
Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
@@ -727,15 +884,18 @@
NS_LOG_WARN ("TTL exceeded. Drop.");
m_dropTrace (packet);
return;
- }
- SendRealOut (rtentry, packet, ipHeader);
+ }
+ NS_LOG_LOGIC ("Not for me, forwarding.");
+ Lookup (interface, ipHeader, packet,
+ MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
}
+
void
-Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
+Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
+ Ptr<Ipv4Interface> incomingInterface)
{
- NS_LOG_FUNCTION (this << packet << &ip);
- Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
+ NS_LOG_FUNCTION (this << p << &ip);
Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
if (protocol != 0)
@@ -744,15 +904,15 @@
// RX_ENDPOINT_UNREACH codepath
Ptr<Packet> copy = p->Copy ();
enum Ipv4L4Protocol::RxStatus status =
- protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
+ protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
switch (status) {
case Ipv4L4Protocol::RX_OK:
// fall through
case Ipv4L4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
- // XXX handle multi-interfaces
- if (IsUnicast (ip.GetDestination (), GetInterface (iif)->GetAddress (0).GetMask ()))
+ // XXX handle multi-interface case
+ if (IsUnicast (ip.GetDestination (), incomingInterface->GetAddress (0).GetMask ()))
{
GetIcmp ()->SendDestUnreachPort (ip, copy);
}
@@ -761,7 +921,32 @@
}
}
-uint32_t
+void
+Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ NS_LOG_FUNCTION (this << origin << group);
+ m_multicastGroups.push_back(
+ std::pair<Ipv4Address, Ipv4Address> (origin, group));
+}
+
+void
+Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
+{
+ NS_LOG_FUNCTION (this << origin << group);
+
+ for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
+ i != m_multicastGroups.end ();
+ i++)
+ {
+ if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
+ {
+ m_multicastGroups.erase (i);
+ return;
+ }
+ }
+}
+
+uint32_t
Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
{
NS_LOG_FUNCTION (this << i << address);
@@ -769,7 +954,7 @@
return interface->AddAddress (address);
}
-Ipv4InterfaceAddress
+Ipv4InterfaceAddress
Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
{
NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
@@ -777,7 +962,7 @@
return interface->GetAddress (addressIndex);
}
-uint32_t
+uint32_t
Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
{
NS_LOG_FUNCTION (this << interface);
@@ -801,6 +986,76 @@
return interface->GetMetric ();
}
+bool
+Ipv4L3Protocol::GetInterfaceForDestination (
+ Ipv4Address destination, uint32_t& interface) const
+{
+ NS_LOG_FUNCTION (this << destination << &interface);
+//
+// The first thing we do in trying to determine a source address is to
+// consult the routing protocols. These will also check for a default route
+// if one has been set.
+//
+ for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
+ i != m_routingProtocols.end ();
+ i++)
+ {
+ NS_LOG_LOGIC ("Requesting Source Address");
+ uint32_t interfaceTmp;
+
+ if ((*i).second->RequestInterface (destination, interfaceTmp))
+ {
+ NS_LOG_LOGIC ("Found interface " << interfaceTmp);
+ interface = interfaceTmp;
+ return true;
+ }
+ }
+//
+// If there's no routing table entry telling us what *single* interface will
+// be used to send a packet to this destination, we'll have to just pick one.
+// If there's only one interface on this node, a good answer isn't very hard
+// to come up with. Before jumping to any conclusions, remember that the
+// zeroth interface is the loopback interface, so what we actually want is
+// a situation where there are exactly two interfaces on the node, in which
+// case interface one is the "single" interface connected to the outside world.
+//
+ if (GetNInterfaces () == 2)
+ {
+ NS_LOG_LOGIC ("One Interface. Using interface 1.");
+ interface = 1;
+ return true;
+ }
+//
+// If we fall through to here, we have a node with multiple interfaces and
+// no routes to guide us in determining what interface to choose. Either
+// no default route was found (for unicast or multicast), or in the case of a
+// multicast, the default route contained multiple outbound interfaces.
+//
+// The fallback position is to just get the unicast default route and use
+// the outgoing interface specified there. We don't want to leave the source
+// address unset, so we just assert here.
+//
+// N.B. that in the case of a multicast with a route containing multiple
+// outgoing interfaces, the source address of packets from that node will be
+// set to the IP address of the interface set in the default unicast route.
+// Also, in the case of a broadcast, the same will be true.
+//
+ NS_LOG_LOGIC ("Using default unicast route");
+ Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
+
+ if (route == NULL)
+ {
+ NS_LOG_LOGIC ("Ipv4L3Protocol::GetInterfaceForDestination (): "
+ "Unable to determine outbound interface. No default route set");
+ return false;
+ }
+
+ interface = route->GetInterface ();
+
+ NS_LOG_LOGIC ("Default route specifies interface " << interface);
+ return true;
+}
+
uint16_t
Ipv4L3Protocol::GetMtu (uint32_t i) const
{
@@ -832,9 +1087,7 @@
if (((interface->GetAddress (j).GetLocal ()) != (Ipv4Address ()))
&& (interface->GetAddress (j).GetMask ()) != (Ipv4Mask ()))
{
- NS_ASSERT_MSG (GetStaticRouting(), "SetUp:: No static routing");
- GetStaticRouting ()->AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()),
- interface->GetAddress (j).GetMask (), i);
+ AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()), interface->GetAddress (j).GetMask (), i);
}
}
}
@@ -851,12 +1104,12 @@
while (modified)
{
modified = false;
- for (uint32_t i = 0; i < GetStaticRouting ()->GetNRoutes (); i++)
+ for (uint32_t i = 0; i < GetNRoutes (); i++)
{
- Ipv4RoutingTableEntry route = GetStaticRouting ()->GetRoute (i);
+ Ipv4Route route = GetRoute (i);
if (route.GetInterface () == ifaceIndex)
{
- GetStaticRouting ()->RemoveRoute (i);
+ RemoveRoute (i);
modified = true;
break;
}
@@ -864,23 +1117,43 @@
}
}
+// Note: This method will be removed in Ipv4 routing work
+Ipv4Address
+Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const
+{
+ uint32_t interface = 0xffffffff;
+
+ bool result = GetInterfaceForDestination (destination, interface);
+
+ if (result)
+ {
+ // if multiple addresses exist, search for the first one on the same subnet
+ for (uint32_t i = 0; i < GetNAddresses (interface); i++)
+ {
+ Ipv4InterfaceAddress ipv4InAddr = GetAddress (interface, i);
+ if (ipv4InAddr.GetLocal().CombineMask(ipv4InAddr.GetMask ()) == destination.CombineMask (ipv4InAddr.GetMask ()))
+ {
+ return ipv4InAddr.GetLocal ();
+ }
+ }
+ // Destination is off-link, so return first address.
+ return GetAddress (interface, 0).GetLocal ();
+ }
+ else
+ {
+//
+// If we can't find any address, just leave it 0.0.0.0
+//
+ return Ipv4Address::GetAny ();
+ }
+}
+
Ptr<NetDevice>
Ipv4L3Protocol::GetNetDevice (uint32_t i)
{
return GetInterface (i)-> GetDevice ();
}
-void
-Ipv4L3Protocol::SetIpForward (bool forward)
-{
- m_ipForward = forward;
-}
-
-bool
-Ipv4L3Protocol::GetIpForward (void) const
-{
- return m_ipForward;
-}
}//namespace ns3
--- a/src/internet-stack/tcp-socket-impl.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/internet-stack/tcp-socket-impl.cc Fri May 29 10:15:19 2009 +0400
@@ -563,6 +563,9 @@
m_rxBufSize += i->second->GetSize()-avail;
}
}
+ SocketAddressTag tag;
+ tag.SetAddress (InetSocketAddress (m_remoteAddress, m_remotePort));
+ outPacket->AddPacketTag (tag);
return outPacket;
}
@@ -577,7 +580,7 @@
Ptr<Packet>
TcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
- Address &fromAddress)
+ Address &fromAddress)
{
NS_LOG_FUNCTION (this << maxSize << flags);
Ptr<Packet> packet = Recv (maxSize, flags);
@@ -586,7 +589,7 @@
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -1196,9 +1199,6 @@
p = p->CreateFragment (0,s);
m_nextRxSequence += s; // Advance next expected sequence
NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
//buffer this, it'll be read by call to Recv
UnAckData_t::iterator i =
m_bufferedData.find (tcpHeader.GetSequenceNumber () );
@@ -1266,9 +1266,6 @@
}
}
// Save for later delivery
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
m_bufferedData[startSeq] = p;
i = m_bufferedData.find (startSeq);
next = i;
@@ -1295,9 +1292,6 @@
p = p->CreateFragment (m_nextRxSequence - tcpHeader.GetSequenceNumber (),s);
SequenceNumber start = m_nextRxSequence;
m_nextRxSequence += s; // Advance next expected sequence
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
//buffer the new fragment, it'll be read by call to Recv
UnAckData_t::iterator i = m_bufferedData.find (start);
if (i != m_bufferedData.end () ) //we found it already in the buffer
--- a/src/internet-stack/udp-socket-impl.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/internet-stack/udp-socket-impl.cc Fri May 29 10:15:19 2009 +0400
@@ -23,8 +23,6 @@
#include "ns3/inet-socket-address.h"
#include "ns3/ipv4-route.h"
#include "ns3/ipv4.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/ipv4-routing-protocol.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/trace-source-accessor.h"
#include "udp-socket-impl.h"
@@ -72,7 +70,6 @@
{
NS_LOG_FUNCTION_NOARGS ();
- // XXX todo: leave any multicast groups that have been joined
m_node = 0;
if (m_endPoint != 0)
{
@@ -311,6 +308,7 @@
return -1;
}
+ uint32_t localInterface;
Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
// Locally override the IP TTL for this socket
@@ -321,21 +319,22 @@
// irrespective of what is set in these socket options. So, this tagging
// may end up setting the TTL of a limited broadcast packet to be
// the same as a unicast, but it will be fixed further down the stack
+ //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipMulticastTtl);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipTtl);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
{
SocketSetDontFragmentTag tag;
- bool found = p->FindFirstMatchingTag (tag);
+ bool found = p->RemovePacketTag (tag);
if (!found)
{
if (m_mtuDiscover)
@@ -346,7 +345,7 @@
{
tag.Disable ();
}
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
}
//
@@ -392,31 +391,14 @@
NS_LOG_LOGIC ("Limited broadcast end.");
return p->GetSize();
}
- else if (ipv4->GetRoutingProtocol () != 0)
+ else if (ipv4->GetInterfaceForDestination(dest, localInterface))
{
- Ipv4Header header;
- header.SetDestination (dest);
- Socket::SocketErrno errno;
- Ptr<Ipv4Route> route;
- uint32_t oif = 0; //specify non-zero if bound to a source address
- // TBD-- we could cache the route and just check its validity
- route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
- if (route != 0)
- {
- NS_LOG_LOGIC ("Route exists");
- header.SetSource (route->GetSource ());
- m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (),
- m_endPoint->GetLocalPort (), port, route);
- NotifyDataSent (p->GetSize ());
- return p->GetSize();
- }
- else
- {
- NS_LOG_LOGIC ("No route to destination");
- NS_LOG_ERROR (errno);
- m_errno = errno;
- return -1;
- }
+ NS_LOG_LOGIC ("Route exists");
+ m_udp->Send (p->Copy (), ipv4->GetSourceAddress (dest), dest,
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p->GetSize ());
+ NotifySend (GetTxAvailable ());
+ return p->GetSize();;
}
else
{
@@ -482,7 +464,7 @@
Ptr<Packet>
UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
- Address &fromAddress)
+ Address &fromAddress)
{
NS_LOG_FUNCTION (this << maxSize << flags);
Ptr<Packet> packet = Recv (maxSize, flags);
@@ -490,7 +472,7 @@
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -512,34 +494,6 @@
return 0;
}
-int
-UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
-{
- NS_LOG_FUNCTION (interface << groupAddress);
- /*
- 1) sanity check interface
- 2) sanity check that it has not been called yet on this interface/group
- 3) determine address family of groupAddress
- 4) locally store a list of (interface, groupAddress)
- 5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
- */
- return 0;
-}
-
-int
-UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress)
-{
- NS_LOG_FUNCTION (interface << groupAddress);
- /*
- 1) sanity check interface
- 2) determine address family of groupAddress
- 3) delete from local list of (interface, groupAddress); raise a LOG_WARN
- if not already present (but return 0)
- 5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
- */
- return 0;
-}
-
void
UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
{
@@ -554,7 +508,7 @@
Address address = InetSocketAddress (ipv4, port);
SocketAddressTag tag;
tag.SetAddress (address);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
m_deliveryQueue.push (packet);
m_rxAvailable += packet->GetSize ();
NotifyDataRecv ();
@@ -598,54 +552,30 @@
}
void
-UdpSocketImpl::SetIpTtl (uint8_t ipTtl)
+UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
{
m_ipTtl = ipTtl;
}
-uint8_t
+uint32_t
UdpSocketImpl::GetIpTtl (void) const
{
return m_ipTtl;
}
void
-UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl)
+UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
{
m_ipMulticastTtl = ipTtl;
}
-uint8_t
+uint32_t
UdpSocketImpl::GetIpMulticastTtl (void) const
{
return m_ipMulticastTtl;
}
void
-UdpSocketImpl::SetIpMulticastIf (int32_t ipIf)
-{
- m_ipMulticastIf = ipIf;
-}
-
-int32_t
-UdpSocketImpl::GetIpMulticastIf (void) const
-{
- return m_ipMulticastIf;
-}
-
-void
-UdpSocketImpl::SetIpMulticastLoop (bool loop)
-{
- m_ipMulticastLoop = loop;
-}
-
-bool
-UdpSocketImpl::GetIpMulticastLoop (void) const
-{
- return m_ipMulticastLoop;
-}
-
-void
UdpSocketImpl::SetMtuDiscover (bool discover)
{
m_mtuDiscover = discover;
@@ -658,3 +588,207 @@
} //namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "internet-stack.h"
+#include <string>
+
+namespace ns3 {
+
+class UdpSocketImplTest: public Test
+{
+ Ptr<Packet> m_receivedPacket;
+ Ptr<Packet> m_receivedPacket2;
+
+public:
+ virtual bool RunTests (void);
+ UdpSocketImplTest ();
+
+ void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+ void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+ void ReceivePkt (Ptr<Socket> socket);
+ void ReceivePkt2 (Ptr<Socket> socket);
+};
+
+
+UdpSocketImplTest::UdpSocketImplTest ()
+ : Test ("UdpSocketImpl")
+{
+}
+
+void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+ m_receivedPacket = packet;
+}
+
+void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+ m_receivedPacket2 = packet;
+}
+
+void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+ uint32_t availableData;
+ availableData = socket->GetRxAvailable ();
+ m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+ NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+}
+
+void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
+{
+ uint32_t availableData;
+ availableData = socket->GetRxAvailable ();
+ m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+ NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
+}
+
+bool
+UdpSocketImplTest::RunTests (void)
+{
+ bool result = true;
+
+ // Create topology
+
+ // Receiver Node
+ Ptr<Node> rxNode = CreateObject<Node> ();
+ AddInternetStack (rxNode);
+ Ptr<SimpleNetDevice> rxDev1, rxDev2;
+ { // first interface
+ rxDev1 = CreateObject<SimpleNetDevice> ();
+ rxDev1->SetAddress (Mac48Address::Allocate ());
+ rxNode->AddDevice (rxDev1);
+ Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
+ Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U));
+ ipv4->AddAddress (netdev_idx, ipv4Addr);
+ ipv4->SetUp (netdev_idx);
+ }
+
+ { // second interface
+ rxDev2 = CreateObject<SimpleNetDevice> ();
+ rxDev2->SetAddress (Mac48Address::Allocate ());
+ rxNode->AddDevice (rxDev2);
+ Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
+ Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U));
+ ipv4->AddAddress (netdev_idx, ipv4Addr);
+ ipv4->SetUp (netdev_idx);
+ }
+
+ // Sender Node
+ Ptr<Node> txNode = CreateObject<Node> ();
+ AddInternetStack (txNode);
+ Ptr<SimpleNetDevice> txDev1;
+ {
+ txDev1 = CreateObject<SimpleNetDevice> ();
+ txDev1->SetAddress (Mac48Address::Allocate ());
+ txNode->AddDevice (txDev1);
+ Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (txDev1);
+ Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U));
+ ipv4->AddAddress (netdev_idx, ipv4Addr);
+ ipv4->SetUp (netdev_idx);
+ }
+ Ptr<SimpleNetDevice> txDev2;
+ {
+ txDev2 = CreateObject<SimpleNetDevice> ();
+ txDev2->SetAddress (Mac48Address::Allocate ());
+ txNode->AddDevice (txDev2);
+ Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+ uint32_t netdev_idx = ipv4->AddInterface (txDev2);
+ Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U));
+ ipv4->AddAddress (netdev_idx, ipv4Addr);
+ ipv4->SetUp (netdev_idx);
+ }
+
+ // link the two nodes
+ Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+ rxDev1->SetChannel (channel1);
+ txDev1->SetChannel (channel1);
+
+ Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
+ rxDev2->SetChannel (channel2);
+ txDev2->SetChannel (channel2);
+
+
+ // Create the UDP sockets
+ Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+ Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+ NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
+ rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
+
+ Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
+ rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+ NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
+
+ Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+ Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+
+ // ------ Now the tests ------------
+
+ // Unicast test
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0,
+ InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
+
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
+
+ // Simple broadcast test
+
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0,
+ InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ // second socket should not receive it (it is bound specifically to the second interface's address
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
+
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
+
+ // Broadcast test with multiple receiving sockets
+
+ // When receiving broadcast packets, all sockets sockets bound to
+ // the address/port should receive a copy of the same packet -- if
+ // the socket address matches.
+ rxSocket2->Dispose ();
+ rxSocket2 = rxSocketFactory->CreateSocket ();
+ rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+ NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
+
+ m_receivedPacket = Create<Packet> ();
+ m_receivedPacket2 = Create<Packet> ();
+ NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123), 0,
+InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+ Simulator::Run ();
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+ NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
+
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
+
+ Simulator::Destroy ();
+
+ return result;
+}
+
+static UdpSocketImplTest gUdpSocketImplTest;
+
+}; // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/node/address.h Thu May 28 21:41:45 2009 -0700
+++ b/src/node/address.h Fri May 29 10:15:19 2009 +0400
@@ -91,7 +91,7 @@
* can be stored in an Address instance.
*/
enum MaxSize_e {
- MAX_SIZE = 30
+ MAX_SIZE = 20
};
/**
--- a/src/node/packet-socket.cc Thu May 28 21:41:45 2009 -0700
+++ b/src/node/packet-socket.cc Fri May 29 10:15:19 2009 +0400
@@ -52,7 +52,7 @@
PacketSocket::PacketSocket () : m_rxAvailable (0)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
m_state = STATE_OPEN;
m_shutdownSend = false;
m_shutdownRecv = false;
@@ -64,40 +64,40 @@
void
PacketSocket::SetNode (Ptr<Node> node)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << node);
m_node = node;
}
PacketSocket::~PacketSocket ()
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
}
void
PacketSocket::DoDispose (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
m_device = 0;
}
enum Socket::SocketErrno
PacketSocket::GetErrno (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
return m_errno;
}
Ptr<Node>
PacketSocket::GetNode (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
return m_node;
}
int
PacketSocket::Bind (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
PacketSocketAddress address;
address.SetProtocol (0);
address.SetAllDevices ();
@@ -107,7 +107,7 @@
int
PacketSocket::Bind (const Address &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
if (!PacketSocketAddress::IsMatchingType (address))
{
m_errno = ERROR_INVAL;
@@ -120,7 +120,7 @@
int
PacketSocket::DoBind (const PacketSocketAddress &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
if (m_state == STATE_BOUND ||
m_state == STATE_CONNECTED)
{
@@ -153,7 +153,7 @@
int
PacketSocket::ShutdownSend (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -166,7 +166,7 @@
int
PacketSocket::ShutdownRecv (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -179,7 +179,7 @@
int
PacketSocket::Close(void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -192,7 +192,7 @@
int
PacketSocket::Connect(const Address &ad)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << ad);
PacketSocketAddress address;
if (m_state == STATE_CLOSED)
{
@@ -233,7 +233,7 @@
int
PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << p << flags);
if (m_state == STATE_OPEN ||
m_state == STATE_BOUND)
{
@@ -278,7 +278,7 @@
int
PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << p << flags << address);
PacketSocketAddress ad;
if (m_state == STATE_CLOSED)
{
@@ -351,7 +351,7 @@
uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
if (m_shutdownRecv)
{
return;
@@ -365,10 +365,11 @@
if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
{
+ Ptr<Packet> copy = packet->Copy ();
SocketAddressTag tag;
tag.SetAddress (address);
- packet->AddTag (tag);
- m_deliveryQueue.push (packet->Copy ());
+ copy->AddPacketTag (tag);
+ m_deliveryQueue.push (copy);
m_rxAvailable += packet->GetSize ();
NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
NotifyDataRecv ();
@@ -388,7 +389,7 @@
uint32_t
PacketSocket::GetRxAvailable (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
// We separately maintain this state to avoid walking the queue
// every time this might be called
return m_rxAvailable;
@@ -397,7 +398,7 @@
Ptr<Packet>
PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << maxSize << flags);
if (m_deliveryQueue.empty() )
{
return 0;
@@ -418,13 +419,13 @@
Ptr<Packet>
PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
Ptr<Packet> packet = Recv (maxSize, flags);
if (packet != 0)
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -434,7 +435,7 @@
int
PacketSocket::GetSockName (Address &address) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
PacketSocketAddress ad = PacketSocketAddress::ConvertFrom(address);
ad.SetProtocol (m_protocol);
--- a/src/wscript Thu May 28 21:41:45 2009 -0700
+++ b/src/wscript Fri May 29 10:15:19 2009 +0400
@@ -33,6 +33,8 @@
'helper',
'contrib/stats',
'applications/v4ping',
+ 'devices/mesh',
+ 'devices/mesh/dot11s',
)
def set_options(opt):
--- a/utils/bench-packets.cc Thu May 28 21:41:45 2009 -0700
+++ b/utils/bench-packets.cc Fri May 29 10:15:19 2009 +0400
@@ -168,14 +168,14 @@
for (uint32_t i = 0; i < n; i++) {
Ptr<Packet> p = Create<Packet> (2000);
- p->AddTag (tag1);
+ p->AddPacketTag (tag1);
p->AddHeader (udp);
- p->FindFirstMatchingTag (tag1);
- p->AddTag (tag2);
+ p->RemovePacketTag (tag1);
+ p->AddPacketTag (tag2);
p->AddHeader (ipv4);
Ptr<Packet> o = p->Copy ();
o->RemoveHeader (ipv4);
- p->FindFirstMatchingTag (tag2);
+ p->RemovePacketTag (tag2);
o->RemoveHeader (udp);
}
}