Non sono del tutto convinto che la mia soluzione sia corretta, ma posso almeno fare un po' più di luce su quello che sta succedendo.
Sfondo
Linux in realtà ha più tabelle di instradamento e vengono cercate una alla volta in un ordine di priorità specifico fino a quando non viene trovata una tabella con una rotta corrispondente. Puoi facoltativamente cercare alcune delle tabelle di routing in base all'indirizzo o al protocollo di origine; vedere il ip-rule(8)
pagina man.
Il guaio è la tabella di instradamento "locale", che ha priorità 0, la più alta possibile. La tabella "locale" viene popolata automaticamente dal kernel e contiene l'interfaccia "ovvia" e le rotte di trasmissione. Per IPv6 sotto Linux, questo include apparentemente l'intero blocco multicast.
Il problema
Userò iproute2 strumento piuttosto che il più tradizionale route
, perché mi mostrerà tutto quello che devo sapere.
Sulla mia macchina Linux:
$ ip -6 route show table local
local ::1 via :: dev lo proto none metric 0
local fe80::213:a9ff:fe91:5bcb via :: dev lo proto none metric 0
local fe80::250:b6ff:fe44:37d1 via :: dev lo proto none metric 0
ff00::/8 dev eth0 metric 256
ff00::/8 dev eth1 metric 256
$ ip -6 route show table main
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth1 proto kernel metric 256
ff15::/16 dev eth1 metric 1024
ff00::/8 dev eth1 metric 1024
$ ip -6 rule show
0: from all lookup local
32766: from all lookup main
...E i miei pacchetti multicast per ff15::1 (5==site-local,>link-local) finiscono su eth0, perché la tabella di routing "locale" corrisponde per prima e sovrascrive la tabella "principale", anche se il La tabella "principale" ha un percorso più specifico. Questo comportamento di override è corretto nel più ampio schema di policy routing, ma la scelta di aggiungere automaticamente ff00::/8 alla tabella locale è discutibile per me.
La mia soluzione
Non ho abbastanza esperienza per sapere se è una buona idea, ma:
# ip -6 route add ff15::/16 dev eth1 table local
e ora i miei pacchetti ff15::1 vengono instradati attraverso eth1.
Ciò concorda in qualche modo con la semantica della tabella locale, in quanto viene instradata direttamente attraverso un dispositivo. Non sembra esattamente giusto (considerando la gestione automatica e "non dovresti guardare questa tabella"), ma è la soluzione migliore che ho trovato.