BATMAN-Konfiguration

Aus wiki.freifunk.net
Zur Navigation springenZur Suche springen
Important.png Wichtig: Der Großteil dieses Artikels stammt noch aus dem Jahr 2013. Manche der hier gegebenen Informationen sind nicht mehr aktuell. Andere Dinge müssen in der aktuellen (Dez 2017) Firmware so nicht mehr getan werden (z.B: die init-skripte)


Einführung

B.A.T.M.A.N.-Advanced ist eine Layer 2.5 Implementierung eines Routingprotokolls für drahtlose Ad-Hoc-Netze, bezogen auf das OSI-Modell (das mit den 7, ähh 8 Schichten ;). Es sitzt also zwischen MAC-Layer und IP-Layer. "Klassische" Routingprotokolle wie OLSR routen auf IP-Ebene, batman-adv dagegen auf MAC-Ebene. Wenn in einem klassischen Routingprotokoll IP-Adressen in der Routingtabelle stehen, sind es bei einer Batman-adv-Routingtabelle MAC-Adressen. Das klingt verwirrend und ist es möglicherweise zu Anfang auch. Für den Anfang muss man sich nur merken, dass Batman-adv in Software einen virtuellen Switch in der Mesh-Wolke erzeugt.

Batman-adv erzeugt einen virtuellen Switch. Das Switch-Interface hat per default in jedem Mesh-Knoten den Namen bat0.

Ihr wisst bestimmt, was ein Switch tut. Kabel rein, und alle Geräte, die am gleichen Switch oder an einer Kaskade von Switches hängen, sind link-lokal (natürlich nur solange die einzelnen Ports nicht in unterschiedlichen VLANs separiert sind). Damit die Geräte an einem physikalischen Switch untereinander kommunizieren können, brauchen sie noch irgendwelche Adressen (IPv4, IPv6, IPX, whatever...) – aber dem Switch an sich ist das *egal*. Für Batman-adv ist das genau so.

Alles, was über bat0 kommuniziert wird, erscheint für die Anwendungen, die auf bat0 zugreifen, link-local (auch wenn es im Mesh viele routende Zwischenstationen erfordert, aber sie bekommen davon nichts mit)

Batman-adv hat einen Server und einen Client-Modus für Gateway-Betrieb. Diesen braucht man um mehrere Internet-Gateways in einem Batman-adv Netz zu betreiben. Dazu weiter unten mehr.

Voraussetzungen und Besonderheiten mit der MTU (Maximum Transfer Unit)

Um zu funktionieren, braucht Batman-adv mindestens ein Transport-Interface, über das es seine Routinginformationen transportieren kann. Es können durchaus auch mehrere Transport-Interfaces sein, batman-adv sucht sich dann beim Routen das Beste heraus, je nachdem, wo es hingehen soll.

Über das oder die Transport-Interfaces fliesst die Nutzlast, die Batman-adv transportieren muss, um den virtuellen Switch zu emulieren. Im Prinzip handelt es sich bei der Nutzlast um Ethernetframes, die eingekapselt werden, wie das auch z.B. bei IP-Tunneln mit IP-Paketen üblich ist. Die Datenpakete der Nutzlast werden "verpackt", sie bekommen einen zusätzlichen Header. Der Header ist Overhead, er benötigt 28 Byte. Wenn also ein 1500 Byte großes Paket über das bat0 Interface transportiert wird, kommen 28 Byte Header dazu, wenn sie über die Transportinterface(s) verschickt werden. Standardmäßig sind auf Ethernet-Interfaces 1500 Byte Transportgröße eingestellt.

Auf den Transport-Interfaces sollte man die MTU (Maximum Transfer Unit) für Batman-adv auf 1528 Byte einstellen, da sonst ein Standard-Ethernet-Paket von 1500 Byte, das durch bat0 wandert, auf dem Transport-Interface fragmentiert wird und deshalb 2 Pakete transportiert werden müssen. Gerade für WLAN sind überflüssige, zusätzliche Datenpakete teuer, weil der Zugriff auf den Funkkanal mit anderen WLAN-Stationen geteilt wird und koordiniert werden muss.

Batman-adv erzeugt auch ohne die Nutzlast etwas Overhead für Routinginformationen über den Zustand des Netzes, damit der Routingalgorithmus entscheiden kann, wie und wohin geroutet werden soll.

Ein kleiner Test mit dem lokalen PC

Wir spielen das mal auf einem PC durch. Unter OpenWrt muss man das Paket kmod-batman-adv installieren. Wenn Ihr einen aktuellen Linux-Kernel auf Eurem PC habt, müsst Ihr nur das Modul laden, da batman-adv bereits mit dem Linux-Kernel mitgeliefert wird. Hat man das Kernel-Modul von Batman-adv geladen und es aktiviert, indem man mindestens ein Transport-Interface damit assoziiert, entsteht ein virtuelles Interface namens bat0.

Als root:

 modprobe batman-adv 

Nun passiert erstmal noch nichts, ausser dass Ihr mit dem Befehl 'lsmod' sehen solltet, dass batman-adv in der Liste der geladenen Module steht:

 root@eee:/home/elektra# lsmod | grep batman
Module                  Size  Used by
batman_adv            127659  0 
libcrc32c              12543  1 batman_adv

Nun kann man mit dem Kernelmodul über das User-Space-Programm 'batctl' reden. Das Programm batctl wird bei OpenWrt automatisch mit dem Kernelmodul installiert. Auf Eurem PC ist batctl wahrscheinlich noch nicht installiert. Das lässt sich unter Debian/Ubuntu mit apt-get install batctl beheben.

Beginnen wir mit batctl o, das zeigt die Liste der im Mesh vorhandenen Meshknoten (oder -stationen) an.

 root@eee:/home/elektra# batctl o
Error - mesh has not been enabled yet
Activate your mesh by adding interfaces to batman-adv

Wir haben noch kein Transport-Interface hinzugefügt. Das behebe ich jetzt mit:

batctl if add wlan0

Ich habe nun wlan0 als Transportinterface hinzugefügt. Nun wiederhole ich batctl o:

root@eee:/home/elektra# batctl o
[B.A.T.M.A.N. adv 2013.3.0, MainIF/MAC: wlan0/00:25:d3:45:3b:b6 (bat0)]
  Originator      last-seen (#/255)           Nexthop [outgoingIF]:   Potential nexthops ...
No batman nodes in range ...

Nun ist batman-adv aktiv, aber ich habe hier noch keine Nachbarn. Es gibt jetzt ein zusätzliches Netzwerk-Interface mit dem Bezeichner bat0:

root@eee:/home/elektra# ifconfig -a
bat0      Link encap:Ethernet  Hardware Adresse 8a:15:ec:cf:da:ed  
          BROADCAST MULTICAST  MTU:1500  Metrik:1
          RX-Pakete:0 Fehler:0 Verloren:0 Überläufe:0 Fenster:0
          TX-Pakete:0 Fehler:0 Verloren:0 Überläufe:0 Träger:0
          Kollisionen:0 Sendewarteschlangenlänge:0 
          RX-Bytes:0 (0.0 B)  TX-Bytes:0 (0.0 B)

Das Interface ist noch nicht eingeschaltet, deswegen habe ich 'ifconfig -a' (list all, d.h. zeige auch inaktive Netzwerk-Interfaces) benutzt, weil es sonst nicht gelistet wird.

Habe ich schon deutlich darauf hingewiesen, dass batman-adv das Mesh in einen riesigen, virtuellen Switch verwandelt? Unser Switch-Port ist bat0.

Im Prinzip muss man bat0 nur noch aktivieren. Damit hat man den gleichen Effekt, als hätte man ein LAN-Kabel in den Switch gesteckt und das lokale Ethernet-Interface aktiviert. Da das bat0-Interface sich wie ein Switch-Port an einem (potentiell) riesigen Switch verhält, braucht es – theoretisch – nicht mal eine IP-Adresse, damit man es benutzen kann. Es muss nur aktiviert sein.

Ein simples:

ip link set bat0 up

würde genügen.

Gibt es irgendwo im batman-adv Netz einen DHCP-Server, genügt es, auf bat0 einen DHCP-Client zu starten. Fügt man bat0 in einer Bridge mit einem Accesspoint-Interface zusammen, würden die Accesspoint-Clients vom DHCP-Server der batman-adv Netzes ihre Netzwerkkonfiguration beziehen. Das machen wir später.

Nun ist das Interface hochgefahren, und weil IPv6 aktiviert ist, ist es eigentlich auch schon benutzbar.

root@eee:/home/elektra# ifconfig 
bat0      Link encap:Ethernet  Hardware Adresse 8a:15:ec:cf:da:ed  
          inet6-Adresse: fe80::0815:ecff:cccc:daed/64 Gültigkeitsbereich:Verbindung
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metrik:1
          RX-Pakete:6 Fehler:0 Verloren:0 Überläufe:0 Fenster:0
          TX-Pakete:31 Fehler:0 Verloren:0 Überläufe:0 Träger:0
          Kollisionen:0 Sendewarteschlangenlänge:0 
          RX-Bytes:252 (252.0 B)  TX-Bytes:5182 (5.1 KB)

Probleme mit MTU PATH DISCOVERY vermeiden

Zumindest, wenn über bat0 IPv4 Pakete transportiert werden sollen, sollte man aber unbedingt eine IPv4 Adresse dem bat0 Interface zuweisen. Wenn man keine IPv4 Adresse auf bat0 hat, funktioniert PATH MTU DISCOVERY nicht. Das äussert sich z.B. darin, dass bis zu 1472 Byte große Datenpakete wunderbar in beide Richtungen fliessen, aber alles, was größer ist, nicht. Man kann zwar z.B. eine Webseite aufrufen und sie fängt an zu laden, bleibt aber immer beim Laden an der gleichen Stelle stehen. Um das Problem zu beheben, kann man entweder eine statische IPv4 Adresse vergeben oder – falls es einen DHCPv4-Server im Mesh gibt – einen DHCPv4-Client auf dem Interface starten. Auch AVAHI (Zeroconf) wäre eine Option, nachdem das Interface hochgefahren ist.

Mit Batman-adv und AVAHI lässt sich prinzipiell ein Mesh ohne jegliche Konfiguration bauen, nur einen Namen sollte man jedem Gerät geben, damit man die Geräte zum Administrieren erreichen kann. Aber darum geht es uns hier nicht.

Skalierbarkeit

Protokolle, die nur link-local in einem LAN oder einem Zuhause-WLAN eingesetzt werden, gehen davon aus, dass Bandbreite fast nichts kostet und im Überfluss vorhanden ist. Diese Protokolle belasten durch ihre Geschwätzigkeit das Mesh-Netz, weil diese Annahme bei drahtlosen Multi-Hop-Mesh-Routen natürlich nicht stimmt. Ein Netzwerk, das praktisch nur ein riesiger Switch ohne VLANs ist, skaliert aus diesem Grund nicht beliebig.

Lösung: Kiez-Setup

Aufgrund dieses Problems werden wir Mesh-Wolken bis zu einer Größe aufbauen, die mit Batman-Adv skaliert, ohne dass wir dazu Traffic filtern und die Funktionalität einschränken müssen. Diese kleinen Mesh-Wolken stellen jeweils ein Mesh-Subnetz in einem größeren Mesh-Netzwerk-Verbund dar - und bilden so ein MAN (Metropolitan Area Network :)

Um Traffic zwischen solchen Mesh-Subnetzen zu routen, die logisch durch IP-Subnetze verwaltet werden, braucht man ein Routingprotokoll, das Subnetze announcieren und routen kann. Das sind z.B. OLSR, BGP, OSPF, BMX6, das alte Layer 3 B.A.T.M.A.N., BABEL etc. Da wir hier viel Erfahrung mit OLSR haben, verwenden wir dafür erstmal OLSR.

Laut den Erfahrungen von Freifunk Lübeck skaliert eine batman-adv-Wolke ohne Filtermaßnahmen bis etwa 80-100 Router mit mehreren hundert Clients. Zwar kann man die Skalierbarkeit erhöhen, indem man bestimmten Traffic filtert, aber das würde die Funktionalität einschränken. Für versehentliche Datei- oder Druckerfreigaben sind wir nicht verantwortlich. Umso besser ist es, wenn Leute absichtlich anderen Leuten Dienste anbieten, die sonst nur in lokalen Netzen vorkommen. Die Idee ist, dass z.B. Dienste wie Multicast-DNS funktionieren und die Leute innerhalb eines Kiezes diese Dienste nutzen können. (Zum Beispiel Peer-to-Peer-Chat mit Bonjour). Das wird ein Spaß! Endlich lokaler Content! Radio-Streams! Yay!


Netzwerk-Konfiguration

Für ein solches Batman-adv Subnetz brauchen wir einen IP-Bereich. Das Britische Verteidungsministerium besitzt einen Class A IP-Bereich 25.0.0.0/8.

Da nicht anzunehmen ist, dass jemand aus unserem Kiez mit dem Britischen Verteidigungsministerium kommunizieren muss (oder umgekehrt das Britische Verteidigungsministerium mit Freifunk kommunizieren müsste), könnten wir das recyclen. Ich nehme das jetzt mal als Beispiel.

Angenommen, die Batman-adv Wolke verwendet 25.130.0.0/20 – hier der Output von ipcalc:

Address:   25.130.0.0           
Netmask:   255.255.240.0 = 20   
Network:   25.130.0.0/20        
HostMin:   25.130.0.1           
HostMax:   25.130.15.254        
Broadcast: 25.130.15.255        
Hosts/Net: 4094

Das ist nicht großzügig bemessen, sollte aber reichen.

Mehrere Gateways

Wir haben in dieser Batman-adv-Wolke mehrere Standorte, die an den OLSR-Backbone angebunden sind. Es sind die Gateways aus dem Subnetz und in das Subnetz. Batman-adv wird auf den Gateways als Batman-Server betrieben. An jedem dieser Gateway-Standorte werden wir einen DHCP-Server für die Batman-adv-Wolke betreiben, der IP-Adressen an die batman-adv-Clients herausgibt. Die herausgegebenen IPs der unterschiedlichen DHCP-Server innerhalb einer Batman-Adv-Wolke dürfen sich nicht überlappen, sie müssen aber alle aus dem gleichen Subnetz stammen.

Beispiel-Gateway Nummer 1

Alle DHCP-Server in dieser Mesh-Wolke geben aus dem 25.130.0.0/20 stammende IP-Adressen aus und sie tragen sich selbst als Default-Gateway ein. Für den ersten Gateway wäre das z.B. 25.130.0.1 als Gateway-IP. Jeder DHCP-Server gibt IP-Adressen aus einem Teilbereich heraus. Der DHCP-Server 25.130.0.1 gibt also z.B. IP-Adressen von 25.130.0.20 bis 25.130.1.254 an die Clients heraus, alles unter 20 geht als statische Adressen an die benachbarten Router. Diese Adressen passen – nicht ganz zufällig – in ein Subnetz 25.130.0.1/23:

Address:   25.130.0.1           
Netmask:   255.255.254.0 = 23   
Network:   25.130.0.0/23        
HostMin:   25.130.0.1           
HostMax:   25.130.1.254         
Broadcast: 25.130.1.255         
Hosts/Net: 510

Aufgepasst: Dieses /23 Subnetz ist *nicht* das Subnetz, das wir den Clients per DHCP geben. Die IP-Adressen, die dieser DHCP-Server herausgibt, passen lediglich in dieses /23 Subnetz hinein. Die IP-Adressen-Konfiguration des bat0 Interface in dieser Maschine ist 25.130.0.1/20, und auch die IP-Adressen, welche die Clients bekommen, gehören zum Subnetz 25.130.x.x/20. Die Adressen, die Gateway #1 herausgibt, müssen deshalb in das kleinere Subnetz 25.130.0.1/23 hineinpassen, damit wir dieses Subnetz über OLSR HNA (Host Network Announcement) in andere Bereiche des stadtweiten Netzes announcieren können! Auf diese Weise fließt der Datenverkehr von und zu den Clients aus dem OLSR-Netz über genau das Gateway, von dem sie ihre IP-Adresse bekommen haben. Das ist gut für Clients, die sich nicht quer durch den Kiez bewegen (also z.B. von Friedrichshain-Süd nach Friedrichshain-Nord), da sonst das Batman-Routing u.U. Umwege einlegen muss. Hier gilt es abzuwägen: Macht man die DHCP-Lease-Time relativ kurz, bekommen Geräte, die sich über weite Strecken bewegen häufiger eine neue IP-Adresse zugewiesen und das Routing ist günstiger. Aber: Wenn sich ihre IP-Adresse ändert, brechen stehende Verbindungen ab, also z.B. VOIP-Gespräche.

Zur Zeit hakt es noch mit der Konfiguration von batman-adv via UCI in OpenWrt. Wir haben uns erstmal mit einem init-Skript beholfen. Eine Besonderheit dieses Setups muss man vielleicht vorweg noch erwähnen: bat0 wird hier zu einem Bridge-Interface als Slave hinzugefügt. Damit sind die Interfaces, die in dem Bridge-Interface mit bat0 gebrückt sind, ebenfalls Teil des großen, virtuellen "Batman-adv-Kiez-Switches"

Important.png Wichtig: Das Verwenden von init-Skripten ist aktuell (Mai 2017) nicht mehr nötig
#!/bin/sh /etc/rc.common
# /etc/init.d/bat-adv
# No fraggin' copyright
# wlan0 = AP interface for associating clients
# wlan0-1 = Ad-Hoc interface to transport payload
# bat-br = Bridge with AP-interface and bat0 enslaved


START=99

start() { 
          batctl if add wlan0-1 br-lan
          ifconfig wlan0-1 mtu 1528
          brctl addbr bat-br
          brctl addif bat-br wlan0
          brctl addif bat-br bat0
          batctl it 3000
          batctl gw server
          ip link set bat0 up
          ip link set bat-br up 
          ip a add 25.130.0.1/20 brd 25.130.15.255 dev bat-br
}

stop () {
          batctl if del wlan0-1 br-lan
}


ToDo: Die Konfiguration des DHCP-Servers muss angepasst werden.

Gateway Nummer 2

Gateway Nummer 2 gibt aus dem 25.130.0.0/20 IP-Adressen per DHCP heraus, die in das Subnetz 25.130.2.0/24 passen. Als Gateway announciert er sich selbst, 25.130.2.1. In diesem Beispiel gibt der Gateway Adressen heraus, die in ein kleineres Subnetz /24 passen:

root@eee:/home/elektra# ipcalc 25.130.2.0/24
Address:   25.130.2.0           
Netmask:   255.255.255.0 = 24   
Network:   25.130.2.0/24        
HostMin:   25.130.2.1           
HostMax:   25.130.2.254         
Broadcast: 25.130.2.255        
Hosts/Net: 254

Hier ist die IP-Konfiguation des Bridge-Interfaces, dass das bat0-Interface enthält 25.130.2.1/20, die Clients bekommen Adressen von 25.130.2.x/20 bis 25.130.2.254/20. Das OLSR-HNA Announcement ist 25.130.2.0/24.

#!/bin/sh /etc/rc.common
# /etc/init.d/bat-adv
# No fraggin' copyright
# wlan0 = AP interface for associating clients
# wlan0-1 = Ad-Hoc interface to transport payload
# bat-br = Bridge with AP-interface and bat0 enslaved


START=99

start() { 
          batctl if add wlan0-1 br-lan
          ifconfig wlan0-1 mtu 1528
          brctl addbr bat-br
          brctl addif bat-br wlan0
          brctl addif bat-br bat0
          batctl it 3000
          batctl gw server
          ip link set bat0 up
          ip link set bat-br up 
          ip a add 25.130.2.1/20 brd 25.130.15.255 dev bat-br
}

stop () {
          batctl if del wlan0-1 br-lan
}


Batman-Router ohne Gateway-Anschluss

Das bat0 Interface eines Batman-Routers bekommt eine IP aus dem Bereich 25.130.x.x/20. Liegt der Knoten z.B. in der Nähe von Gateway 25.130.0.1, bekommt er eine der statischen, reservierten Adressen aus dessen HNA-Bereich. Der batman-adv Modus ist nicht Server, sondern Client. Dieser Knoten ist lediglich eine Relais-Station.


#!/bin/sh /etc/rc.common
# /etc/init.d/bat-adv
# No fraggin' copyright
# wlan0 = AP interface for associating clients
# wlan0-1 = Ad-Hoc interface to transport payload
# bat-br = Bridge with AP-interface and bat0 enslaved


START=99

start() { 
          batctl if add wlan0-1 
          ifconfig wlan0-1 mtu 1528
          brctl addbr bat-br
          brctl addif bat-br wlan0
          brctl addif bat-br bat0
          batctl it 3000
          batctl gw client
          ip link set bat0 up
          ip link set bat-br up 
          ip a add 25.130.x.x/20 brd 25.130.15.255 dev bat-br
}

stop () {
          batctl if del wlan0-1
}


Konfiguration unter OpenWrt

Mit diesen Gundlagen "bewaffnet" kann man auch BATMAN auf einem OpenWrt-system einrichten.

Eine kurzes Howto gibt's auf den Seiten von Freifunk Berlin: als Abschnitt im Mesh-via-LAN Tutorial