Commit 370585ed authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

Blacklist tunnel connected to us

Remove the refresh-rate option

Added new simulation results.
parent 43c83b2f
To be done :
Update the USAGE > OPTION > Tunnel & Peers options section of the re6stnet
man page ( about how tunnel options are treated ).
Do a 'real' test, on one ( or more ) real machine(s) preferably :
- package re6stnet
- install re6stnet
......@@ -29,4 +26,12 @@ To be done :
Put a section about how to build the package from the sources in the README
~~~ => Complete and upgrade the Routing with babel presentation (web page on tiolive.com/nexedi)
---------------------------------------------------------------------------------------------
We should put a high latency on the servers openvpn interfaces to avoid people staying connected to it.
Check that blacklisting for peers connected to us works
Check that if 2 tunnels are established between 2 peers, one of them is destroyed
Check peers ID when connectiong to the server
Choose peer DB size
......@@ -145,28 +145,14 @@ Tunnel & Peers options
--tunnel-refresh duration
Interval in seconds between two tunnel refresh. Refreshing tunnels
mean :
- killing all dead tunnels ( detected via the ping-exit option
if openvpn )
- killing the 'worst' tunnels, so that at least the ratio of
tunnels set by the --refresh-rate option have been killed
- creating new tunnels to other clients randomly choosen in the
peers database, to reach the number of connection specified by
the connection-count option ( There can be less tunnels if the
peers DB does not contain enough peers )
Default : 300
mean replace the worst tunnel if the number of tunnels has reach
its maximum number.
Default : 300
--connection-count number
The maximum number of openvpn clients to start.
The average number of connections per peer
Default : 20
--refresh-rate ratio
The ratio of connection to kill each time we refresh tunnels.
For more information see the --tunnel-refresh option
ratio should be a float between 0 and 1 ( included )
Default : 0.05
Openvpn-options
---------------
......@@ -286,7 +272,7 @@ Now you can restart your re6st-registry with two more options:
--key path_to_ca.key --mailhost yourmailhost --private 2001:db8:42:3::1
--bootstrap 0000000000000011``
Finally, you can start your own re6st node following the instrucxtions in the
Finally, you can start your own re6st node following the instructions in the
precedent section.
......
......@@ -51,7 +51,7 @@ class main(object):
parser = argparse.ArgumentParser(
description='Peer discovery http server for re6stnet')
_ = parser.add_argument
_('port', type=int, help='Port of the host server')
_('--port', required=True, type=int, help='Port of the host server')
_('--db', required=True,
help='Path to database file')
_('--ca', required=True,
......
import logging, sqlite3, socket, subprocess, xmlrpclib, time, os
import logging, sqlite3, socket, subprocess, xmlrpclib, time
import utils
class PeerManager:
# internal ip = temp arg/attribute
def __init__(self, db_path, registry, key_path, refresh_time, address,
internal_ip, prefix, manual, pp , db_size):
internal_ip, prefix, manual, pp, db_size):
self._refresh_time = refresh_time
self._address = address
self._internal_ip = internal_ip
......@@ -27,8 +28,8 @@ class PeerManager:
used INTEGER NOT NULL DEFAULT 0,
date INTEGER DEFAULT (strftime('%s', 'now')))""")
self._db.execute("UPDATE peers SET used = 0")
self._db.execute("CREATE INDEX IF NOT EXISTS
_peers_used ON peers(used)")
self._db.execute("""CREATE INDEX IF NOT EXISTS
_peers_used ON peers(used)""")
self._db.execute("""CREATE TABLE IF NOT EXISTS config (
name text primary key,
value text)""")
......@@ -159,8 +160,10 @@ class PeerManager:
def handle_message(self, msg):
script_type, arg = msg.split()
if script_type == 'client-connect':
self.blacklist(arg, 2)
logging.info('Incomming connection from %s' % (arg,))
elif script_type == 'client-disconnect':
self.whitelist(arg)
logging.info('%s has disconnected' % (arg,))
elif script_type == 'route-up':
if not self._manual:
......@@ -175,4 +178,3 @@ class PeerManager:
else:
logging.debug('Unknow message recieved from the openvpn pipe : %s'
% msg)
......@@ -71,7 +71,7 @@ class Connection:
class TunnelManager:
def __init__(self, write_pipe, peer_db, openvpn_args, hello_interval,
refresh, connection_count, refresh_count, iface_list, network):
refresh, connection_count, iface_list, network):
self._write_pipe = write_pipe
self._peer_db = peer_db
self._connection_dict = {}
......@@ -87,7 +87,7 @@ class TunnelManager:
self._next_tunnel_refresh = time.time()
self._client_count = (connection_count + 1) // 2
self._refresh_count = refresh_count
self._refresh_count = 1
self.free_interface_set = set('re6stnet' + str(i)
for i in xrange(1, self._client_count + 1))
......
......@@ -73,9 +73,6 @@ def getConfig():
help='Path to the private key file')
_('--connection-count', default=20, type=int,
help='Number of tunnels')
_('--refresh-count', default=1, type=int,
help='''The number of connections to drop when refreshing the
connections''')
_('--tunnel-refresh', default=300, type=int,
help='time (seconds) to wait before changing the connections')
......@@ -142,7 +139,7 @@ def main():
manual, config.pp, 200)
tunnel_manager = tunnel.TunnelManager(write_pipe, peer_db, openvpn_args,
config.hello, config.tunnel_refresh, config.connection_count,
config.refresh_count, config.iface_list, network)
config.iface_list, network)
# Launch routing protocol. WARNING : you have to be root to start babeld
interface_list = list(tunnel_manager.free_interface_set) \
......
import matplotlib.pyplot as plt
max_peers = 30
nFiles = 2
nRounds = 3000
file_names = ['out_%s.csv' % i for i in range(nFiles)]
distance = [0] * nRounds
arity = [[0] * 31 for i in range(nRounds)]
for file_name in file_names:
# open the file
f = open(file_name, 'r')
lines = f.read().split('\n')
for line in lines:
vals = line.split(',')
if len(vals) < 2:
continue
i = int(vals[0])
if i >= nRounds:
continue
distance[i] += float(vals[1])
for j in range(0, 31):
arity[i][j] += float(vals[j + 2])
for i in range(0, nRounds):
distance[i] = distance[i] / len(file_names)
for j in range(0, 31):
arity[i][j] = arity[i][j] / len(file_names)
plt.plot(range(31), arity[1], range(31), arity[nRounds - 1])
plt.legend(('Random network', 'After %s iterations' % nRounds))
plt.xlabel('Arity')
plt.ylabel('Ratio of node')
plt.axis([10, 30, 0, 0.4])
#plt.xscale('log')
plt.show()
This diff is collapsed.
This diff is collapsed.
#include "main.h"
Graph::Graph(int size, int k, int maxPeers, mt19937& rng, const Latency& latency) :
Graph::Graph(int size, int k, int maxPeers, mt19937& rng, Latency* latency) :
generator(mt19937(rng())), size(size), k(k), maxPeers(maxPeers), latency(latency),
distrib(uniform_int_distribution<int>(0, size-1))
{
......@@ -11,8 +11,8 @@ Graph::Graph(int size, int k, int maxPeers, mt19937& rng, const Latency& latenc
SaturateNode(i);
}
Graph::Graph(const Graph& g) :
generator(g.generator), size(g.size), k(g.k), maxPeers(g.maxPeers), latency(latency),
Graph::Graph(Graph& g) :
generator(mt19937(g.generator())), size(g.size), k(g.k), maxPeers(g.maxPeers), latency(g.latency),
distrib(g.distrib)
{
adjacency = new unordered_set<int>[size];
......@@ -38,7 +38,7 @@ bool Graph::AddEdge(int from)
to = distrib(generator);
if( to != from
&& latency.values[from][to] > 0
&& latency->values[from][to] > 0
&& adjacency[from].count(to) == 0
&& adjacency[to].size() + k < maxPeers + generated[to].size())
{
......@@ -88,7 +88,7 @@ void Graph::GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances)
order.push(node);
for(int neighbor : adjacency[node])
{
int neighborDist = d + latency.values[neighbor][node];
int neighborDist = d + latency->values[neighbor][node];
if(distances[neighbor] == -1 || distances[neighbor] > neighborDist)
{
......@@ -101,7 +101,6 @@ void Graph::GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances)
}
// get the BC
// The error is here
while(!order.empty())
{
int node = order.top();
......@@ -111,9 +110,52 @@ void Graph::GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances)
}
}
routesResult Graph::GetRouteResult(int node, int nRefresh, double* bc)
{
int nRoutes[size], prevs[size], distances[size];
GetRoutesFrom(node, nRoutes, prevs, distances);
if(bc != NULL)
for(int j=0; j<size; j++)
bc[j] += nRoutes[j];
routesResult r;
r.routesToDelete = 0;
for(int k=0; k<nRefresh; k++)
{
int mini = -1;
for(int j : generated[node])
if(mini == -1 || nRoutes[mini] > nRoutes[j])
mini = j;
if(mini != -1)
{
r.toDelete.push(mini);
r.routesToDelete += nRoutes[mini];
}
}
r.arity = adjacency[node].size();
r.avgDistance = 0;
r.unreachable = 0;
for(int j=0; j<size; j++)
{
if(distances[j] >= 0)
r.avgDistance += distances[j];
else
r.unreachable++;
}
int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arityDistrib,
double* bcArity, int nRefresh, int round)
r.avgDistance /= (double)(size - r.unreachable);
return r;
}
int Graph::UpdateLowRoutes(double& avgDistance, double& unreachable, double& nRoutesKilled,
double* arityDistrib, double* bcArity, int nRefresh, int round)
{
int nUpdated = 0;
routesResult results[size];
......@@ -131,43 +173,7 @@ int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arit
}
for(int i=0; i<size; i++)
{
// Compute the routes
int nRoutes[size], prevs[size], distances[size];
GetRoutesFrom(i, nRoutes, prevs, distances);
for(int j=0; j<size; j++)
bc[j] += nRoutes[j];
// Get the values
routesResult r;
for(int k=0; k<nRefresh; k++)
{
int mini = -1;
for(int j : generated[i])
if(mini == -1 || nRoutes[mini] > nRoutes[j])
mini = j;
if(mini != -1)
r.toDelete.push(mini);
}
r.arity = adjacency[i].size();
r.avgDistance = 0;
r.unreachable = 0;
for(int j=0; j<size; j++)
{
if(distances[i] >= 0)
r.avgDistance += distances[j];
else
r.unreachable++;
}
r.avgDistance /= (double)(size - r.unreachable);
results[i] = r;
}
results[i] = GetRouteResult(i, nRefresh, bc);
for(int i = 0; i<size; i++)
{
......@@ -184,6 +190,7 @@ int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arit
avgDistance += r.avgDistance*(size-r.unreachable);
avgDistanceWeight += size-r.unreachable;
unreachable += r.unreachable;
nRoutesKilled += r.routesToDelete;
arityDistrib[adjacency[i].size()]++;
bcArity[adjacency[i].size()] += bc[i] - 2*size + 1;
}
......@@ -199,6 +206,71 @@ int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arit
return nUpdated;
}
pair<double, double> Graph::UpdateLowRoutesArity(int arityToUpdate)
{
// Update
routesResult results[size];
double nRoutesDeleted = 0;
double avgDist = 0;
for(int i=0; i<size; i++)
if(adjacency[i].size() == arityToUpdate || adjacency[i].size() < k)
results[i] = GetRouteResult(i, 1, NULL);
for(int i=0; i<size; i++)
if(results[i].toDelete.size() > 0)
{
routesResult r = results[i];
while(!r.toDelete.empty())
{
RemoveEdge(i, r.toDelete.top());
r.toDelete.pop();
}
nRoutesDeleted += r.routesToDelete;
SaturateNode(i);
}
// Get the distance
int distances[size];
for(int from=0; from<size; from++)
{
for(int i=0; i<size; i++)
distances[i] = -1;
distances[from] = 0;
priority_queue<pair<int, int>> remainingNodes;
remainingNodes.push(pair<int, int>(-0, from));
// Get the order
while(!remainingNodes.empty())
{
pair<int, int> p = remainingNodes.top();
int node = p.second;
int d = -p.first;
remainingNodes.pop();
if(d == distances[node])
for(int neighbor : adjacency[node])
{
int neighborDist = d + latency->values[neighbor][node];
if(distances[neighbor] == -1 || distances[neighbor] > neighborDist)
{
distances[neighbor] = neighborDist;
remainingNodes.push(pair<int, int>(-neighborDist, neighbor));
}
}
}
for(int i=0; i<size; i++)
avgDist += distances[i];
}
return pair<double, double>(avgDist/(size*size), nRoutesDeleted);
}
int Graph::CountUnreachableFrom(int node)
{
bool accessibility[size];
......@@ -256,17 +328,40 @@ void Graph::KillMachines(float proportion)
}
}
void Graph::Reboot(double proba)
void Graph::Reboot(double proba, int round)
{
uniform_real_distribution<double> d(0.0, 1.0);
for(int i=0; i<size; i++)
if(d(generator) <= proba)
{
for(int j : generated[i])
stack<int> toSaturate;
unordered_set<int> generated_cpy(generated[i]);
for(int j : generated_cpy)
RemoveEdge(i, j);
for(int j : adjacency[i])
unordered_set<int> adjacency_cpy(adjacency[i]);
for(int j : adjacency_cpy)
{
toSaturate.push(j);
RemoveEdge(j, i);
}
SaturateNode(i);
while(!toSaturate.empty())
{
SaturateNode(toSaturate.top());
toSaturate.pop();
}
}
}
void Graph::GetArity(int* arity)
{
for(int a=0; a<=maxPeers; a++)
arity[a] = 0;
for(int i=0; i<size; i++)
arity[adjacency[i].size()]++;
}
\ No newline at end of file
......@@ -7,12 +7,13 @@
#include "main.h"
void simulate(int size, int k, int maxPeer, int seed, const Latency& latency, const char* outName)
void simulate(int size, int k, int maxPeer, int seed, Latency* latency, const char* outName)
{
mt19937 rng(seed);
FILE* output = fopen(outName, "wt");
int fno = fileno(output);
double nRoutesKilled = 0;
Graph graph(size, k, maxPeer, rng, latency);
......@@ -33,10 +34,10 @@ void simulate(int size, int k, int maxPeer, int seed, const Latency& latency, co
double avgDistance, unreachable;
double arityDistrib[31], bcArity[31];
graph.Reboot(1.0/(1036.8 + 1.0));
graph.UpdateLowRoutes(avgDistance, unreachable, arityDistrib, bcArity, 1, i);
graph.Reboot(1.0/(100 + 1.0), i);
graph.UpdateLowRoutes(avgDistance, unreachable, nRoutesKilled, arityDistrib, bcArity, 1, i);
fprintf(output, "%d,%f", i, avgDistance);
fprintf(output, "%d,%f,%f", i, avgDistance, nRoutesKilled);
for(int j=0; j<=30; j++)
fprintf(output, ",%f", arityDistrib[j]);
for(int j=0; j<=30; j++)
......@@ -53,28 +54,157 @@ void simulate(int size, int k, int maxPeer, int seed, const Latency& latency, co
fclose(output);
}
void testOptimized(int size, int k, int maxPeer, int seed, Latency* latency, const char* outName)
{
cout << "\r" << 0 << "/" << 3000;
cout.flush();
FILE* output = fopen(outName, "wt");
int fno = fileno(output);
FILE* input = fopen("update_order", "r");
mt19937 rng(seed);
Graph graph(size, k, maxPeer, rng, latency);
double nRoutesKilled = 0;
int arityDistrib[maxPeer+1];
for(int i=0; i<3000; i++)
{
int toUpdate;
fscanf(input, "%d", &toUpdate);
pair<double, double> result = graph.UpdateLowRoutesArity(toUpdate);
nRoutesKilled += result.second;
graph.GetArity(arityDistrib);
fprintf(output, "%d,%f,%d,%f,A", i, result.first, toUpdate, nRoutesKilled);
for(int a=k; a<=maxPeer; a++)
fprintf(output, ",%d", arityDistrib[a]);
fprintf(output, "\n");
fflush(output);
fsync(fno);
cout << "\r" << i+1 << "/" << 3000;
cout.flush();
}
cout << endl;
fclose(output);
fclose(input);
}
void Optimize(int size, int k, int maxPeer, int seed, Latency* latency, const char* outName)
{
cout << "\r" << 0 << "/" << 3000;
cout.flush();
FILE* output = fopen(outName, "wt");
int fno = fileno(output);
mt19937 rng(seed);
Graph* graph = new Graph(size, k, maxPeer, rng, latency);
int range = maxPeer - k + 1;
int updates[range];
for(int i = 0; i<range; i++)
updates[i] = 0;
pair<double, double> results[range];
Graph* copies[range];
double oldDistance = numeric_limits<double>::infinity();
double nRoutesKilled = 0;
int arityDistrib[maxPeer+1];
//graph.Reboot(1.0/(100 + 1.0), i);
for(int i=0; i<3000; i++)
{
vector<future<pair<double, double>>> threads;
for(int a=0; a<range; a++)
{
copies[a] = new Graph(*graph);
auto lambda = [] (Graph *g, int a, int k) { return g->UpdateLowRoutesArity(a + k); };
threads.push_back(async(launch::async, lambda, copies[a], a, k));
}
int minIndice = 0;
double minValue = numeric_limits<double>::infinity();
for(int a=0; a<range; a++)
{
results[a] = threads[a].get();
if(results[a].second > 0)
{
double val = (results[a].first - oldDistance)/results[a].second;
if(val < minValue)
{
minIndice = a;
minValue = val;
}
}
}
swap(graph,copies[minIndice]);
for(int a=0; a<range; a++)
delete copies[a];
updates[minIndice]++;
oldDistance = results[minIndice].first;
nRoutesKilled += results[minIndice].second;
graph->GetArity(arityDistrib);
fprintf(output, "%d,%f,%f,U", i, oldDistance, nRoutesKilled);
for(int a=0; a<range; a++)
fprintf(output, ",%d", updates[a]);
fprintf(output, ",A");
for(int a=0; a<range; a++)
fprintf(output, ",%d", arityDistrib[a+k]);
fprintf(output, "\n");
fflush(output);
fsync(fno);
cout << "\r" << i+1 << "/" << 3000;cout.flush();
}
delete graph;
cout << endl;
}
int main(int argc, char** argv)
{
mt19937 rng(time(NULL));
//Latency latencyR("latency/pw-1715/pw-1715-latencies", 1715);
//latencyR.Rewrite(20);
Latency latency("datasets/latency_2_2500", 2500);
Latency* latency = new Latency("datasets/latency_2_2500", 2500);
//cout << "Optimal distance : " << latency->GetAverageDistance() << endl;
//cout << "Average ping : " << latency->GetAveragePing() << endl;
//cout << "Optimal distance : " << latency.GetAverageDistance() << endl;
//cout << "Average ping : " << latency.GetAveragePing() << endl;
vector<future<void>> threads;
for(int i=0; i<1; i++)
{
int seed = rng();
char* out = new char[20];
sprintf(out, "out_%d.csv", i);
threads.push_back(async(launch::async, [seed, out, &latency]()
{ simulate(2500, 10, 30, seed, latency, out); delete[] out; }));
char* out = new char[100];
sprintf(out, "test_optimized_%d.csv", i);
threads.push_back(async(launch::async, [seed, out, latency]()
{ testOptimized(2500, 10, 30, seed, latency, out); delete[] out; }));
}
for(int i=0; i<1; i++)
for(int i=0; i<4; i++)
threads[i].get();
//Optimize(2500, 10, 30, rng(), latency, "out.csv");
delete latency;
return 0;
}
......@@ -11,6 +11,14 @@
using namespace std;
struct routesResult
{
double avgDistance;
int arity;
int unreachable;
int routesToDelete;
stack<int> toDelete;
};
class Latency
{
......@@ -29,13 +37,15 @@ private:
class Graph
{
public:
Graph(int size, int k, int maxPeers, mt19937& generator, const Latency& latency);
Graph(const Graph& g);
~Graph() { delete[] adjacency; delete[] generated; };
int UpdateLowRoutes(double& avgDistance, double unreachable, double* arityDistrib, double* bcArity, int nRefresh, int round);
Graph(int size, int k, int maxPeers, mt19937& generator, Latency* latency);
Graph(Graph& g);
~Graph() { delete[] adjacency; delete[] generated;};
int UpdateLowRoutes(double& avgDistance, double& unreachable, double& nRoutesKilled, double* arityDistrib, double* bcArity, int nRefresh, int round);
double GetUnAvalaibility();
void Reboot(double proba);
void Reboot(double proba, int round);
void KillMachines(float proportion);
pair<double, double> UpdateLowRoutesArity(int arityToUpdate);
void GetArity(int* arity);
private:
void SaturateNode(int node);
......@@ -43,6 +53,7 @@ private:
void RemoveEdge(int from, int to);
void GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances);
int CountUnreachableFrom(int node);
routesResult GetRouteResult(int node, int nRefresh, double* bc);
mt19937 generator;
uniform_int_distribution<int> distrib;
......@@ -52,13 +63,5 @@ private:
unordered_set<int>* adjacency;
unordered_set<int>* generated;
const Latency& latency;
Latency* latency;
};
struct routesResult
{
double avgDistance;
int arity;
int unreachable;
stack<int> toDelete;
};
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment