Skip to content

Commit

Permalink
support visualizing simulated network with dot
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Aug 5, 2015
1 parent 8ea2b3d commit b160ae7
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 5 deletions.
39 changes: 38 additions & 1 deletion include/simulator/simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All rights reserved.
#include <boost/function.hpp>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <functional>
Expand All @@ -49,6 +50,11 @@ namespace sim
struct sink
{
virtual void incoming_packet(aux::packet p) = 0;

// used for visualization
virtual std::string label() const = 0;

virtual std::string attributes() const { return "shape=box"; }
};

// this represents a network route (a series of sinks to pass a packet
Expand Down Expand Up @@ -83,6 +89,8 @@ namespace sim
{ hops.insert(hops.end(), r.hops.begin(), r.hops.end()); }
void append(std::shared_ptr<sink> s) { hops.push_back(s); }
bool empty() const { return hops.empty(); }
std::shared_ptr<sink> last() const
{ return hops.back(); }


private:
Expand Down Expand Up @@ -503,6 +511,8 @@ namespace sim

// implements sink
virtual void incoming_packet(aux::packet p) override final;
virtual std::string label() const override final
{ return m_bound_to.address().to_string(); }

void async_receive_from_impl(std::vector<asio::mutable_buffer> const& bufs
, udp::endpoint* sender
Expand Down Expand Up @@ -709,6 +719,8 @@ namespace sim

// implements sink
virtual void incoming_packet(aux::packet p) override;
virtual std::string label() const override final
{ return m_bound_to.address().to_string(); }

void internal_connect(tcp::endpoint const& bind_ip
, std::shared_ptr<aux::channel> const& c
Expand Down Expand Up @@ -901,6 +913,14 @@ namespace sim

io_service(sim::simulation& sim, ip::address const& ip);
io_service();
~io_service();

// not copyable and non movable (it's not movable because we currently
// keep pointers to the io_service instances in the simulator object)
io_service(io_service const&) = delete;
io_service(io_service&&) = delete;
io_service& operator=(io_service const&) = delete;
io_service& operator=(io_service&&) = delete;

std::size_t run(boost::system::error_code& ec);
std::size_t run();
Expand Down Expand Up @@ -947,6 +967,7 @@ namespace sim
{ return m_incoming_route; }

int get_path_mtu(asio::ip::address ip) const;
ip::address get_ip() const { return m_ip; }

private:

Expand Down Expand Up @@ -1064,6 +1085,10 @@ namespace sim

configuration& config() const { return m_config; }

void add_io_service(asio::io_service* ios);
void remove_io_service(asio::io_service* ios);
std::vector<asio::io_service*> get_all_io_services() const;

private:
struct timer_compare
{
Expand All @@ -1074,6 +1099,9 @@ namespace sim

configuration& m_config;

// these are the io services that represent nodes on the network
std::unordered_set<asio::io_service*> m_nodes;

// all non-expired timers
typedef std::multiset<asio::high_resolution_timer*, timer_compare> timer_queue_t;
timer_queue_t m_timer_queue;
Expand Down Expand Up @@ -1160,6 +1188,9 @@ namespace sim
m_dst->incoming_packet(std::move(p));
}

virtual std::string label() const override final
{ return m_dst ? m_dst->label() : ""; }

void clear() { m_dst = nullptr; }

private:
Expand Down Expand Up @@ -1202,10 +1233,12 @@ namespace sim
{
queue(asio::io_service& ios, int bandwidth
, chrono::high_resolution_clock::duration propagation_delay
, int max_queue_size);
, int max_queue_size, std::string name = "queue");

virtual void incoming_packet(aux::packet p) override final;

virtual std::string label() const override final;

private:

void begin_send_next_packet();
Expand All @@ -1226,12 +1259,16 @@ namespace sim
// the number of bytes currently in the packet queue
int m_queue_size;

std::string m_node_name;

// this is the queue of packets and the time each packet was enqueued
std::vector<std::pair<chrono::high_resolution_clock::time_point, aux::packet>> m_queue;
asio::high_resolution_timer m_forward_timer;

chrono::high_resolution_clock::time_point m_last_forward;
};

void dump_network_graph(simulation const& s, std::string filename);
}

#endif // SIMULATOR_HPP_INCLUDED
Expand Down
6 changes: 3 additions & 3 deletions src/default_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace sim {
// 0 bandwidth and 0 queue means infinite. The network itself only adds
// 50 ms latency
m_network = std::make_shared<queue>(std::ref(sim.get_io_service())
, 0, duration_cast<duration>(milliseconds(30)), 0);
, 0, duration_cast<duration>(milliseconds(30)), 0, "network");
m_sim = &sim;
}

Expand All @@ -49,7 +49,7 @@ namespace sim {
if (it != m_incoming.end()) return route(it->second);
it = m_incoming.insert(it, std::make_pair(ip, std::make_shared<queue>(
std::ref(m_sim->get_io_service()), 800 * 1000
, duration_cast<duration>(milliseconds(1)), 200 * 1000)));
, duration_cast<duration>(milliseconds(1)), 200 * 1000, "DSL modem in")));
return route(it->second);
}

Expand All @@ -68,7 +68,7 @@ namespace sim {
if (it != m_outgoing.end()) return route(it->second);
it = m_outgoing.insert(it, std::make_pair(ip, std::make_shared<queue>(
std::ref(m_sim->get_io_service()), 200 * 1000
, duration_cast<duration>(milliseconds(1)), 200 * 1000 )));
, duration_cast<duration>(milliseconds(1)), 200 * 1000, "DSL modem out")));
return route(it->second);
}

Expand Down
6 changes: 6 additions & 0 deletions src/io_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ namespace sim { namespace asio {
{
m_outgoing_route = m_sim.config().outgoing_route(ip);
m_incoming_route = m_sim.config().incoming_route(ip);
m_sim.add_io_service(this);
}

io_service::~io_service()
{
m_sim.remove_io_service(this);
}

io_service::io_service()
Expand Down
30 changes: 29 additions & 1 deletion src/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,43 @@ namespace sim
queue::queue(asio::io_service& ios
, int bandwidth
, chrono::high_resolution_clock::duration propagation_delay
, int max_queue_size)
, int max_queue_size
, std::string name)
: m_max_queue_size(max_queue_size)
, m_forwarding_latency(propagation_delay)
, m_bandwidth(bandwidth)
, m_queue_size(0)
, m_node_name(name)
, m_forward_timer(ios)
, m_last_forward(chrono::high_resolution_clock::now())
{}

std::string queue::label() const
{
char ret[400];
int p = snprintf(ret, sizeof(ret), "%s\n", m_node_name.c_str());

if (m_bandwidth != 0)
{
p += snprintf(ret + p, sizeof(ret) - p, "rate: %d kB/s\n"
, m_bandwidth / 1000);
}

if (m_queue_size != 0)
{
p += snprintf(ret + p, sizeof(ret) - p, "queue: %d kB\n"
, m_queue_size / 1000);
}

if (m_forwarding_latency.count() != 0)
{
p += snprintf(ret + p, sizeof(ret) - p, "latency: %d ms\n"
, int(chrono::duration_cast<chrono::milliseconds>(m_forwarding_latency).count()));
}

return ret;
}

void queue::incoming_packet(aux::packet p)
{
const int packet_size = p.buffer.size() + p.overhead;
Expand Down
23 changes: 23 additions & 0 deletions src/simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,28 @@ namespace sim
return network_route;
}

void simulation::add_io_service(asio::io_service* ios)
{
bool added = m_nodes.insert(ios).second;
assert(added);
}

void simulation::remove_io_service(asio::io_service* ios)
{
auto it = m_nodes.find(ios);
assert(it != m_nodes.end());
m_nodes.erase(it);
}

std::vector<io_service*> simulation::get_all_io_services() const
{
std::vector<io_service*> ret;
ret.reserve(m_nodes.size());
std::remove_copy_if(
m_nodes.begin(), m_nodes.end(), std::back_inserter(ret)
, [](io_service* ios) { return ios->get_ip() == asio::ip::address(); });
return ret;
}

}

0 comments on commit b160ae7

Please sign in to comment.