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 )
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 source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#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,54 +110,40 @@ void Graph::GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances)
}
}
int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arityDistrib,
double* bcArity, int nRefresh, int round)
routesResult Graph::GetRouteResult(int node, int nRefresh, double* bc)
{
int nUpdated = 0;
routesResult results[size];
double bc[size];
for(int i=0; i<size; i++)
bc[i] = 0;
avgDistance = 0;
double avgDistanceWeight = 0;
unreachable = 0;
for(int i=0; i<=maxPeers; i++)
{
bcArity[i] = 0;
arityDistrib[i] = 0;
}
for(int i=0; i<size; i++)
{
// Compute the routes
int nRoutes[size], prevs[size], distances[size];
GetRoutesFrom(i, nRoutes, prevs, distances);
GetRoutesFrom(node, nRoutes, prevs, distances);
if(bc != NULL)
for(int j=0; j<size; j++)
bc[j] += nRoutes[j];
// Get the values
routesResult r;
r.routesToDelete = 0;
for(int k=0; k<nRefresh; k++)
{
int mini = -1;
for(int j : generated[i])
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[i].size();
r.arity = adjacency[node].size();
r.avgDistance = 0;
r.unreachable = 0;
for(int j=0; j<size; j++)
{
if(distances[i] >= 0)
if(distances[j] >= 0)
r.avgDistance += distances[j];
else
r.unreachable++;
......@@ -166,9 +151,30 @@ int Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arit
r.avgDistance /= (double)(size - r.unreachable);
results[i] = r;
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];
double bc[size];
for(int i=0; i<size; i++)
bc[i] = 0;
avgDistance = 0;
double avgDistanceWeight = 0;
unreachable = 0;
for(int i=0; i<=maxPeers; i++)
{
bcArity[i] = 0;
arityDistrib[i] = 0;
}
for(int i=0; i<size; i++)
results[i] = GetRouteResult(i, nRefresh, bc);
for(int i = 0; i<size; i++)
{
routesResult r = results[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;
};
struct routesResult
{
double avgDistance;
int arity;
int unreachable;
stack<int> toDelete;
Latency* latency;
};
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