Skip to content

Commit

Permalink
Upgrade (#52)
Browse files Browse the repository at this point in the history
* Use kodo-rlnc 15 + Remove factories
  • Loading branch information
petya2164 committed Sep 4, 2019
1 parent 0a4ff54 commit 7f91ec0
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 204 deletions.
5 changes: 5 additions & 0 deletions NEWS.rst
Expand Up @@ -7,6 +7,11 @@ detailed list of every change, see the Git log.
Latest
------
* tbd
* Minor: Upgrade to the ns-3.30 release
* Major: Use the --destdir option to specify the target installation folder
for the examples (e.g. ``~/ns-3-dev/examples/kodo``).
Consequently, the --ns3_path option was removed.
* Major: Upgrade to kodo-rlnc 15

2.0.0
-----
Expand Down
44 changes: 20 additions & 24 deletions README.rst
Expand Up @@ -93,12 +93,12 @@ Our aim is to make the examples compatible with the latest ns-3 revision.
If you experience any issues with the latest revision, then you can switch
to the latest stable release (this step is **optional**)::

git checkout ns-3.29
git checkout ns-3.30

Our build system automatically tests the examples with the latest supported
revision of ns-3. This revision is specified in our buildbot.py_ script.

.. _buildbot.py: https://github.com/steinwurf/kodo-ns3-examples/blob/master/buildbot.py#L74
.. _buildbot.py: https://github.com/steinwurf/kodo-ns3-examples/blob/master/buildbot.py#L73

Configure the ns-3 project (it is important to also enable the examples)::

Expand Down Expand Up @@ -128,17 +128,13 @@ The ``waf configure`` command ensures that all dependencies are downloaded
(by default, waf will create a folder called ``bundle_dependencies`` to
store these libraries).

You must have **a valid Steinwurf license** to download the ``fifi`` and
``kodo`` dependencies, otherwise you will get a git error when you execute
the configure command!

Now we build the kodo-rlnc static library and we install the examples and all
the required files to the ``~/ns-3-dev/examples/kodo`` folder::

python waf build install --ns3_path="~/ns-3-dev"
python waf build install --destdir="~/ns-3-dev/examples/kodo"

The ``--ns3_path`` option is used to specify your ns-3 folder (you can change
this if your ns-3 is located elsewhere).
The ``--destdir`` option is used to specify the target folder (you can change
the ``kodo`` subfolder name to something else if you like).

Building the Kodo examples in ns-3
----------------------------------
Expand Down Expand Up @@ -182,19 +178,22 @@ and how many transmissions were required.

Adding your own simulation
--------------------------

At this point, you might want to add your own simulation that uses kodo.
It is recommended to create a new program by copying one of the kodo examples.
The examples are installed in ``~/ns-3-dev/examples/kodo``, so we will go to
that folder and make a copy ``kodo-wifi-broadcast.cc`` to create a new
simulation called ``my-simulation.cc`` (you can choose any name here)::

cd ~/ns-3-dev/examples/kodo
cp kodo-wifi-broadcast.cc my-simulation.cc
It is recommended to create a separate folder (e.g.
``~/ns-3-dev/examples/my-simulation``) for your custom simulation and copy all
the necessary files from ``~/ns-3-dev/examples/kodo`` (most importantly the
``include`` and ``lib`` folders).

To build an executable from the ``my-simulation.cc`` source file, we have to
define a new program in ``~/ns-3-dev/examples/kodo/wscript``.
Open this file in your text editor, and add the following lines at the end
(be careful with the indentation since this is a Python script)::
If you copy the wscript file, then please delete or comment out the parts where
we call ``bld.create_ns3_program``. We cannot have multiple programs with
the same name (e.g. ``kodo-recoders``).

When you create a new program, you can start by copying one of the kodo examples.
If you have a source file called ``my-simulation.cc``, then you can
define a new program in ``~/ns-3-dev/examples/my-simulation/wscript``.
like this::

obj = bld.create_ns3_program('my-simulation',
['core', 'applications', 'point-to-point',
Expand All @@ -220,13 +219,10 @@ these in the wscript like this::
**Warning:** If you install the kodo ns-3 examples again with this command::

cd ~/kodo-ns3-examples
python waf build install --ns3_path="~/ns-3-dev"
python waf build install --destdir="~/ns-3-dev/examples/kodo"

then the example source files and the wscript will be overwritten in
the ``~/ns-3-dev/examples/kodo`` folder, so it is recommended to create a
backup if you modified any of these files.

You can also create a separate folder for your custom simulation to avoid this
problem. For example, you can create the ``~/ns-3-dev/examples/my-simulation``
folder and copy the ``include`` and ``lib`` folders from
``~/ns-3-dev/examples/kodo``.

4 changes: 2 additions & 2 deletions buildbot.py
Expand Up @@ -70,7 +70,7 @@ def configure(properties):
# See revisions here: https://gitlab.com/nsnam/ns-3-dev/commits/master
os.chdir(ns3_path)
run_command(['git', 'pull'])
run_command(['git', 'reset', '--hard', '7112e718'])
run_command(['git', 'reset', '--hard', '5de272fa'])
# Configure ns-3 with the examples enabled
run_command([sys.executable, 'waf', 'configure', '--enable-examples'])

Expand All @@ -80,7 +80,7 @@ def build(properties):
# Install the examples, the required headers and the compiled static
# libraries to '{ns3_path}/examples/kodo'
command = [sys.executable, 'waf', 'build', 'install', '-v']
command += ['--ns3_path={}'.format(properties['ns3_path'])]
command += ['--destdir={}/examples/kodo'.format(properties['ns3_path'])]
run_command(command)

ns3_path = properties['ns3_path']
Expand Down
4 changes: 2 additions & 2 deletions docs/wifi_broadcast.rst
Expand Up @@ -130,7 +130,7 @@ The ``Broadcast`` class can be roughly defined in the following way:
{
public:

Broadcast (const fifi::api::field field, const uint32_t users,
Broadcast (const fifi::finite_field field, const uint32_t users,
const uint32_t generationSize, const uint32_t packetSize,
const ns3::Ptr<ns3::Socket>& source,
const std::vector<ns3::Ptr<ns3::Socket>>& sinks)
Expand All @@ -156,7 +156,7 @@ The ``Broadcast`` class can be roughly defined in the following way:

private:

const fifi::api::field m_field;
const fifi::finite_field m_field;
const uint32_t m_users;
const uint32_t m_generationSize;
const uint32_t m_packetSize;
Expand Down
34 changes: 15 additions & 19 deletions examples/kodo-broadcast-object.h
Expand Up @@ -45,7 +45,7 @@ class BroadcastObject

public:

BroadcastObject (const fifi::api::field field, const uint32_t users,
BroadcastObject (const fifi::finite_field field, const uint32_t users,
const uint32_t objectSize, const uint32_t generationSize,
const uint32_t packetSize, const uint32_t extraPackets,
const ns3::Ptr<ns3::Socket>& source,
Expand All @@ -62,14 +62,9 @@ class BroadcastObject
m_currentBlock = 0;
m_payloadsForCurrentBlock = 0;

// Create factories using the supplied parameters
storage_encoder::factory encoderFactory (m_field,
m_generationSize, m_packetSize);
storage_decoder::factory decoderFactory (m_field,
m_generationSize, m_packetSize);

// Create the storage encoder
m_encoder = encoderFactory.build ();
m_encoder = std::make_shared<storage_encoder> (m_field,
m_generationSize, m_packetSize);

// Initialize the data buffer that might be larger than a single generation
// In a realistic application, this input buffer can be read from a file
Expand All @@ -82,12 +77,12 @@ class BroadcastObject
m_decoderStacks.resize (m_users);
for (uint32_t n = 0; n < m_users; n++)
{
auto decoder = decoderFactory.build ();
storage_decoder decoder (m_field, m_generationSize, m_packetSize);

// Create data buffer for the decoder
m_decoderBuffers[n].resize (m_objectSize);
decoder->set_mutable_storage (storage::storage (m_decoderBuffers[n]));
m_decoderStacks[n].resize (decoder->blocks ());
decoder.set_mutable_storage (storage::storage (m_decoderBuffers[n]));
m_decoderStacks[n].resize (decoder.blocks ());

m_decoders.emplace_back (decoder);
}
Expand All @@ -102,7 +97,7 @@ class BroadcastObject

for (uint32_t n = 0; n < m_users; n++)
{
allDecoded = allDecoded && m_decoders[n]->is_complete ();
allDecoded = allDecoded && m_decoders[n].is_complete ();
}

if (!allDecoded)
Expand All @@ -127,11 +122,12 @@ class BroadcastObject
}

// Create a payload that will also contain the block ID
std::vector<uint8_t> payload (4 + m_encoderStacks[i]->payload_size ());
std::vector<uint8_t> payload (
4 + m_encoderStacks[i]->max_payload_size ());
// First, the current block ID to the payload
endian::big_endian::put<uint32_t>(i, payload.data());
// Write a symbol to the payload buffer after the block ID
uint32_t bytesUsed = m_encoderStacks[i]->write_payload (&payload[4]);
uint32_t bytesUsed = m_encoderStacks[i]->produce_payload (&payload[4]);
auto packet = ns3::Create<ns3::Packet> (&payload[0], 4 + bytesUsed);
socket->Send (packet);
m_payloadsForCurrentBlock++;
Expand Down Expand Up @@ -167,22 +163,22 @@ class BroadcastObject
// Create the decoder for this block if it does not exist
if (!m_decoderStacks[n][i])
{
m_decoderStacks[n][i] = m_decoders[n]->build (i);
m_decoderStacks[n][i] = m_decoders[n].build (i);
}

// Nothing to do if this block is already completed
if (m_decoderStacks[n][i]->is_complete ())
return;

// Pass the symbol to the appropriate decoder
m_decoderStacks[n][i]->read_payload (&payload[4]);
m_decoderStacks[n][i]->consume_payload (&payload[4]);

if (m_decoderStacks[n][i]->is_complete ())
{
std::cout << "Block " << i << " completed at Decoder " << n + 1
<< std::endl;
}
if (m_decoders[n]->is_complete ())
if (m_decoders[n].is_complete ())
{
std::cout << "All blocks completed at Decoder " << n + 1 << std::endl;
}
Expand All @@ -192,7 +188,7 @@ class BroadcastObject

uint32_t m_currentBlock;
uint32_t m_payloadsForCurrentBlock;
const fifi::api::field m_field;
const fifi::finite_field m_field;
const uint32_t m_users;
const uint32_t m_objectSize;
const uint32_t m_generationSize;
Expand All @@ -204,7 +200,7 @@ class BroadcastObject
std::shared_ptr<storage_encoder> m_encoder;
std::vector<encoder_stack_ptr> m_encoderStacks;
std::vector<uint8_t> m_encoderBuffer;
std::vector<std::shared_ptr<storage_decoder>> m_decoders;
std::vector<storage_decoder> m_decoders;
std::vector<std::vector<decoder_stack_ptr>> m_decoderStacks;
std::vector<std::vector<uint8_t>> m_decoderBuffers;

Expand Down
47 changes: 20 additions & 27 deletions examples/kodo-broadcast.h
Expand Up @@ -31,7 +31,7 @@ class Broadcast
{
public:

Broadcast (const fifi::api::field field, const uint32_t users,
Broadcast (const fifi::finite_field field, const uint32_t users,
const uint32_t generationSize, const uint32_t packetSize,
const ns3::Ptr<ns3::Socket>& source,
const std::vector<ns3::Ptr<ns3::Socket>>& sinks)
Expand All @@ -42,43 +42,37 @@ class Broadcast
m_source (source),
m_sinks (sinks)
{
// Create factories using the supplied parameters
kodo_rlnc::encoder::factory encoderFactory (m_field,
m_generationSize, m_packetSize);
kodo_rlnc::decoder::factory decoderFactory (m_field,
m_generationSize, m_packetSize);

// Create encoder and disable systematic mode
m_encoder = encoderFactory.build ();
m_encoder->set_systematic_off ();
m_encoder = kodo_rlnc::encoder (m_field, m_generationSize, m_packetSize);
m_encoder.set_systematic_off ();

// Initialize the encoder data buffer
m_encoderBuffer.resize (m_encoder->block_size ());
m_encoder->set_const_symbols (storage::storage (m_encoderBuffer));
m_payload.resize (m_encoder->payload_size ());
m_encoderBuffer.resize (m_encoder.block_size ());
m_encoder.set_symbols_storage (m_encoderBuffer.data ());
m_payload.resize (m_encoder.max_payload_size ());

// Create decoders
m_decoderBuffers.resize (m_users);
for (uint32_t n = 0; n < m_users; n++)
{
auto decoder = decoderFactory.build ();
kodo_rlnc::decoder decoder (m_field, m_generationSize, m_packetSize);

// Add custom trace callback to each decoder
// Add custom log callback to each decoder
auto callback = [](const std::string& zone, const std::string& data)
{
std::set<std::string> filters =
{ "decoder_state", "symbol_coefficients_before_read_symbol" };
{ "decoder_state", "symbol_coefficients_before_consume_symbol" };
if (filters.count (zone))
{
std::cout << zone << ":" << std::endl;
std::cout << data << std::endl;
}
};
decoder->set_trace_callback (callback);
decoder.set_log_callback (callback);

// Create data buffer for the decoder
m_decoderBuffers[n].resize (decoder->block_size ());
decoder->set_mutable_symbols (storage::storage (m_decoderBuffers[n]));
m_decoderBuffers[n].resize (decoder.block_size ());
decoder.set_symbols_storage ( m_decoderBuffers[n].data ());

m_decoders.emplace_back (decoder);
}
Expand All @@ -93,7 +87,7 @@ class Broadcast

for (uint32_t n = 0; n < m_users; n++)
{
allDecoded = allDecoded && m_decoders[n]->is_complete ();
allDecoded = allDecoded && m_decoders[n].is_complete ();
}

if (!allDecoded)
Expand All @@ -102,7 +96,7 @@ class Broadcast
std::cout << "Sending coded packet: " << m_transmissionCount
<< std::endl;
std::cout << "------------------------" << std::endl;
uint32_t bytesUsed = m_encoder->write_payload (&m_payload[0]);
uint32_t bytesUsed = m_encoder.produce_payload (&m_payload[0]);
auto packet = ns3::Create<ns3::Packet> (&m_payload[0], bytesUsed);
socket->Send (packet);
m_transmissionCount++;
Expand All @@ -126,26 +120,25 @@ class Broadcast

std::cout << "Received a packet at Decoder " << n + 1 << std::endl;

std::vector<uint8_t> payload (m_decoders[n]->payload_size ());

// Pass the packet payload to the appropriate decoder
auto packet = socket->Recv ();
packet->CopyData (&payload[0], m_decoders[n]->payload_size ());
m_decoders[n]->read_payload (&payload[0]);
std::vector<uint8_t> payload (packet->GetSize ());
packet->CopyData (&payload[0], payload.size ());
m_decoders[n].consume_payload (&payload[0]);
}

private:

const fifi::api::field m_field;
const fifi::finite_field m_field;
const uint32_t m_users;
const uint32_t m_generationSize;
const uint32_t m_packetSize;

ns3::Ptr<ns3::Socket> m_source;
std::vector<ns3::Ptr<ns3::Socket>> m_sinks;
std::shared_ptr<kodo_rlnc::encoder> m_encoder;
kodo_rlnc::encoder m_encoder;
std::vector<uint8_t> m_encoderBuffer;
std::vector<std::shared_ptr<kodo_rlnc::decoder>> m_decoders;
std::vector<kodo_rlnc::decoder> m_decoders;
std::vector<std::vector<uint8_t>> m_decoderBuffers;

std::vector<uint8_t> m_payload;
Expand Down
8 changes: 4 additions & 4 deletions examples/kodo-recoders.cc
Expand Up @@ -117,10 +117,10 @@ int main (int argc, char *argv[])
double transmitProbability = 0.5; // Transmit probability for the recoders

// Create a map for the field values
std::map<std::string, fifi::api::field> fieldMap;
fieldMap["binary"] = fifi::api::field::binary;
fieldMap["binary4"] = fifi::api::field::binary4;
fieldMap["binary8"] = fifi::api::field::binary8;
std::map<std::string, fifi::finite_field> fieldMap;
fieldMap["binary"] = fifi::finite_field::binary;
fieldMap["binary4"] = fifi::finite_field::binary4;
fieldMap["binary8"] = fifi::finite_field::binary8;

Time interPacketInterval = Seconds (interval);

Expand Down

0 comments on commit 7f91ec0

Please sign in to comment.