Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| knb:raspberry [2020/11/30 13:56] – Django | knb:raspberry [2026/11/02 19:25] (aktuell) – Ins Archiv verschoben: archiv:knb:raspberry wartung | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | {{htmlmetatags> | + | ====== |
| - | metatag-description=(Offloader auf Basis eines Raspberry PI 4B) | + | |
| - | metatag-keywords=(Freifunk, | + | |
| - | }} | + | |
| - | ====== Offloader auf Basis eines Raspberry PI 4B ====== | + | |
| - | {{: | + | |
| + | Diese Anleitung ist veraltet und liegt jetzt im Archiv: [[: | ||
| - | <WRAP center round important 80%> | + | Für den Raspberry Pi 4 gibt es ein fertiges |
| - | Disclaimer: Die Anleitung ist nur für Leute, die sich bereits mit dem Thema Linux auseinander gesetzt haben oder sich intensiv damit beschäftigen wollen. | + | |
| - | </ | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Diese Anleitung funktioniert auf quasi allen Linux basierten Betriebssystemen, | + | |
| - | </ | + | |
| - | + | ||
| - | Mit dem [[https:// | + | |
| - | + | ||
| - | <WRAP center round important 80%> | + | |
| - | Für kabelgebundene Clients und/oder Meshing per Kabel benötigt ihr einen VLAN-fähigen Switch! | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | Angeboten wird das PI in einer 1GB, 2GB und 4GB RAM Variante. Will man wirklich nur einen reinen Offloader ohne Zusatzfunktionen betreiben, reicht im Grunde die 1GB Version. Allerdings ist mehr RAM immer besser ;) und man weiß ja nicht, was man im Endeffekt noch alles darauf betreiben will. | + | |
| - | + | ||
| - | {{: | + | |
| - | {{: | + | |
| - | {{: | + | |
| - | + | ||
| - | Nachdem es kein fertiges Gluon Image für das Raspberry PI 4B gibt im Moment, installieren wir erstmal strikt nach Anleitung das aktuelle Raspbian. | + | |
| - | + | ||
| - | Außerdem ermöglicht uns der Einsatz von Raspbian, dass wir alle normalen Anwendungen wie Webserver, Chatserver oder den Unifi-Controller einfach installieren können. | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Auf dem FFBSeeCamp 2019 gab es auch einen [[http:// | + | |
| - | + | ||
| - | Vom CCC gibt es dazu auch einen **//recent audio-only feed//** [[https:// | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | Eine Anleitung dazu findet ihr auf der [[https:// | + | |
| - | + | ||
| - | Am Ende der Prozedur, empfiehlt es sich auf der Boot Partition einfach eine leere Datei mit dem Namen " | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Der Benutzername lautet " | + | |
| - | Unbedingt ändern! Sonst kommen Leute aus dem Internet auf euer Raspberry! | + | |
| - | </ | + | |
| - | + | ||
| - | <WRAP center round alert 80%> | + | |
| - | Möchte man vom Raspberry später auch ein WLAN ausstrahlen lassen so ist es zwingend von Nöten, dass WIFI explizit via **rfkill** freizugeben! | + | |
| - | Hier loggen wir uns per SSH ein und setzen folgenden Befehl ab: | + | |
| - | # rfkill unblock wifi | + | |
| - | Anschließend starten wir den Raspberry 1x neu! | + | |
| - | # systemctl reboot | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Ansible-Playbook gesteuerter Bau des Offloaders ===== | + | |
| - | Wer nicht die nachfolgenden gut dokumentierten Schritte per Hand ausführen möchte, kann sich auch mit Hilfe von **[[https:// | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Das entsprechende **[[https:// | + | |
| - | </ | + | |
| - | + | ||
| - | ===== BATMAN ===== | + | |
| - | + | ||
| - | + | ||
| - | Nachdem ihr euch eingeloggt habt, wechseln wir zum Root User und laden das BATMAN Kernelmodul herunter. Das wird gebraucht um nachher das Routing innerhalb des Freifunknetzes zu übernehmen. | + | |
| - | + | ||
| - | Am Besten schaut ihr vorher, welches die [[https:// | + | |
| - | < | + | |
| - | pi@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Nachdem das Kernelmodul manuell gebaut wird, wollen wir natürlich dass das auch Bestand hat, wenn ein Kernelupdate eingespielt wird. Dazu brauchen wir nun einige Pakete. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Anschließend müssen wir auf Grund dessen, dass der Raspberry PI Kernel crosscompiled wurde die make Skripte neu generieren. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Es kann passieren, dass hier nach einiger Zeit mit der Fehlermeldung \\ | + | |
| - | " | + | |
| - | abgebrochen wird, das stellt aber kein Problem dar. | + | |
| - | </ | + | |
| - | + | ||
| - | Nun nachdem die Vorbereitungen getroffen sind, zurück zu BATMAN. Und dem Anlegen der dkms.conf. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Der Inhalt der dkms.conf sieht wie folgt aus: | + | |
| - | < | + | |
| - | PACKAGE_NAME=batman-adv | + | |
| - | PACKAGE_VERSION=2019.2 | + | |
| - | + | ||
| - | DEST_MODULE_LOCATION=/ | + | |
| - | BUILT_MODULE_NAME=batman-adv | + | |
| - | BUILT_MODULE_LOCATION=net/ | + | |
| - | + | ||
| - | MAKE="' | + | |
| - | CLEAN="' | + | |
| - | + | ||
| - | AUTOINSTALL=" | + | |
| - | </ | + | |
| - | + | ||
| - | Die Datei speichern und schon sind wir bereit für das erste Mal bauen des Kernelmodules. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Als nächstes müssen wir dafür sorgen, dass das Kernelmodul beim Boot auch geladen wird. Dazu müssen wir die Datei "/ | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | # | + | |
| - | # Load batman-adv module on system boot | + | |
| - | # | + | |
| - | batman-adv | + | |
| - | dummy | + | |
| - | </ | + | |
| - | + | ||
| - | Nun kann man entweder rebooten oder die Module manuell laden. | + | |
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Um BATMAN verwalten zu können müssen wir nun noch " | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Dann überprüfen wir ob alles korrekt geladen ist. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | < | + | |
| - | Active routing protocol configuration: | + | |
| - | + | ||
| - | Selected routing algorithm (used when next batX interface is created): | + | |
| - | => BATMAN_IV | + | |
| - | + | ||
| - | Available routing algorithms: | + | |
| - | * BATMAN_IV | + | |
| - | * BATMAN_V | + | |
| - | </ | + | |
| - | + | ||
| - | Nachdem wir BATMAN_V bei uns verwenden, sehen wir dass aktuell der falsche Routing Algorithmus ausgewählt ist. Das korrigieren einmal sofort manuell. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | Nun kommen wir zur Interface Konfiguration. In diesem Beispiel, werden wir das Raspberry PI im Segment " | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi:/ | + | |
| - | </ | + | |
| - | + | ||
| - | <file bash / | + | |
| - | # interfaces(5) file used by ifup(8) and ifdown(8) | + | |
| - | + | ||
| - | # Please note that this file is written to be used with dhcpcd | + | |
| - | # For static IP, consult / | + | |
| - | + | ||
| - | # Include files from / | + | |
| - | + | ||
| - | auto eth0 | + | |
| - | iface eth0 inet dhcp | + | |
| - | + | ||
| - | auto br-welt | + | |
| - | iface br-welt inet dhcp | + | |
| - | bridge-ports bat-welt | + | |
| - | pre-up / | + | |
| - | pre-up /sbin/ip link add dummy-welt type dummy | + | |
| - | pre-up /sbin/ip link set address $(ip -br l | grep eth0 | egrep -o ' | + | |
| - | pre-up /sbin/ip link set dummy-welt up | + | |
| - | pre-up / | + | |
| - | pre-up /sbin/ip link set bat-welt up | + | |
| - | pre-up / | + | |
| - | pre-up /sbin/ip link set address $(ip -br l | grep eth0 | egrep -o ' | + | |
| - | post-up /sbin/ip link set address $(ip -br l | grep eth0 | egrep -o ' | + | |
| - | + | ||
| - | </ | + | |
| - | + | ||
| - | Im Beispiel setzen wir die MAC Addresse für BATMAN fest auf die MAC von eth0, damit wir später auch Statistiken etc abrufen können. | + | |
| - | + | ||
| - | ===== FASTD ===== | + | |
| - | + | ||
| - | <WRAP center round important 80%> | + | |
| - | Bitte informiert euch vorher in welches Segment ihr wollt, dementsprechend muss der FASTD Port angepasst werden! | + | |
| - | </ | + | |
| - | + | ||
| - | {{tablelayout? | + | |
| - | ^ Domain | + | |
| - | | ffmuc_muc_cty | + | |
| - | | ffmuc_muc_nord | + | |
| - | | ffmuc_muc_ost | + | |
| - | | ffmuc_muc_sued | + | |
| - | | ffmuc_muc_west | + | |
| - | | ffmuc_uml_nord | + | |
| - | | ffmuc_uml_ost | + | |
| - | | ffmuc_uml_sued | + | |
| - | | ffmuc_uml_west | + | |
| - | | ffmuc_gauting | + | |
| - | | ffmuc_freising | + | |
| - | | ffmuc_welt | + | |
| - | + | ||
| - | + | ||
| - | Um zum Freifunk München Netz verbinden zu können, brauchen wir nun noch fastd. | + | |
| - | + | ||
| - | Diesen installieren wir einfach per apt | + | |
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | Und anschließend generieren wir uns einen Key, den wir zum Verbinden und verschlüsseln benötigen. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | 2019-07-05 10:57:41 +0100 --- Info: Reading 32 bytes from / | + | |
| - | Secret: 1843fd17494d265d65f9563e3655728dbf1c8f7fb04365a9ab733f4debdb8f51 | + | |
| - | Public: 7703d5f1766c11cc701cc039af1913faef216ced7b33dd18f87e57c172e0324e | + | |
| - | </ | + | |
| - | + | ||
| - | Wir benötigen davon nur den Secret Key. Anschließend erzeugen wir die Konfiguration. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | # vi / | + | |
| - | + | ||
| - | <file bash / | + | |
| - | # | + | |
| - | # welt FASTd configuration | + | |
| - | # | + | |
| - | + | ||
| - | log to syslog level info; | + | |
| - | + | ||
| - | interface " | + | |
| - | + | ||
| - | method " | + | |
| - | method " | + | |
| - | + | ||
| - | secret " | + | |
| - | mtu 1406; | + | |
| - | + | ||
| - | status socket "/ | + | |
| - | + | ||
| - | on up " | + | |
| - | batctl ra BATMAN_V | + | |
| - | ip link set $INTERFACE down | + | |
| - | ip link set address $(ip -br l | grep eth0 | egrep -o ' | + | |
| - | ip link set $INTERFACE up | + | |
| - | batctl -m bat-welt if add $INTERFACE | + | |
| - | + | ||
| - | "; | + | |
| - | + | ||
| - | on down " | + | |
| - | batctl -m bat-welt if del $INTERFACE | + | |
| - | "; | + | |
| - | peer group " | + | |
| - | peer limit 1; | + | |
| - | + | ||
| - | peer " | + | |
| - | key " | + | |
| - | remote " | + | |
| - | } | + | |
| - | + | ||
| - | peer " | + | |
| - | key " | + | |
| - | remote " | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | Nun aktivieren wir " | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | ===== ext-respondd ===== | + | |
| - | + | ||
| - | <WRAP center round important 80%> | + | |
| - | Dieser Teil ist wichtig, da es sein kann dass ihr gegen die Nutzungsbedingungen einiger Communities verstoßt, wenn ihr euch nicht als Knoten im Netz meldet. Außerdem trägt es generell zur Netzhygiene bei, wenn alle Knoten in den Statistiken auftauchen. | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | Nachdem wir auch auf der Knotenkarte auftauchen wollen, installieren wir auch noch ext-respondd | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | Dann müssen wir auch noch die Konfigurationsdateien von ext-respondd anpassen. | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Bitte tragt die Daten inklusive dem Segmentnamen korrekt ein. Eine Übersicht der Segmentnamen gibt es [[https:// | + | |
| - | + | ||
| - | </ | + | |
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | Die Dateien sind selbsterklärend, | + | |
| - | < | + | |
| - | { | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | } | + | |
| - | }, | + | |
| - | " | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | { | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Checken der Konfiguration ===== | + | |
| - | + | ||
| - | Anschließend rebooten wir einmal und wenn alles stimmt sollte der Knoten auf der Karte erscheinen und " | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | [B.A.T.M.A.N. adv 2019.1, MainIF/MAC: dummy-welt/ | + | |
| - | IF | + | |
| - | f2: | + | |
| - | </ | + | |
| - | + | ||
| - | Nun sollet ihr eine IPv6 Adresse aus dem gewählten Segment auf eurem Interface sehen. | + | |
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | br-welt | + | |
| - | + | ||
| - | </ | + | |
| - | + | ||
| - | ===== Meshing per Kabel ===== | + | |
| - | + | ||
| - | Falls ihr per Kabel meshen wollt, ist dies nur sinnvoll per VLAN möglich. | + | |
| - | + | ||
| - | Dazu müsst ihr zuerst ein VLAN Interface in / | + | |
| - | <file bash / | + | |
| - | auto eth0.666 | + | |
| - | iface eth0.666 inet manual | + | |
| - | post-up / | + | |
| - | post-up / | + | |
| - | </ | + | |
| - | + | ||
| - | <WRAP center round important 80%> | + | |
| - | Beachtet bitte, das Setup funktioniert nur in Umgebungen ohne VXLAN Meshing. Mit VXLAN Meshing braucht es auch noch ein VXLAN Interface. | + | |
| - | + | ||
| - | Mehr dazu siehe unten. | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | ==== Mesh per vxlan==== | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Für andere Communities benötigt ihr die entsprechenden VXLAN IDs zum Meshen | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | Um meshing per Kabel nutzen zu können, muss bei manchen Communities (wie bei FFMUC) VXLAN benutzt werden. | + | |
| - | + | ||
| - | Bei uns gibt es momentan folgende VXLAN IDs, diese werden von GLUON dynamisch aus dem domain_seed erzeugt. | + | |
| - | {{tablelayout? | + | |
| - | ^ Domain | + | |
| - | | ffmuc_muc_cty | + | |
| - | | ffmuc_muc_nord | + | |
| - | | ffmuc_muc_ost | + | |
| - | | ffmuc_muc_sued | + | |
| - | | ffmuc_muc_west | + | |
| - | | ffmuc_uml_nord | + | |
| - | | ffmuc_uml_ost | + | |
| - | | ffmuc_uml_sued | + | |
| - | | ffmuc_uml_west | + | |
| - | | ffmuc_gauting | + | |
| - | | ffmuc_freising | + | |
| - | | ffmuc_welt | + | |
| - | + | ||
| - | <WRAP center round tip 80%> | + | |
| - | Um die VXLAN ID aus einem domain_seed zu berechnen haben wir ein kleines {{ : | + | |
| - | + | ||
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | Die Konfiguration in / | + | |
| - | + | ||
| - | <file bash / | + | |
| - | auto eth0.666 | + | |
| - | iface eth0.666 inet manual | + | |
| - | pre-up /sbin/ip link add vxlan-mesh type vxlan id 16306234 group ff02::15c dstport 4789 port 32768 61000 no udpcsum udp6zerocsumtx udp6zerocsumrx dev eth0.666 || true | + | |
| - | up /sbin/ip link set vxlan-mesh up | + | |
| - | post-up / | + | |
| - | post-up / | + | |
| - | down ip link set vxlan-mesh down | + | |
| - | post-down ip link del vxlan-mesh || true | + | |
| - | </ | + | |
| - | + | ||
| - | Damit das vxlan-mesh Interface auch der bevorzugte Meshingpoint in BATMAN_V wird noch folgendes in die / | + | |
| - | + | ||
| - | <file bash / | + | |
| - | echo 1000000 > / | + | |
| - | </ | + | |
| - | Danach rebooten oder das Interface hochfahren. Wenn alles geklappt hat und ihr bereits einen Router zum Meshen in diesem VLAN habt, sollte danach folgendes in batctl zu sehen sein. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | [B.A.T.M.A.N. adv 2018.3, MainIF/MAC: vxlan-mesh/ | + | |
| - | IF | + | |
| - | 52: | + | |
| - | f2: | + | |
| - | </ | + | |
| - | Sollte sich kein Client am Mesh VLAN befinden, wird die vxlan-mesh Zeile nicht angezeigt. | + | |
| - | + | ||
| - | Außerdem sollten die Interfaces wie folgt aussehen: | + | |
| - | < | + | |
| - | root@ffoff: | + | |
| - | dummy-welt: active | + | |
| - | vxlan-mesh: active | + | |
| - | fastd-welt: active | + | |
| - | </ | + | |
| - | + | ||
| - | Leider ist der Link zum Gateway auf der Map nicht zu sehen. | + | |
| - | ===== Wifi Clients ===== | + | |
| - | + | ||
| - | Dazu müssen wir hostapd installieren und konfigurieren; | + | |
| - | + | ||
| - | {{page>: | + | |
| - | + | ||
| - | Die Liste der SSIDs findet ihr hier: | + | |
| - | {{page>: | + | |
| - | + | ||
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | + | ||
| - | </ | + | |
| - | + | ||
| - | vi / | + | |
| - | <file bash / | + | |
| - | ssid=muenchen.freifunk.net/ | + | |
| - | + | ||
| - | country_code=US | + | |
| - | + | ||
| - | interface=wlan0 | + | |
| - | driver=nl80211 | + | |
| - | + | ||
| - | macaddr_acl=0 | + | |
| - | + | ||
| - | logger_syslog=0 | + | |
| - | logger_syslog_level=4 | + | |
| - | logger_stdout=-1 | + | |
| - | logger_stdout_level=0 | + | |
| - | + | ||
| - | hw_mode=a | + | |
| - | wmm_enabled=1 | + | |
| - | + | ||
| - | # N | + | |
| - | ieee80211n=1 | + | |
| - | require_ht=1 | + | |
| - | ht_capab=[MAX-AMSDU-3839][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40] | + | |
| - | + | ||
| - | # AC | + | |
| - | ieee80211ac=1 | + | |
| - | require_vht=1 | + | |
| - | ieee80211d=0 | + | |
| - | ieee80211h=0 | + | |
| - | vht_capab=[MAX-AMSDU-3839][SHORT-GI-80] | + | |
| - | vht_oper_chwidth=1 | + | |
| - | channel=36 | + | |
| - | vht_oper_centr_freq_seg0_idx=42 | + | |
| - | </ | + | |
| - | + | ||
| - | Danach hostapd für den Systemstart aktivieren und starten. | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | Das Wlan0 muss nun noch in die Bridge gepackt werden. Dazu passen wir die / | + | |
| - | < | + | |
| - | #!/bin/sh -e | + | |
| - | # | + | |
| - | # rc.local | + | |
| - | # | + | |
| - | # This script is executed at the end of each multiuser runlevel. | + | |
| - | # Make sure that the script will "exit 0" on success or any other | + | |
| - | # value on error. | + | |
| - | # | + | |
| - | # In order to enable or disable this script just change the execution | + | |
| - | # bits. | + | |
| - | # | + | |
| - | # By default this script does nothing. | + | |
| - | + | ||
| - | # Print the IP address | + | |
| - | _IP=$(hostname -I) || true | + | |
| - | if [ " | + | |
| - | printf "My IP address is %s\n" " | + | |
| - | fi | + | |
| - | sleep 10; /sbin/brctl addif br-welt wlan0 | + | |
| - | exit 0 | + | |
| - | </ | + | |
| - | + | ||
| - | Am Besten nochmal rebooten um sicher zugehen dass alles passt, danach einfach mit dem ClientWifi verbinden. | + | |
| - | + | ||
| - | ===== LAN Clients ===== | + | |
| - | Diese sind im Grunde ganz einfach, ihr erstellt ein VLAN Interface in der / | + | |
| - | + | ||
| - | Hier ein Beispiel mit VLAN333, erst das VLAN Interface definieren und dann in der vorhandenen Bridge hinzufügen. | + | |
| - | + | ||
| - | vi / | + | |
| - | <file bash / | + | |
| - | auto eth0.333 | + | |
| - | iface eth0.333 inet manual | + | |
| - | + | ||
| - | auto br-welt | + | |
| - | iface br-welt inet dhcp | + | |
| - | bridge-ports bat-welt eth0.333 | + | |
| - | </ | + | |
| - | + | ||
| - | + | ||
| - | ===== Geschwindigkeiten ===== | + | |
| - | + | ||
| - | Nun zur wichtigsten Frage, welche Performance kann man erwarten. | + | |
| - | + | ||
| - | Hier ein paar Speedtest Ergebnisse: | + | |
| - | + | ||
| - | WiFi Client an VDSL 100: \\ | + | |
| - | {{: | + | |
| - | + | ||
| - | Kabel Client an VDSL 100: \\ | + | |
| - | {{: | + | |
| - | + | ||
| - | Kabel Client an 1Gbit/s Glas: \\ | + | |
| - | {{: | + | |
| - | + | ||
| - | $ wget -O /dev/null https:// | + | |
| - | + | ||
| - | < | + | |
| - | Resolving speed.hetzner.de (speed.hetzner.de)... 88.198.248.254 | + | |
| - | Connecting to speed.hetzner.de (speed.hetzner.de)|88.198.248.254|: | + | |
| - | HTTP request sent, awaiting response... 200 OK | + | |
| - | Length: 10485760000 (9.8G) [application/ | + | |
| - | Saving to: ‘/ | + | |
| - | / | + | |
| - | </ | + | |
| - | + | ||
| - | ===== Ändern des Hostnamen ===== | + | |
| - | Hat man mehr als einen Raspberry in seinem Netzwerk am laufen, so kann es mitunter sehr schnell unübersichtlich werden, wenn alle Geräte den gleichen Hostnamen verwenden und z.B. mit diesen an einem zentralen DHCP-Server melden und eine IP-Adresse beziehen. Wir wollen daher den Hostnamen auf den wer setzen, den wir für unseren Offloader beim Setzen des Nodenamen zuvor bei der Definition des **[[# | + | |
| - | + | ||
| - | pi@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | <file / | + | |
| - | :: | + | |
| - | ff02:: | + | |
| - | ff02:: | + | |
| - | + | ||
| - | 127.0.1.1 ff-django-raspi</ | + | |
| - | + | ||
| - | root@raspberrypi: | + | |
| - | < | + | |
| - | Icon name: computer | + | |
| - | Machine ID: b08567d7855541cf8110f09e88638c58 | + | |
| - | Boot ID: b35eb62018fc4446b8252eb2f2ae9ff5 | + | |
| - | Operating System: Raspbian GNU/Linux 10 (buster) | + | |
| - | Kernel: Linux 4.19.66-v7l+ | + | |
| - | Architecture: | + | |
| - | + | ||
| - | Wenn wir uns nun neu mit unserem Offloader verbinden, wird der nunmehr richtige Freifunk-Node-Name auch als Hostname verwendet. | + | |
| - | pi@ff-django-raspi: | + | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | ===== Uplink per LTE via iOS Gerät ===== | + | |
| - | + | ||
| - | Nebenbei | + | |
| - | + | ||
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | / | + | |
| - | < | + | |
| - | allow-hotplug eth1 | + | |
| - | iface eth1 inet dhcp | + | |
| - | </ | + | |
| - | + | ||
| - | Am Besten rebootet ihr jetzt einmal. | + | |
| - | + | ||
| - | Danach steckt ihr euer iOS Gerät per USB an während ihr im Hotspot Menü seid und werdet gefragt, ob das PI Zugriff bekommen kann. Das beantwortet ihr mit " | + | |
| - | + | ||
| - | Euer PI bezieht sich nun eine IP per DHCP vom iOS Gerät und kann darüber Verbindungen zu den Freifunk | + | |
| - | + | ||
| - | Und so sieht ein Mobile PI mit iPad als Uplink aus: | + | |
| - | {{: | + | |
| - | + | ||
| - | ===== OLED Display ===== | + | |
| - | {{: | + | |
| - | {{: | + | |
| - | + | ||
| - | In dem Beispiel verwenden wir ein OLED Display von [[https:// | + | |
| - | ==== Anschluss/ | + | |
| - | Angeschlossen wird das Ganze wie folgt: | + | |
| - | < | + | |
| - | < | + | |
| - | </ | + | |
| - | + | ||
| - | ==== I2C-Bus aktivieren ==== | + | |
| - | Als nächstes aktivieren wir die I2C Schnittstelle und installieren die notwendige Software. | + | |
| - | + | ||
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | + | ||
| - | root@raspberrypi: | + | |
| - | + | ||
| - | + | ||
| - | Bevor wir nun einen Reboot durchführen kontrollieren wir noch, ob in der // | + | |
| - | | + | |
| - | < | + | |
| - | + | ||
| - | # Uncomment some or all of these to enable the optional hardware interfaces | + | |
| - | # Django : 2019-09-11 - für OLED Display Support aktiviert | + | |
| - | # default: # dtparam=i2c_arm=on | + | |
| - | dtparam=i2c_arm=on | + | |
| - | + | ||
| - | ...</ | + | |
| - | + | ||
| - | Nun am Besten einmal rebooten. | + | |
| - | + | ||
| - | ==== Funktionstest ==== | + | |
| - | Danach überprüfen wir ob das Display erkannt wird. | + | |
| - | root@raspberrypi: | + | |
| - | < | + | |
| - | 00: -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- | + | |
| - | 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | + | |
| - | 70: -- -- -- -- -- -- -- -- | + | |
| - | </ | + | |
| - | + | ||
| - | Wie man sieht meldet sich das Display unter der Adresse **3c**. | + | |
| - | + | ||
| - | ==== Installation der Software-Bibliotheken ==== | + | |
| - | Jetzt installieren wir die notwendige Python Library um das Display ansteuern zu können. | + | |
| - | < | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | </ | + | |
| - | + | ||
| - | Anschließend können wir mit ein paar Beispielen probieren ob das Display korrekt funktioniert. | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | + | ||
| - | Auf dem Display werden ein paar Systemdaten angezeigt: | + | |
| - | + | ||
| - | {{ : | + | |
| - | + | ||
| - | ==== Script installieren und anpassen ==== | + | |
| - | Nachdem alles alles soweit funktioniert, | + | |
| - | + | ||
| - | Anschließend das [[https:// | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | root@raspberrypi: | + | |
| - | + | ||
| - | Nun passen wir in dem Script folgende Variabelen unseren Gegebenheiten an: | + | |
| - | * '' | + | |
| - | * '' | + | |
| - | * '' | + | |
| - | * '' | + | |
| - | + | ||
| - | root@raspberrypi: | + | |
| - | + | ||
| - | <file python / | + | |
| - | # Inspired by https:// | + | |
| - | # | + | |
| - | # Maintained by awlnx - aw@awlnx.space | + | |
| - | # | + | |
| - | + | ||
| - | import subprocess | + | |
| - | import time | + | |
| - | import re | + | |
| - | import Adafruit_GPIO.SPI as SPI | + | |
| - | import Adafruit_SSD1306 | + | |
| - | from PIL import | + | |
| - | from PIL import ImageDraw | + | |
| - | from PIL import ImageFont | + | |
| - | import math | + | |
| - | + | ||
| - | # Adjust to your needs | + | |
| - | wifi = ' | + | |
| - | vpn = ' | + | |
| - | batman = ' | + | |
| - | # Django | + | |
| - | # default: primary_mac = ' | + | |
| - | primary_mac = ' | + | |
| - | + | ||
| - | # We assume 100mbit/s max bandwidth | + | |
| - | maxRateIn = 10000000 | + | |
| - | maxRateOut = 10000000 | + | |
| - | PImaxRateIn = 10000000 | + | |
| - | PImaxRateOut = 10000000 | + | |
| - | + | ||
| - | ### DO NOT EDIT BELOW THIS POINT ### | + | |
| - | + | ||
| - | # Raspberry Pi pin configuration: | + | |
| - | RST = 24 | + | |
| - | + | ||
| - | # 128x64 display with hardware I2C: | + | |
| - | disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) | + | |
| - | + | ||
| - | # Initialize library. | + | |
| - | disp.begin() | + | |
| - | + | ||
| - | # Clear display. | + | |
| - | disp.clear() | + | |
| - | disp.display() | + | |
| - | + | ||
| - | # Create blank image for drawing. | + | |
| - | # Make sure to create image with mode ' | + | |
| - | width = disp.width | + | |
| - | height = disp.height | + | |
| - | image = Image.new(' | + | |
| - | + | ||
| - | # Get drawing object to draw on image. | + | |
| - | draw = ImageDraw.Draw(image) | + | |
| - | + | ||
| - | font = ImageFont.truetype('/ | + | |
| - | fontsmall = ImageFont.truetype('/ | + | |
| - | fontverysmall = ImageFont.truetype('/ | + | |
| - | fontmedium = ImageFont.truetype('/ | + | |
| - | + | ||
| - | #Display Image | + | |
| - | disp.image(image) | + | |
| - | disp.display() | + | |
| - | + | ||
| - | # | + | |
| - | + | ||
| - | def get_network_bytes(interface): | + | |
| - | for line in open('/ | + | |
| - | if interface in line: | + | |
| - | data = line.split(' | + | |
| - | rx_bytes, tx_bytes = (data[0], data[8]) | + | |
| - | return (int(rx_bytes), | + | |
| - | + | ||
| - | def drawBar (x, barHeight): | + | |
| - | # parameters are x, y, end x, end y | + | |
| - | # draw.rectangle ((x, height - barHeight, x + 10, height -1), outline=255, | + | |
| - | draw.rectangle ((x, 32 - barHeight, x + 8, height - 32), outline=255, | + | |
| - | + | ||
| - | def drawBarLOW (x, barLOWHeight): | + | |
| - | # parameters are x, y, end x, end y | + | |
| - | draw.rectangle ((x, 32 + barLOWHeight, | + | |
| - | + | ||
| - | def textRate(rate): | + | |
| - | # rate -> raw bitrate | + | |
| - | # Returns: SI formatted bitrate | + | |
| - | if rate == 0: | + | |
| - | return " | + | |
| - | rate = rate * 8 | + | |
| - | size_name = ( | + | |
| - | " | + | |
| - | i = int(math.floor(math.log(rate , 1024))) | + | |
| - | p = math.pow(1024, | + | |
| - | s = round(rate / p, 1) | + | |
| - | return "%s %s" % (s, size_name[i]) | + | |
| - | + | ||
| - | lastInBytes = get_network_bytes(vpn)[0]; | + | |
| - | lastOutBytes = get_network_bytes(vpn)[1]; | + | |
| - | lastPIInBytes = get_network_bytes(wifi)[0]; | + | |
| - | lastPIOutBytes = get_network_bytes(wifi)[1]; | + | |
| - | lastTime = time.time() | + | |
| - | + | ||
| - | #timed array vars | + | |
| - | timerTime = time.time() | + | |
| - | highestSpeedIn = 0 | + | |
| - | highestSpeedOut = 0 | + | |
| - | PIhighestSpeedIn = 0 | + | |
| - | PIhighestSpeedOut = 0 | + | |
| - | speedArrayIn = [] | + | |
| - | speedArrayOut = [] | + | |
| - | PIspeedArrayIn = [] | + | |
| - | PIspeedArrayOut = [] | + | |
| - | inMax = 0 | + | |
| - | outMax = 0 | + | |
| - | PIinMax = 0 | + | |
| - | PIoutMax = 0 | + | |
| - | + | ||
| - | while (1): | + | |
| - | time.sleep(2) | + | |
| - | draw.rectangle((0, | + | |
| - | + | ||
| - | now = time.time() | + | |
| - | elapsed = now - lastTime | + | |
| - | lastTime = now | + | |
| - | + | ||
| - | #calculate rates in and out | + | |
| - | inBytes = get_network_bytes(vpn)[0] | + | |
| - | currInBytes = (inBytes - lastInBytes) / elapsed | + | |
| - | lastInBytes = inBytes | + | |
| - | + | ||
| - | outBytes = get_network_bytes(vpn)[1] | + | |
| - | currOutBytes = (outBytes - lastOutBytes) / elapsed | + | |
| - | lastOutBytes = outBytes | + | |
| - | + | ||
| - | PIinBytes = get_network_bytes(wifi)[0] | + | |
| - | currPIInBytes = (PIinBytes - lastPIInBytes) / elapsed | + | |
| - | lastPIInBytes = PIinBytes | + | |
| - | + | ||
| - | PIoutBytes = get_network_bytes(wifi)[1] | + | |
| - | currPIOutBytes = (PIoutBytes - lastPIOutBytes) / elapsed | + | |
| - | lastPIOutBytes = PIoutBytes | + | |
| - | + | ||
| - | + | ||
| - | #max rate last 24 hours calculations | + | |
| - | + | ||
| - | if currInBytes > highestSpeedIn: | + | |
| - | highestSpeedIn = currInBytes | + | |
| - | if currOutBytes > highestSpeedOut: | + | |
| - | highestSpeedOut = currOutBytes | + | |
| - | if currPIInBytes > PIhighestSpeedIn: | + | |
| - | PIhighestSpeedIn = currPIInBytes | + | |
| - | if currPIOutBytes > PIhighestSpeedOut: | + | |
| - | PIhighestSpeedOut = currPIOutBytes | + | |
| - | + | ||
| - | if now > timerTime + 3600: | + | |
| - | print(' | + | |
| - | timerTime = now | + | |
| - | + | ||
| - | speedArrayIn.append (highestSpeedIn) | + | |
| - | if len (speedArrayIn) > 23: | + | |
| - | del speedArrayIn[0] | + | |
| - | inMax = max(speedArrayIn) | + | |
| - | + | ||
| - | speedArrayOut.append (highestSpeedOut) | + | |
| - | if len (speedArrayOut) > 23: | + | |
| - | del speedArrayOut[0] | + | |
| - | outMax = max(speedArrayOut) | + | |
| - | + | ||
| - | highestSpeedIn = 0 | + | |
| - | highestSpeedOut = 0 | + | |
| - | + | ||
| - | PIspeedArrayIn.append (PIhighestSpeedIn) | + | |
| - | if len (PIspeedArrayIn) > 23: | + | |
| - | del PIspeedArrayIn[0] | + | |
| - | PIinMax = max(PIspeedArrayIn) | + | |
| - | + | ||
| - | PIspeedArrayOut.append (PIhighestSpeedOut) | + | |
| - | if len (PIspeedArrayOut) > 23: | + | |
| - | del PIspeedArrayOut[0] | + | |
| - | PIoutMax = max(PIspeedArrayOut) | + | |
| - | + | ||
| - | PIhighestSpeedIn = 0 | + | |
| - | PIhighestSpeedOut = 0 | + | |
| - | + | ||
| - | #adjust these in each loop in case we find a faster speed | + | |
| - | inMax = max(inMax, highestSpeedIn) | + | |
| - | outMax = max(outMax, highestSpeedOut) | + | |
| - | PIinMax = max(PIinMax, | + | |
| - | PIoutMax = max(PIoutMax, | + | |
| - | + | ||
| - | #draw graph | + | |
| - | inHeight = 0.0 | + | |
| - | outHeight = 0.0 | + | |
| - | PIinHeight = 0.0 | + | |
| - | PIoutHeight = 0.0 | + | |
| - | + | ||
| - | if currInBytes > 0: | + | |
| - | inHeight = float(currInBytes / maxRateIn) * 32 | + | |
| - | + | ||
| - | if currOutBytes > 0: | + | |
| - | outHeight = float(currOutBytes / maxRateOut) * 32 | + | |
| - | + | ||
| - | if currPIInBytes > 0: | + | |
| - | PIinHeight = float(currPIInBytes / PImaxRateIn) * 32 | + | |
| - | + | ||
| - | if currPIOutBytes > 0: | + | |
| - | PIoutHeight = float(currPIOutBytes / PImaxRateOut) * 32 | + | |
| - | + | ||
| - | drawBar (0, inHeight) | + | |
| - | drawBar (10, PIinHeight) | + | |
| - | drawBarLOW (0, outHeight) | + | |
| - | drawBarLOW (10, PIoutHeight) | + | |
| - | #write rates | + | |
| - | draw.text((26, | + | |
| - | draw.text((26, | + | |
| - | + | ||
| - | draw.text((81, | + | |
| - | draw.text((81, | + | |
| - | + | ||
| - | # Batman Clients | + | |
| - | clients = subprocess.check_output(" | + | |
| - | draw.text((0, | + | |
| - | draw.text((10, | + | |
| - | + | ||
| - | #max rates | + | |
| - | draw.text((36, | + | |
| - | draw.text((26, | + | |
| - | draw.text((26, | + | |
| - | + | ||
| - | draw.text((90, | + | |
| - | draw.text((81, | + | |
| - | draw.text((81, | + | |
| - | + | ||
| - | disp.image(image) | + | |
| - | disp.display() | + | |
| - | + | ||
| - | </ | + | |
| - | + | ||
| - | Nun können das Script erst einmal manuell anstarten und prüfen ob die gewünschten Informationen richtig angezeigt werden. | + | |
| - | root@raspberrypi: | + | |
| - | + | ||
| - | {{ :knb:raspberry: | + | |
| - | + | ||
| - | Um nun nicht jedes mal beim Starten des Offloaders/ | + | |
| - | | + | |
| - | + | ||
| - | <file bash / | + | |
| - | [Unit] | + | |
| - | After=network.target | + | |
| - | + | ||
| - | [Service] | + | |
| - | ExecStart=/ | + | |
| - | + | ||
| - | [Install] | + | |
| - | WantedBy=default.target | + | |
| - | </ | + | |
| - | + | ||
| - | Anschließend Informieren wir unser System über unser definiertes Daemon-Startscript und aktivieren dies auch gleich noch. | + | |
| - | | + | |
| - | | + | |
| - | + | ||
| - | Zu guter letzte rebooten wir nun unseren Rechner. | + | |
| - | | + | |
| - | + | ||
| - | {{ : | + | |