Traduzioni: English - Italiano


Bonding

Questo articolo mostra come unire (bond) due connessioni Ethernet assieme per creare una interfaccia "auto failover".

Installazione

Prima di tutto occorre installare il pacchetto ifenslave, necessario per abilitare il «bonding»:

# apt-get install ifenslave

Spegnere / Deconfigurare le interfacce esistenti

# ifdown eth0 (Ripetere il comando per tutte le interfacce da includere nel bond)
# /etc/init.d/networking stop

{i} Alcune volte, ifdown non funziona, in questo caso si usi ifconfig eth0 down.

Configurazione - Esempio 1

Modificare il file /etc/network/interfaces:

auto bond0

iface bond0 inet static
    address 10.31.1.5
    netmask 255.255.255.0
    network 10.31.1.0
    gateway 10.31.1.254
    slaves eth0 eth1
    bond-mode active-backup
    bond-miimon 100
    bond-downdelay 200
    bond-updelay 200

Per maggiori dettagli si guardi /usr/share/doc/ifenslave/README.Debian e /usr/src/linux/Documentation/networking/bonding.txt.

Configurazione - Esempio 2 ("Modalità laptop")

Connettere le interfacce di rete cablata e wireless insieme (RJ45/WLAN) per definire un'unica interfaccia di rete virtuale ("bonding"), chiamata ad es. bond0.

Fintanto che il cavo di rete è connesso la sua interfaccia (es. eth0) viene usata per il traffico di rete. Se si disconnette la spina RJ45, ifenslave passa all'interfaccia wireless (es. wlan0) in modo trasparente, senza alcuna perdita di pacchetti di rete.

Dopo aver riconnesso il cavo di rete, ifenslave torna a eth0 ("modalità failover").

Dal punto di vista dell'esterno (rete) non importa quale interfaccia sia attiva. Il device di bonding presenta il proprio indirizzo MAC definito via software (cioè virtuale), diverso dagli indirizzi MAC hardware di eth0 o wlan0.

Il server DHCP userà questo indirizzo MAC per assegnare l'indirizzo IP al device bond0. Perciò il computer ha il suo proprio unico indirizzo IP con cui può essere identificato. Senza il bonding ogni interfaccia avrebbe un proprio indirizzo IP.

Modificare il file /etc/network/interfaces:

# Definire gli slave
auto eth0
iface eth0 inet manual
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup
auto wlan0
iface wlan0 inet manual
    wpa-conf /etc/network/wpa.conf
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup

# Definire il master
auto bond0
iface bond0 inet dhcp
    bond-slaves none
    bond-primary eth0
    bond-mode active-backup
    bond-miimon 100

Notare: la configurazione soprastante è stata provata e funziona su Debian 6 e successive. L'ultima versione verificata è la Debian 9.8 (*). La configurazione va in qualche modo in controcorrente rispetto alla documentazione di interfaces, ifup e ifenslave e gli esempi in /usr/share/doc/ifenslave/examples/.

In teoria solo una interfaccia dovrebbe avere l'attributo auto. ifup bond0 attiverò automaticamente gli slave (come dice la documentazione). Ciò è vero in parte ma ovviamente le opzioni di configurazione degli slave vengono ignorate. Ad esempio wlan0 viene attivata senza avviare wpa_supplicant e l'impostazione bond-primary di eth0 viene ignorata. (TODO: È un bug di ifenslave?)

Sembra che gli slave debbano essere attivati prima di bond0 per includere le loro opzioni di configurazione. Per farlo usando lo script /etc/init.d/networking, le loro definizioni devono precedere quella di bond0 e devono essere impostati gli attributi auto.

Naturalmente non devono essere riattivati di nuovo quando si attiva bond0. L'opzione bond-slaves none disabilita ciò. Le opzioni bond-master, bond-primary e bond-mode devono essere ripetute coerentemente per ogni slave.

Si genereranno avvertimenti del tipo "ifup: interface xyz already configured", ma almeno funziona.

(*) Con le versioni più nuove di Debian i nomi dei device di rete (possono) sono cambiati, a seconda del percorso di aggiornamento. Le installazioni da zero usano ora "nomi delle interfacce di rete prevedibili" (https://wiki.debian.org/NetworkConfiguration#Predictable_Network_Interface_Names). Per trovare i nomi delle interfacce guardare in: $ ls /sys/class/net/ 

Questo documento usa ancora i nomi tradizionali.

Configuratione - Esempio 3 ("Modalità portatile", per lo più come descritto nella documentazione - Debian 9 "stretch")

Questo è un modo per attivare la modalità portatile con ripiego automatico tra connessione wireless e cablata, con quella cablata come preferita se sono entrambe disponibili. È basato sulla documentazione; tuttavia l'esempio nella documentazione non è completo e non è del tutto corretto. In particolare le modifiche nell'esempio (usr/share/doc/ifenslave/examples/ethernet+wifi) sono:

Detto questo ecco il fantastico /etc/network/interfaces risultante:

auto bond0
iface bond0 inet static
    bond-slaves wlan0 eth0
    bond-mode active-backup
    bond-primary eth0
    bond-miimon 100
    address <ipv4address>/<maskbits>
    gateway <ipv4address>

allow-bond0 eth0
iface eth0 inet manual

allow-bond0 wlan0
iface wlan0 inet manual
#    bond-give-a-chance 10
    wpa-bridge bond0
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Se si usa DHCP o qualche altro servizio, è necessario cambiare la sezione "bond0" di conseguenza, ma le altre interfacce devono rimanere "manual", dato che non dovrebbero ottenere un indirizzo IP.

Fare il bridge con il bond

Se si vuole usare il bond in un bridge, aggiungere semplicemente le righe del bridge come di consueto nel proprio file /etc/network/interfaces. Modificare l'interfaccia di interface a "manual" e usarla come interfaccia bridge. Ecco un file d'esempio per interfacce bond con bridge:

# onboard network interface
auto enp4s0
iface enp4s0 inet manual
# PCIe nic
auto enp8s0
iface enp8s0 inet manual
# bond inteface
auto bond0
iface bond0 inet manual
        slaves enp4s0 enp8s0
        bond-mode 802.3ad
# bridge interface
auto br0
iface br0 inet static
        address 192.168.1.17
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        gateway 192.168.1.1
        bridge_ports bond0
        bridge_stp off
        bridge_fd 0
        bridge_maxwait 0

Usare systemd-networkd

Questo metodo non usa il pacchetto ifenslave ricordato sopra. Se il proprio computer usa systemd e le schede di rete funzionano non è necessario fare altro. Notare che, come è prassi comune nei sistemi operativi in stile UNIX, le maiuscole e le minuscole contano: "Bond" è diverso da "bond" e "Nome" non è la stessa cosa di "nome".

Abilitare systemd-networkd

Se non si sta già usando systemd-networkd, è necessario abilitarlo.

systemctl enable systemd-networkd

Configurare il device di bond

Creare un file con estensione .netdev in /etc/systemd/network. Chiamarlo usando il nome dell'interfaccia con il bond che si vuole usare (es. bond0.netdev).

Questo esempio presume un bonding 802.3ad o LACP, per maggiori informazioni vedere la pagina di manuale disystemd.netdev o la documentazione del kernel.

La maggior parte dei sistemi dovrebbe funzionare con 802.3ad e questa è probabilmente la modalità che si vorrà usare dato che ha le schede di rete che lavorano assieme per dare il doppio del tasso di scambio di dati. Se, tuttavia, nel proprio caso non funziona si può provare un'altra modalità, come active-backup (usata nell'esempio ifenslave soprastante).

Notare che systemd crea sempre un'interfaccia predefinita bond0 che modalità "balance round robin" e la modalità non può essere modificata. Perciò, per usare qualsiasi altra modalità, creare bond1 o un altro nome per l'interfaccia. L'interfaccia bond0 con modalità 802.3ad semplicemente non funzionerà.

[NetDev]
Name=bond1
Description=LAG/Bond ad uno switch
Kind=bond

[Bond]
Mode=802.3ad

Aggiungere interfacce al bond/lag

Ci sono due modi per farlo. Uno è di creare un file .network per ogni interfaccia di rete, più uno per la rete con bonding. L'altro è di descrivere le interfacce di rete nel file della rete con bonding. Qui viene usato quest'ultimo metodo.

Creare un file con estensione .network in /etc/systemd/network usando lo stesso nome usato prima (es. bond1.network).

systemd-networkd usa un sistema di corrispondenze per decidere quale interfaccia usare. Si possono usare le corrispondenze basate sui nomi se si preferisce, ma non usare le corrispondenze basate su MAC dato che può creare confusione con il bond che cambia gli indirizzi MAC.

Questo esempio usa le corrispondenze basate su ID PCI. Per trovare gli indirizzi per le proprie schede di rete usare:

lspci -d | grep Ether

poi usare tali informazioni per creare il file .network.

[Match]
Path=pci-0000:00:01.0
Path=pci-0000:05:10.0

[Network]
Bond=bond1

Un'altra opzione è quella di usare semplicemente i nomi delle interfacce di rete sostituendo la riga Path= con Name=<nome-interfaccia-rete>. Si possono usare anche metacaratteri e si possono specificare entrambi/tutti i device in un unico file:

[Match]
Name=enp*

[Network]
Bond=bond1

o

[Match]
Name=enp0s01
Name=enp5s10

[Network]
Bond=bond1

Dare un IP al bond

Creare un file con estensione .network in /etc/systemd/network. Il nome (ovviamente) non dovrebbe essere già in uso. Questo dice a systemd di attivare la rete con bonding. Per un indirizzo IP statico si può usare:

[Match]
Name=bond1

[Network]
Address=10.31.1.5
Gateway=10.31.1.1
DNS=10.31.1.1

Per il DHCP (es. per un portatile dove si possono usare connessioni wireless o cablate) provare:

[Match]
Name=bond1

[Network]
DHCP=yes

Rendere attive le impostazioni

Se la rete stava usando /etc/network/interfaces prima di impostare il bonding, rinominare il file per impedire che venga usato:

mv /etc/network/interfaces /etc/network/interfaces.save

A questo punto è raccomandato riavviare il sistema. È il modo più semplice per ripulire ogni configurazione di rete precedente e testare che systemd-networkd si avvii come atteso. La rete dovrebbe venir attivata con il bonding in funzione. Lo si può verificare con:

ip link list

Si dovrebbero vedere 4 device: lo, due interfacce di rete fisiches (indicate come "SLAVE") e il device bond1. solo il device bond1 dovrebbe avere un indirizzo IP. Dovrebbe anche essere indicato come "MASTER".

Se è necessario fare altre modifiche in seguito, o risolvere problemi con le attuali impostazioni, da questo momento in poi si può semplicemente riavviare systemd-networkd dopo aver aggiornato i file /etc/systemd/network.

systemctl restart systemd-networkd

Abilitare il bridging per le macchine virtuali

Questa sezione è stata aggiunta perché all'autore non era immediatamente ovvio perché la sua configurazione di rete bridge esistente non funzionasse con systemd-networkd. Prima di impostare il bond di rete, usava le utilità bridge per creare un device br0 usando /etc/network/interfaces. Una volta rimosso tale file era necessario un nuovo modo per impostare il bridge.

Fortunatamente systemd-networkd ha molti talenti ed è piuttosto bravo a gestire i bridge di rete. Tutto ciò che è necessario fare è definire il bridge ed assegnarli le caratteristiche appropriate.

Come per il device bond0, è necessario creare un file .netdev per definire il device. Chi scrive ha creato br1.netdev come segue:

[NetDev]
Name=br0
Kind=bridge

Poi ha fatto il collegamento al bond di rete definito in precedenza usando br0.network:

[Match]
Name=bond1

[Network]
Bridge=br0

Da ultimo ha modificato il file .network in modo che facesse riferimento a br0 invece che a bond1. Dato che le definizioni precedenti hanno reso bond1 uno slave di br0, ciò risulta nella corretta attivazione del bridge.

Problema del cambio di nomi di udev

Probabilmente si vedranno solo regole UDEV per i dispositivi di rete se si ha aggiornato da versioni precedenti di Debian. Le nuove installazioni danno i nomi alle schede di rete in base ai loro indirizzi PCI. Le regole sono usate per preservare i nomi obsoleti per i device (es. eth0) nel caso vengano usati altrove.

Se si è sicuri di non usare i nomi obsoleti si può semplicemente rimuovere il file descritto in seguito.

"udev" assegna nomi agli adattatori di rete sulla base di

/etc/udev/rules.d/70-persistent-net.rules

dove una regola tipicamente ha il seguente formato:

# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Il problema con il bonding è che due o più NIC possono avere lo stesso identico indirizzo MAC e ciò confonde udev quando cerca di (ri)assegnare i nomi agli adattatori sulla base dei loro indirizzi MAC e quindi fallisce perché esiste già una scheda con lo stesso indirizzo MAC. Quando ciò avviene i NIC possono rimanere con nomi come "rename2" invece di "eth0", ecc.

Una possibile soluzione è cambiare la regola udev in modo che assegni i nomi alle interfacce di rete sulla base degli ID PCI dei NIC, invece che in base agli indirizzi MAC. Ciò può essere fatto sostituendo

ATTR{address}=="xx:xx:xx:xx:xx:xx"

con qualcosa di simile a

KERNELS=="0000:04:00.0"

nel file "70-persistent-net.rules". Gli ID PCI corrispondenti possono essere trovati in dmesg:

sudo dmesg | grep eth

dove si possono cercare frammenti di riga simili a:

r8169 0000:04:00.0 eth0: RTL8168e/8111e
#     ^^^^^^^^^^^^

Tuttavia questo non è raccomandato dato che non trova, ad esempio, i dispositivi wireless o dispositivi che non usano i nomi obsoleti.

L'alternativa preferibile è quella di trovare gli ID PCI usando "lspci -D | grep Ether":

0000:04:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 06)

Notare che nei sistemi moderni si può tradurre l'indirizzo PCI nel nome di rete usando i due numeri di mezzo espressi in base 10. Nell'esempio soprastante il controllore 0000:04:00.0 sarebbe enp4s00.

Test/Debug

Suggerimento

Allo scopo di capire meglio ciò che succede dietro alle quinte, mentre si sperimenta può essere utile un piccolo script per mostrare alcune informazioni sul device di bonding.

#! /bin/sh

echo "Slaves = $(cat /sys/class/net/bond0/bonding/slaves)"
echo "Primary = $(cat /sys/class/net/bond0/bonding/primary)"
echo "Active Slave = $(cat /sys/class/net/bond0/bonding/active_slave)"

r=$(pidof dhclient)
test -n "$r" && ps $r

r=$(pidof wpa_supplicant)
test -n "$r" && ps $r

Debug di ifenslave

Il meccanismo di bonding è basato su un modulo del kernel chiamato bonding che espone la sua interfaccia attraverso il file system virtuale /sys (es. /sys/class/net/bond0/*).

L'impostazione e la configurazione viene fatta in spazio utente con gli script:

Questi script vengono chiamati all'inizializzazione del sistema e allo spegnimento (in realtà è ifup che li chiama). Il loro scopo è di passare al modulo del kernel gli appropriati parametri e impostazioni.

Se qualcosa va storto con il bonding (e il suggerimento visto prima non funziona) si può dover guardare a ciò che gli script fanno passo-passo.

Per abilitare l'output prolisso, invocare direttamente ifup -a -v (invece di invocare /etc/init.d/networking). L'opzione -v abilita un registro di tutti i comandi che vengono eseguiti dagli script. Ciò fornisce almeno una traccia di ciò che sta succedendo e quando.

Sfortunatamente ciò non mostra le reazioni del modulo del kernel (come eventuali messaggi di errore), dato che i messaggi del (modulo del) kernel vengono riportati usndo l'utilità syslog.

Per ottenere una reale vista all'interno di ciò che sta succedendo è necessario fare ciò che viene definito debug invasivo. Ciò significa aggiungere righe in punti critici degli script per inviare un messaggio al syslog.

Esempio:

Funzione sysfs_change_down nel file /etc/network/if-pre-up.d/ifenslave

        logger -t sysfs_change_down sysfs "$1" "$2"
  sysfs "$1" "$2"
        logger -t sysfs_change_down $(cat /sys/class/net/bond0/bonding/mode)

Note aggiuntive per Debian Lenny su Sparc

(potrebbe essere applicabile anche ad altre architetture)

# cd /etc/modprobe.d

# cat > aliases-bond.conf
alias bond0 bonding
  options bonding mode=1 arp_interval=2000 arp_ip_target=192.168.3.1
<CTRL-D>

Senza questo file, durante l'avvio dell'interfaccia unita si otterrà un avvertimento simile a questo:

bonding: Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.

Avvio / Configurazione delle nuove interfacce

# ifup bond0
# /etc/init.d/networking start

Inoltre, se si sta usando un ambiente Lenny che è stato aggiorndato da Etch, si raccomanda caldamente di verificare il risultato del seguente comando per verificare la modalità dell'interfaccia «bonding», perché i file di configurazione per Etch e versione più vecchie non funzionano su Lenny o versioni successive.

cat /sys/class/net/bond0/bonding/mode

Test

1. Fare un ping verso un altro sistema nel terminale

# ping X.X.X.X

2. Disconnettere il cavo di rete attiva e guardare il risultato del ping, la rete dovrebbe essere ripristinata in pochi secondi.

3. Riconnettere il cavo di rete disconnesso, aspettare 30 secondi per permettere alla tabella ARP di essere aggiornata

4. Disconnettere un altro cavo di rete e guardare i risultati del ping, la rete dovrebbe essere ripristinata in pochi secondi

Cambiare lo slave attivo

1. Usare ifenslave per cambiare lo slave attivo. L'esempio sottostante imposterà eth0 come slave attivo

# ifenslave -c bond0 eth0 eth1


CategoryNetwork