import networkx
import random
import tempfile
+import os
+import time
+import matplotlib.pyplot as plt
+from subprocess import Popen, PIPE, STDOUT
+
+node_colors = None
+graph = None
+pos = None
def get_args():
parser = argparse.ArgumentParser(description="Sensor profiler")
parser.add_argument('-p', '--peers', action='store', type=int, required=True,
help='Number of peers to run')
+ parser.add_argument('-l', '--links', action='store', type=int, required=False,
+ help='Number of links to create')
+ parser.add_argument('-i', '--sensors-interval', action='store', type=int,
+ required=False,
+ help='Change the interval of running sensors to given value')
+ parser.add_argument('-a', '--anomalous-peers', action='store', type=int,
+ required=True,
+ help='Number of peers to simulate anomalies on')
return parser.parse_args()
def generate_topology(peers, links):
- G = networkx.empty_graph(peers)
+ global graph
+ global node_colors
+ global pos
+ graph = networkx.empty_graph(peers)
for i in range(0, links):
a = 0
b = 0
while a == b:
- a = random.randint(0, peers)
- b = random.randint(0, peers)
- G.add_edge(a, b)
- return G
+ a = random.randint(0, peers - 1)
+ b = random.randint(0, peers - 1)
+ graph.add_edge(a, b)
+ node_colors = [0] * peers
+ pos = networkx.layout.spring_layout(graph)
-def create_topology_file(graph):
+def create_topology_file():
+ global graph
nodes = list()
for i in range(len(graph.edge)):
nodes.append(list())
if len(nodes[i]) == 0:
continue
f.write('%d:' % i)
- f.write('|'.join(map(str,nodes[i])))
+ f.write('|'.join(map(str, nodes[i])))
f.write('\n')
- #f.close()
+ # f.close()
return f.name
+def draw_graph():
+ global graph
+ global node_colors
+ global pos
+ t = int(time.time())
+ inc = 2
+ name = str(t) + '.png'
+ while os.path.exists(name):
+ name = '%d(%d).png' % (t, inc)
+ inc += 1
+ print 'Drawing graph to file: %s' % name
+ plt.clf()
+ anomaly_lbls = {}
+ for i in range(len(graph.node)):
+ if node_colors[i] >= 1:
+ anomaly_lbls[i] = '\n\n\n' + str(node_colors[i] - 1)
+ networkx.draw(graph, pos=pos, node_color=node_colors, with_labels=range(len(graph.node)), cmap=plt.cm.Reds, vmin=0, vmax=2)
+ networkx.draw_networkx_labels(graph, pos, anomaly_lbls)
+ plt.savefig(name)
+
+def peers_reconnected(p1, p2):
+ global graph
+ if p2 in graph[p1]:
+ print 'Link already exists'
+ return
+ graph.add_edge(p1, p2)
+ draw_graph()
+
+def peers_disconnected(p1, p2):
+ global graph
+ print 'Disconnected peers %d and %d' % (p1, p2)
+ if p2 not in graph[p1]:
+ print 'Link does not exist'
+ return
+ graph.remove_edge(p1, p2)
+ draw_graph()
+
+def anomaly_report(report):
+ global node_colors
+ if 0 == report['anomalous']:
+ node_colors[report['peer']] = 0
+ else:
+ clr = 1 + report['neighbors']
+ if node_colors[report['peer']] >= clr:
+ return
+ node_colors[report['peer']] = clr
+ draw_graph()
+
+def handle_profiler_line(line):
+ if not line:
+ return
+ print line
+ if 'Peer disconnection request sent' in line: # Peers disconnected
+ parts = line.split(':')
+ peers = parts[-1].split(',')
+ peers_disconnected(int(peers[0]), int(peers[1]))
+ return
+ if 'Anomaly report:' in line:
+ parts = line.split('Anomaly report:')
+ anomaly_report(eval(parts[1]))
+ return
+ if 'Peer connection request sent' in line: # Peers reconnected
+ parts = line.split(':')
+ peers = parts[-1].split(',')
+ peers_reconnected(int(peers[0]), int(peers[1]))
+
+def run_profiler(peers, topology_file, sensors_interval, anomalous_peers):
+ cmd1 = "./gnunet-sensor-profiler -p %d -t %s -a %d" % (peers, topology_file, anomalous_peers)
+ if sensors_interval:
+ cmd1 += " -i %d" % sensors_interval
+ cmd2 = "> log 2>&1"
+ cmd = "%s %s" % (cmd1, cmd2)
+ print cmd
+ process = Popen([cmd], shell=True)
+ time.sleep(0.5)
+ line = ''
+ f = open('log')
+ while process.poll() is None:
+ for c in f.read():
+ if not c or c == '\n':
+ handle_profiler_line(line)
+ line = ''
+ else:
+ line += c
+
def main():
args = vars(get_args())
num_peers = args['peers']
if num_peers < 3:
print 'Min number of peers is 3'
return
- num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
+ sensors_interval = None
+ if 'sensors_interval' in args:
+ sensors_interval = args['sensors_interval']
+ if 'links' in args:
+ num_links = args['links']
+ else:
+ #num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
+ num_links = int(math.log(num_peers) * num_peers)
# Generate random topology
- graph = generate_topology(num_peers, num_links)
+ generate_topology(num_peers, num_links)
print 'Generated random topology with %d peers and %d links' % (num_peers, num_links)
+ # Create a file with links to cut to split the topology into two
# Create TESTBED topology file
- top_file = create_topology_file(graph)
+ top_file = create_topology_file()
print 'Created TESTBED topology file %s' % top_file
+ draw_graph()
# Run c profiler
+ if os.path.isfile('log'):
+ os.remove('log')
+ run_profiler(num_peers, top_file, sensors_interval, args['anomalous_peers'])
if __name__ == "__main__":
main()