Routa nepřejde do stavu linkdown/dead

Routa nepřejde do stavu linkdown/dead
« kdy: Dnes v 11:55:01 »
Mám na linuxu staticky definované routy. Jednu síť (třeba 77.0.0.0/8) mám via 192.168.1.50 přes pobočný PC, sám tento počítač je součástí 192.168.1.3/24.

je to propojeno switchem. Pokud vypnu switch nebo kabel z toho pobočného 50 a zkusím ho (...1.3) pingnout samozřejmě dostanu ICMP host unreachable.  a do této sítě se samozřejmě nedostanu (v případě default ani na internet)

Proč ale se toto nepropíše  (automaticky, klidně po nějakém zpoždění kvůli arp třeba) do ip route show na routeru?
Očekávám, že routy označené (vypsané, ne nastavené) s příznakem dead, deadlink, linkdown, linkinpark, deadcat, down (existuje opravdu vše, pátral jsem po rozdílu mezi nimi, linkdown je když manuálně vypnu interface) se nepoužijí a v tom případě použije routa s nižší metrikou. To je možné důležité, protože na tu síť se jde dostat i jinou routou, třeba i default routou.

Je nějaký mechanismus u statického routingu, že když mám 77/8 nebo default  via 192.168.0.50  a ten "via host" bude unreachable, že taková routa se prohlásí za dead nebo down a automaticky se přeskočí, aniž by se musela mazat z route tabulky? na multihop route jsem  se ptal a nedostal doporučení na tento účel. Myslel jsem, že v tomhle je linux chytrý, že pokud je nexthop unreachable, (a ping hlásí na tohoto hosta host unreachable), že takový routa bude očerněna.
Jenže ip route  vypisuje vše jako kdyby se nic nedělo


a existuje utilita ip sla?  Je něco z utilit ip *, co mi může pomoc v tomhle?
chová se default route v něčem jinak ?
« Poslední změna: Dnes v 11:59:04 od mikesznovu »


jjrsk

  • *****
  • 524
    • Zobrazit profil
Re:Routa nepřejde do stavu linkdown/dead
« Odpověď #1 kdy: Dnes v 12:16:59 »
A jak bys asi tak cekal, ze router zjisti, ze routa je nedostupna?

On to nema jak zjistit, na to potrebujes dynamicky routing.

Re:Routa nepřejde do stavu linkdown/dead
« Odpověď #2 kdy: Dnes v 12:52:43 »
Jestli bez náčrtku správně chápu tazatele, jde mu o to, že linux se snaží používat next-hop, figurující v kernelové routovací tabulce, přestože minimálně v ARP tabulce nemá pro tento next-hop ARP záznam (protože mít nemůže, protože někde L2 cestou zvadla konektivita). Já dodám, že se to tak chová zřejmě by default i v případě, že padnul dokonce L2 link na daném rozhraní, kde je "locally connected subnet" obsahující next hop. To sledování linku se tuším dá nějak ošetřit... každopádně za mě: dal bych na oba stroje Quaggu/frrouting, jakožto známku punku BGP s krátkým keepalive, a ať se hoši dohodnou...

timers bgp 4 17

BGP je sice nominálně exterior routing protocol, ale má tu příjemnou vlastnost, že nepotřebuje vidět pád linku, aby zareagoval - očuchá si konektivitu na své úrovni těmi keepalive zprávami. Na rozdíl od spousty IGP.

jjrsk

  • *****
  • 524
    • Zobrazit profil
Re:Routa nepřejde do stavu linkdown/dead
« Odpověď #3 kdy: Dnes v 17:40:47 »
Prave na pady linek je mnohem lepsi ospf protoze reaguje mnohem rychlejs nez bgp. Ve velkym netu se to nepouziva proto, ze to ma tu vlastnost, ze to potrebuje znat stav vsech linek.

A ano, ten stroj jakoze "vi" ze link je down, ale staticka routa = do nejake tabulky je napsano ze patety se maji posilat nekam. Tecka. On se neumi rozhodnout, ze je znicehoz nic ma posilat jinam.

Ostatne routovaci demoni nedelaji nic jinyho nez ze na zakladne nejakych vnejsich informaci do te tabulky zasahuji. A v principu se to co tazatel chce da realizovat scriptem v cronu ... jen to bude "fungovat" presne podle toho.

Re:Routa nepřejde do stavu linkdown/dead
« Odpověď #4 kdy: Dnes v 21:58:24 »
OSPF reaguje okamžitě v případě, že samotnému routeru padne link na fyzickém portu. V tom případě je OSPF naprosto skvělé.
Pokud jsou ale mezi dvěma routery např. dva switche, a padne spoj mezi těmi switchi, tak oběma těm routerům fyzický link zůstane nahoře. A OSPF dlouho dál tvrdošíjně routuje pakety tou mrtvou cestou.

Třeba "bonding driver" v linuxu má option zvanou "miimon", pomocí které ho lze nakonfigurovat, aby si hlídal link state a pro své potřeby se jím řídil - což může dělat pomocí MII ioctl(), ethtool ioctl(), nebo voláním netif_carrier_ok() což je default. (Funkce netif_carrier_ok() žije v kernelu, což není problém, protože bonding driver žije tamtéž.) Ale bonding driver si podle toho řídí jenom svoje vlastní failovery, routovací tabulku/rozhodování to podle všeho neovlivňuje.

Zkusil jsem se zběžně podívat pod kapotu, která oblast ve zdrojácích kernelu se routingu konkrétně týká. Teda spíš jsem se rozhlédl po webu, jestli o tom někdo nesepsal hezké povídání pro lenocha jako jsem já :-)
Tady je docela dobrý začátek, je tam zmíněno pár relevantních funkcí, zejm. fib_lookup() resp. fib_table_lookup().
Odtud vede odkaz na moc pěkný webík, kde jsou hezky v kostce popsány stromové struktury, ve kterých je v kernelu udržována routovací tabulka (FIB, Forwarding Information Base).
Na tomto webíku je zmínka o objektu struct fib_info což vypadá jako jeden záznam v routovací tabulce.
Ten se dále odkazuje na struct fib_nh (= Next Hop) a jeho prostřednictvím na struct fib_nh_common - který už obsahuje pointer na struct net_device, kde by se asi dalo doptat na okamžitý stav rozhraní (zda je "running").

Zarazil jsem se zhruba ve chvíli, kdy bych měl začít zkoumat vnitřnosti funkce fib_table_lookup(). To by bylo vážně na delší ponor. Dovolím si shrnout dojmy:

Routovací tabulka je v kernelu uskladněna v pokročilé stromové struktuře, která je vtipně interně komprimována dvěma způsoby: "path-compressed" a "level-compressed". Zmíněná datová struktura a vyhledávací funkce jsou optimalizovány na rychlost vyhledávání (procházení stromem). Zmíněný webík z roku 2017 tvrdí, že tehdejší plná routovací tabulka vytvoří strom o maximální hloubce 6 nebo 7 uzlů a (maximální? mediánová?) latence procházení je asi 50 ns, na vcelku běžném Haswell CPU.
V datových strukturách jsem si při letmém čenichání nevšiml nějaké informace o "stavu next-hopu", podle které by bylo možno "routovací záznamy náležející zhaslému rozhraní" při prohledávání ignorovat / přeskakovat nebo tak něco. Teoreticky by se dalo, doskákat několik dalších pointer indirections a zkontrolovat to přímo na síťovém rozhraní (struct net_device). Nebo by "něco" muselo cyklicky procházet FIB strom a cinkat jednotlivé záznamy (fib_info), které mají zrovna down příslušný next_hop interface. Není mi bez dalšího dumání jasné, nakolik by zaplevelení FIB takovými "potlačenými" záznamy zkomplikovalo vyhledávání živého next_hopu (procházení stromem). Ale v zásadě: vzhledem k důrazu na co nejefektivnější vyhledávání v tabulce (stromě) mi dává smysl, že se toto prostě nedělá. Ne per packet. Beru to jako zralé návrhové rozhodnutí. Znamenalo by to latenci navíc, a zátěž CPU.

Ještě by se dalo uvažovat, že v kernelu bude FIB "dvouúrovňová": horní "managementová" úroveň by držela všechny záznamy, a byla by nějak cyklicky "zrcadlena" do spodní "provozní" FIB tabulky, ze které by byly vyplety "potlačené" routovací záznamy. Hm. I tady zcela chápu, že se správcům nechtělo udržovat takovou složitost přímo v kernelu, když totéž a mnoho dalšího snadno zařídí dedicated routing daemon žijící v user space. Prostě "keep it simple". Čím víc o tom přemejšlím, tím víc maintainery chápu.

OT: Cestou jsem narazil na zajímavou stránku Interactive Linux Kernel Map - která mi připadá zábavná, přestože konkrétně výše zmíněnou oblast cudně zamlčuje :-) Tzn. ten hezký barevný pavouk nebude zdaleka úplný...