diff --git a/.gitignore b/.gitignore index 5207069..23b7a04 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ Versuch\ 3/.venv/ +*.pcap diff --git a/README.md b/README.md index 11edfb5..980df17 100644 --- a/README.md +++ b/README.md @@ -110,19 +110,79 @@ ntpq time1.rrzn.uni-hannover.de ### Streaming über das drahtgebundene Netz -- Mittelwert = sum(i)/n = x -- Varianz = sum((i - x)^2)/n -- Std.Abw = root(Varianz) +- Segmentation offloading ausschalten + +```bash +ethtool -K tso off +``` + +- tcpdump starten auf Client und Server + - als root +- Auf dem Client + +```bash +tcpdump -i tcp and port 1337 and dst -r +``` + +- Auf dem Server + +```bash +tcpdump -i tcp and port 1337 and src -r +``` + +- simple-server.py und simple-client.py verwenden + - Client auf dem PI + - Server auf dem Laptop + +```bash +./simple-server.py -a --tcp +./simple-client.py -s --tcp +``` + +- Commulative arrival function für Server und Client berechnen und ploten + - Für später schon Bitraten notieren + +```bash +./plot-pcap.py --client --server +``` + +- OWDs berechnen + +```bash +./calc-owd.py --client --server +``` + +- Mittelwert: +- Varianz: +- Standardabweichung: - Eingestellte Bitrate: - Tatsächlich gesendete Bitrate: ### Streaming über WLAN +- default route über WLan einrichten + #### Plot TCP +- Stream für 60s mitschneiden und auswerten + - Wie vorher schon nur über WLan + - Plot der Pakete + - OWDS + +- Mittelwert: +- Varianz: +- Standardabweichung: + #### Plot UDP +- Mittelwert: +- Varianz: +- Standardabweichung: + + +- Was ist besser? + #### Mittelwert und Standardabweichung der OWDs - TCP: @@ -134,3 +194,29 @@ ntpq time1.rrzn.uni-hannover.de - Um OWDs mit UDP genauer zu berechnen müsste die Reihenfolge der Pakete beachtet werden und die Uhren von Client und Server genaustens synkronisiert werden. +#### Verschiedene Bitraten + +- Hier wieder OWDs messen + +- Für LAN + +- Für WLAN + +#### Verschiedene Parameter raspivid + +- Hier wieder OWDs messen + +#### Verschiedene Puffergrößen + +- Einmal mit 10Byte und 1400 Byte (WLan MTU) +- Was passiert, wenn die Puffergröße größer als tie MTU + - Fragmentierung, mehr Overhead +- Mit 4000B Puffergröße versuchen + - Mit Wireshark angucken + +### Streaming am Fahrzeug + +- Ploten der Pakete in einer Abbildung (wie vorher) + - Wenn das Modellauto sich stetig vom Router entfernt. + - Wenn das Modellauto den Raum verlässt. +- Was kann in beiden Fällen beobachtet werden? diff --git a/Versuchstag-3/calc-owd.py b/Versuchstag-3/calc-owd.py new file mode 100755 index 0000000..ea88a0e --- /dev/null +++ b/Versuchstag-3/calc-owd.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import argparse +import os +import sys +import math + +from scapy.all import * + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Plot two PCAP files') + parser.add_argument('--client', metavar='', help='pcap file to parse', required=True) + parser.add_argument('--server', metavar='', help='pcap file to parse', required=True) + args = parser.parse_args() + + if not os.path.isfile(args.server): + print('"{}" does not exist'.format(args.server), file=sys.stderr) + sys.exit(-1) + if not os.path.isfile(args.client): + print('"{}" does not exist'.format(args.client), file=sys.stderr) + sys.exit(-1) + + # calc owd + packets_send = rdpcap(args.client) + packets_rec = rdpcap(args.server) + + # check len + PACKAGES = 4000 + if (not len(packets_send) >= PACKAGES) or (not len(packets_rec) >= PACKAGES): + print("Nicht genug Pakete!") + exit() + + owds = [] + for i in range(0, PACKAGES): + owd = packets_rec[i].time - packets_send[i].time + owds.append(owd) + + mittwelwert = sum(owds) / len(owds) + varianz = 0 + for owd in owds: + varianz = varianz + (owd - mittwelwert)**2 + varianz = varianz / len(owds) + stdabw = math.sqrt(varianz) + + print("Mittelwert: " + str(mittwelwert)) + print("Varianz: " + str(varianz)) + print("Standardabweichung: " + str(stdabw)) diff --git a/Versuchstag-3/plot-pcap.py b/Versuchstag-3/plot-pcap.py new file mode 100755 index 0000000..d249c3c --- /dev/null +++ b/Versuchstag-3/plot-pcap.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import argparse +import os +import sys + +from scapy.all import * +import matplotlib.pyplot as plt + +def process_pcap(file_name): + print('Opening {}...'.format(file_name)) + + x_axis_time = [0] + y_axis_com_data = [0] + + # Get times + packets = rdpcap(file_name) + for pkt in packets: + x_axis_time.append(pkt.time) + time_start = x_axis_time[1] + time_end = x_axis_time[-1] + # format time axis + for i in range(1, len(x_axis_time)): + x_axis_time[i] = x_axis_time[i] - time_start + + # get payloads + pcap_file = RawPcapReader(file_name) + for (pkt_data, pkt_metadata,) in pcap_file: + y_axis_com_data.append(y_axis_com_data[-1] + pkt_metadata.wirelen) + + print('{} contains {} packets.\nStart time: {}\tEnd time: {}\t Transfered: {}kB\tDuration: {}'.format(file_name, len(packets), time_start, time_end, (y_axis_com_data[-1] / 8) / 1000, time_end - time_start)) + bitrate = (y_axis_com_data[-1] / (time_end - time_start)) / 1000000 # MBit/s + print('Bitrate: ' + str(math.floor(bitrate * 100)/100) + 'MBit/s\n') + + return (x_axis_time, y_axis_com_data) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Plot two PCAP files') + parser.add_argument('--client', metavar='', help='pcap file to parse', required=True) + parser.add_argument('--server', metavar='', help='pcap file to parse', required=True) + args = parser.parse_args() + + file_name1 = args.server + file_name2 = args.client + + if not os.path.isfile(file_name1): + print('"{}" does not exist'.format(file_name), file=sys.stderr) + sys.exit(-1) + if not os.path.isfile(file_name2): + print('"{}" does not exist'.format(file_name), file=sys.stderr) + sys.exit(-1) + + pcap1_x, pcap1_y = process_pcap(file_name1) + pcap2_x, pcap2_y = process_pcap(file_name2) + + plt.plot(pcap1_x, pcap1_y) + plt.plot(pcap2_x, pcap2_y, color='green') + plt.xlabel('Time [ms]') + plt.ylabel('Transfered Data [bit]') + plt.legend(["Server (Laptop)", "Client (Pi)"]) + plt.show() + sys.exit(0) diff --git a/Versuchstag-3/simple-client.py b/Versuchstag-3/simple-client.py new file mode 100755 index 0000000..c68567b --- /dev/null +++ b/Versuchstag-3/simple-client.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +import socket, argparse, subprocess + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Simple Client') + parser.add_argument('-p', default=1337, type=int, help='Serverport the server is listen on.') + parser.add_argument('-s', type=str, required=True, help='IPv4 address of the servers') + parser.add_argument('--tcp', action='store_true', help='Use TCP.') + parser.add_argument('--udp', action='store_true', help='Use UDP.') + args = parser.parse_args() + + if args.udp and args.tcp: + print("Only one protocol is allowed.") + exit(1) + elif not args.udp and not args.tcp: + print("Specify protocol") + exit(1) + + BUFFER_SIZE = 1400 + + # IP und Port des Servers + IP = args.s + PORT = args.p + # Unterstützte Addresstypen (IPv4, IPv6, lokale Addressen) + address_families = (socket.AF_INET, socket.AF_INET6, socket.AF_UNIX) + # Unterstützte Sockettypen (TCP, UDP, Raw (ohne Typ)) + socket_types = (socket.SOCK_STREAM, socket.SOCK_DGRAM, socket.SOCK_RAW) + # Passenden Address- und Sockettyp wählen + address_family = address_families[0] + if args.tcp: + socket_type = socket_types[0] + else: + socket_type = socket_types[1] + # Erstellen eines Sockets (TCP und UDP) + sock = socket.socket(address_family, socket_type) + try: + if args.tcp: + # Verbinden zu einem Server-Socket (Nur TCP) + sock.connect((IP,PORT)) + + # raspivid starten + cmd_raspivid = 'raspivid -t 0 -fps 20 -w 1280 -h 720 -b 2000000 -o -' + rasprocess = subprocess.Popen(cmd_raspivid,shell=True,stdout=subprocess.PIPE) + + while True: + # Daten der Größe BUFFER_SIZE aus der Ausgabe von raspivid auslesen + message = rasprocess.stdout.read(BUFFER_SIZE) + + if args.tcp: + # TCP + sock.send(message) + else: + # UDP + sock.sendto(message, (IP, PORT)) + + except KeyboardInterrupt: + print("Close socket.") + sock.close() + print("Exiting through keyboard event (CTRL + C)") diff --git a/Versuchstag-3/simple-server.py b/Versuchstag-3/simple-server.py new file mode 100755 index 0000000..efece12 --- /dev/null +++ b/Versuchstag-3/simple-server.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import socket, argparse, subprocess + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Simple Server') + parser.add_argument('-p', default=1337, type=int, help='Serverport the server is listen on.') + parser.add_argument('-a', type=str, required=True, help='IPv4 address of the servers interface for bind.') + parser.add_argument('--tcp', action='store_true', help='Use TCP.') + parser.add_argument('--udp', action='store_true', help='Use UDP.') + args = parser.parse_args() + + if args.udp and args.tcp: + print("Only one protocol is allowed.") + exit(1) + elif not args.udp and not args.tcp: + print("Specify protocol") + exit(1) + + # Port des Servers + PORT = args.p + # Lesepuffergröße + BUFFER_SIZE = 1400 + # Unterstützte Addresstypen (IPv4, IPv6, lokale Addressen) + address_families = (socket.AF_INET, socket.AF_INET6, socket.AF_UNIX) + # Unterstützte Sockettypen (TCP, UDP, Raw (ohne Typ)) + socket_types = (socket.SOCK_STREAM, socket.SOCK_DGRAM, socket.SOCK_RAW) + # Passenden Address- und Sockettyp wählen + address_family = address_families[0] + if args.tcp: + socket_type = socket_types[0] + else: + socket_type = socket_types[1] + # Maximale Anzahl der Verbindungen in der Warteschlange + backlog = 1 + try: + # Erstellen eines Socket (TCP und UDP) + sock = socket.socket(address_family, socket_type) + sock.bind((args.a, PORT)) + if args.tcp: + # Lausche am Socket auf eingehende Verbindungen (Nur TCP) + sock.listen(backlog) + clientsocket, address = sock.accept() + + # mplayer starten + cmd_mplayer = 'mplayer -fps 25 -cache 512 -' + mprocess = subprocess.Popen(cmd_mplayer, shell=True, stdin=subprocess.PIPE) + + while True: + # Daten (der Größe BUFFER_SIZE) aus dem Socket holen und ausgeben: + if args.tcp: + # TCP: + data = clientsocket.recv(BUFFER_SIZE) + else: + # UDP: + data, address = sock.recvfrom(BUFFER_SIZE) + # Die ausgelesenen Daten an mplayer weiterleiten + mprocess.stdin.write(data) + + except KeyboardInterrupt: + print("Close socket.") + sock.close() + print("Exiting through keyboard event (CTRL + C)")