yoel caspersen blog bloghoved

En Linux-router med MPLS

Sidste forår kiggede vi på risikoen for, at Huawei ville blive en del af handelskrigen mellem USA og Kina, og jeg efterspurgte et alternativ til ZTE, som på daværende tidspunkt netop havde fået lukket sin livsvigtige forsyning af amerikanske komponenter.

ZTE indgik et forlig med det amerikanske handelsministerium og overlevede med nød og næppe, men presset på Huawei er siden taget til - de beskyldes nu åbent for spionage og overtrædelse af internationale handelssanktioner, og Canada har med anholdelsen af Huaweis finansdirektør fået et diplomatisk problem på halsen, man i Ottawa nok gerne ville have været foruden.

I dag skal det dog ikke handle om storpolitik, men om lavpraktisk teknik.

Vi har brug for et alternativ til kinesiske routere og switches, og selv om det fra et teknisk synspunkt ville være nemt at gå over til Juniper ligesom mange andre internetudbydere, har jeg taget endnu et kig på software-routing som et mere fleksibelt alternativ til de traditionelle hardware-routere.

I slutningen af sommeren sidste år foreslog jeg en prototype til en Linux-baseret BNG, som er den komponent i et ISP-netværk, der udgør den enkelte kundes default gateway og dermed adgangen til internettet.

Jesper Brouer fra Red Hat tilbød sin hjælp til at bygge en forbedret løsning vha. XDP, og gennem efteråret og vinteren har jeg i de ledige stunder, der har været, kodet på en prototype.

Den skal vi høre mere om på et senere tidspunkt, men lige nu og her skal vi se, hvordan man kan bygge en edge-router til et ISP-netværk baseret på en Linux-server.

Hardware-konfiguration

Vi bygger routeren på en server fra Supermicro med følgende specs:

  • 2U chassis med redundant PSU
  • Supermicro MB X10SRi-F bundkort
  • Intel Xeon E5-1650v4 CPU - 6-Core 3.60GHz
  • 4 x 8GB DDR4 2666MHz ECC Registered 2Rx8
  • 2 x Samsung SM863 SSD - 240GB SATA3
  • Supermicro Intel XL710-AM1 DA netkort, 4 x 10 Gbit/s SFP+

Serveren er indkøbt hos Nextron, som håndbygger den til os. Den kommer med et sæt slide rails, så vi kan montere den pænt i vores rack.

Illustration: Yoel Caspersen

Specifikationerne på serveren er valgt, så vi har en standardplatform, vi både kan bruge til edge router og BNG. Til begge dele får vi på sigt brug for XDP, og det er derfor vigtigt, at netkort-driveren understøtter XDP.

Herfra skal der lyde en særlig tak til Jesper Brouer for gode råd og vejledning i forhold til valg af hardware, software og Linux-kernen generelt.

Operativsystem

Vi installerer Ubuntu 18.04 på serveren og skynder os at opgradere Linux-kernen til version 4.18. Egentlig vil jeg gerne op på version 4.20, men i første omgang har vi brug for at kunne kompilere XDP-eksemplerne fra Jesper Brouers repository.

Canonical, som står bag Ubuntu, har valgt at skifte de gamle ifupdown-værktøjer ud med Netplan. Det betyder også et farvel til den gamle konfiguration i /etc/network/interfaces, som jeg efterhånden kunne på fingerspidserne.

I stedet skal serverens IP-adresser nu konfigureres i en YAML-fil i /etc/netplan/ og efterfølgende committes med kommandoen netplan apply.

Simple netværksopsætninger kan testes med kommandoen netplan try, som ruller ændringerne i opsætningen tilbage, hvis man mister forbindelsen til serveren - det er ret smart, hvis man ændrer netværksopsætningen remote, men desværre virker det ikke sammen med LACP-bonding, som vi skal bruge i vores opsætning.

Konfigurationsfilen til Netplan er nogenlunde ligetil, og man kan finde eksempler på de mest gængse opsætninger her.

Opsætning af LACP-bonding giver lidt flere udfordringer. Først skal man installere ifenslave, hvorefter man sætter en parameter for bonding-modulet i /etc/modprobe.d/bonding.conf:

options bonding miimon=100

Herefter kan man opsætte bond-interfacet i Netplan:

    bonds:
       bond1:
          addresses: []
          interfaces: [ens5f1, ens5f2, ens5f3]
          parameters:
              mode: 802.3ad
              lacp-rate: fast
              transmit-hash-policy: layer3+4
              mii-monitor-interval: 100

Det lykkedes mig at finde en bug, enten i Netplan eller i firmwaren til netkortet: Hvis jeg kører kommandoen netplan apply, går linket bond1 i ca. 50 % af tilfældene ned, fordi linket forsvinder fra de underliggende interfaces (ens5f1, ensf52, ens5f3). Kører jeg herefter netplan apply igen, eller manuelt sætter link på de underliggende interfaces, kommer bond1 op igen.

Det er en lidt kritisk bug for en router, og jeg har derfor skrevet mig bag øret, at jeg aldrig må køre netplan apply, mens routeren kører i produktion. I stedet må jeg nøjes med at tilføje nye interfaces manuelt vha. ip link add, skrive dem ind i Netplans konfigurationsfil, så de kommer op igen næste gang routeren genstartes, og så køre netplan generate, så jeg er sikker på, konfigurationsfilen er syntaktisk korrekt.

Netkortet kører firmware version 5.05, og den nyeste version fra Intel er 6.80. Desværre har Supermicro kun stillet version 6.01 til rådighed, og da kortet er et rebrandet OEM-kort fra Intel, kan jeg ikke installere Intels firmware, men må nøjes med den fra Supermicro.

Når jeg har valgt et Intel-kort fra Supermicro, skyldes det, at jeg ikke har kunnet finde kortet til en fornuftig pris i original Intel-udgave.

Routing daemon

Som routing daemon har jeg valgt FRRouting, der understøtter et væld af forskellige protokoller, bl.a. BGP og OSPF, som jeg skal bruge. Jeg henter den nyeste version 7.1-dev fra Github:

git clone https://github.com/FRRouting/frr.git

Vi bygger FRRouting fra source, da jeg gerne vil bestemme præcis, hvilke protokoller, den skal understøtte - fx vil jeg gerne have indbygget support for Equal Cost Multi-Path Routing (ECMP).

Vi tuner også kernen til netværk i /etc/sysctl.conf:

# Asymmetric routing
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
 
# IP forwarding
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
 
# Log martians
net.ipv4.conf.all.log_martians = 1
 
# BGP across VRF instances
net.ipv4.tcp_l3mdev_accept=1
 
# MPLS
net.mpls.conf.ens5f0.input=1
net.mpls.platform_labels=100000
 
# VRRP
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.conf.all.accept_local=1
net.ipv4.conf.default.accept_local=1
 
# Tuning for high bandwidth
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_congestion_control = htcp
net.ipv4.tcp_mtu_probing = 1

Vi skal også have tunet netkortet. Vi starter med at deaktivere irqbalance:

systemctl disable irqbalance.service
systemctl stop irqbalance.service

Herefter sætter vi IRQ affinity vha. Intels script:

./set_irq_affinity.sh local ens5f0
./set_irq_affinity.sh local ens5f1
./set_irq_affinity.sh local ens5f2
./set_irq_affinity.sh local ens5f3

Herved fordeler vi interrupts fra de enkelte receive queues på netkortet jævnt over CPU'ens kerner, og vi sikrer, at interrupts fra en receive queue altid går til den samme CPU-kerne.

Da netkortet fordeler indgående trafik på de forskellige receive queues vha. Receive Side Scaling (RSS), opnår vi i praksis, at pakker, der tilhører samme flow, bliver behandlet af samme CPU-kerne. Derved holdes CPU-cachen varm, og i teorien bør det give en performance-forbedring.

Hyper-threading er også blevet deaktiveret i serverens BIOS efter anbefaling fra Intel.

Test-setup

Nu er det blevet tid til at sætte testmiljøet op.

Illustration: Yoel Caspersen

Vi starter med at definere vores VRF'er. Siden mine første forsøg med Quagga tilbage i 2016 er der sket noget ret smart: Cumulus har udviklet et VRF-interface til Linux.

Vi skal bruge tre VRF'er:

  • Default VRF (MPLS)
  • mgmt (management)
  • kviknet (internet)

Default VRF eksisterer i kraft af den normale route-tabel i Linux. Vi opretter derfor de to andre VRF'er:

ip link add mgmt type vrf table 10
ip link set mgmt up
ip link add kviknet type vrf table 20
ip link set kviknet up

Herefter kan vi tilføje interfaces til vores VRF'er - i dette tilfælde VLAN-interfaces:

ip link set dev vlan1337 master mgmt
ip link set dev vlan1337 up
ip link set dev vlan82 master kviknet
ip link set dev vlan82 up

Næste step i vores test er at få sat MPLS op.

Vi enabler MPLS på det ene af de fire 10 Gbit/s-interfaces og sætter OSPF op vha. vtysh, som er CLI'en til FRRouting.

interface ens5f0
 ip ospf network point-to-point
!
router ospf
 ospf router-id 10.128.4.1
 redistribute connected
 redistribute static
 network 10.0.0.0/8 area 0
!

Vi sætter IP-adressen 10.128.4.1/31 på ens5f0 i Netplan:

        ens5f0:
            dhcp4: false
            addresses:
               - 10.128.4.1/31

Så forbinder vi interfacet til en hardware-router af typen ZTE M9000, der kører MPLS.

Derefter opsætter vi LDP, som bruges til udveksling af MPLS labels:

mpls ldp
 router-id 10.128.4.1
 !
 address-family ipv4
  discovery transport-address 10.128.4.1
  !
  interface ens5f0
  !
 exit-address-family
 !
!

Der er nu hul igennem til vores MPLS-netværk - vi kan se routes, som vores software-router har lært gennem OSPF:

intx-edge1# show ip route ospf 
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route
O>* 10.128.0.0/30 [110/13] via 10.128.4.0, ens5f0, label 17639, 0d00h02m
O>* 10.128.1.1/32 [110/20] via 10.128.4.0, ens5f0, label 17650, 0d00h02m
O>* 10.128.1.2/32 [110/20] via 10.128.4.0, ens5f0, label 17664, 0d00h02m
O>* 10.128.3.0/31 [110/13] via 10.128.4.0, ens5f0, label 17628, 0d00h02m
O>* 10.128.3.2/31 [110/13] via 10.128.4.0, ens5f0, label 17630, 0d00h02m

Ping virker også:

intx-edge1# ping 10.128.3.0
PING 10.128.3.0 (10.128.3.0) 56(84) bytes of data.
64 bytes from 10.128.3.0: icmp_seq=1 ttl=253 time=0.731 ms
64 bytes from 10.128.3.0: icmp_seq=2 ttl=253 time=2.52 ms
64 bytes from 10.128.3.0: icmp_seq=3 ttl=253 time=0.785 ms
64 bytes from 10.128.3.0: icmp_seq=4 ttl=253 time=2.61 ms
^C

Så langt, så godt. Næste skridt er at sætte en MP-BGP session op.

MP-BGP, også kendt som multiprotocol BGP, er en extension til BGP, der gør det muligt at overføre routes fra flere forskellige protokoller over den samme BGP-session.

I praksis bruges det til at implementere L3VPN - routes fra forskellige VRF'er overføres vha. MP-BGP, og selve trafikken flyttes af det underliggende MPLS-netværk.

Routes fra forskellige VRF'er adskilles vha. route discriminators, der udveksles som en del af MP-BGP - som fx her, hvor vi konfigurerer VRF-instancen mgmt:

router bgp 204151 vrf mgmt
 !
 address-family ipv4 unicast
  rd vpn export 204151:2
  rt vpn import 204151:2
  import vpn
  export vpn
 exit-address-family
!

Det, der i praksis sker, er, at routes fra MP-BGP-sessionen i default VRF udveksles med VRF mgmt vha. route leaking.

Før jeg kan bruge MPLS-delen af vores software-router til noget, mangler jeg følgende elementer:

  • Pseudo-wires
  • VPLS

Pseudo-wires bruges, når man skal lave en L2VPN fra et punkt i nettet til et andet. VPLS er en virtuel switch, som emuleres i software.

Med pseudo-wires og VPLS kan jeg skabe en virtuel, distribueret switch - hvilket vi bruger i dag, når vi har servere i et datacenter, der skal forbindes til servere i et andet datacenter på layer 2-niveau.

Desværre er VPLS og pseudo-wires ikke understøttet i Linux endnu - men ifølge kompatibilitetslisten for FRRouting burde det kunne lade sig gøre, hvis man kører OpenBSD på sin software-router.

Jeg dropper derfor i første omgang vores MPLS-setup og kører i stedet vores software-router som en ren BGP-router - jeg har kun to VRF'er, der skal overføres, og det kan jeg klare ved at lave 2 separate BGP-sessioner.

Hastighedstest

Nu er det tid til at teste, hvor meget trafik vores router egentlig kan overføre.

Testen er yderst uvidenskabelig og foregår med en blanding af trafik fra vores Akamai cache og iperf3-sessioner fra nogle servere, der er forbundet med 10 Gbit/s interfaces til netværket.

Resultatet lyder på 19 Gbit/s med den fulde, globale route-tabel på ca. 762.000 routes.

Jesper Brouer har sammen med andre skarpe kerneudviklere begået et interessant paper under titlen The eXpress Data Path: Fast Programmable Packet Processing in the Operating System Kernel.

I dette finder vi bl.a. en sammenligning af route performance i Linux-kernen sammenlignet med route performance ved anvendelse af XDP.

Ifølge deres test burde vi med ren kerne-routing uden XDP kunne opnå ca. 1,3 Mpps pr. CPU core, hvilket under optimale forhold med 1500 bytes pakker svarer til 15 Gbit/s pr. core. Vores CPU har 6 cores, så vi burde i teorien kunne komme op på ca. 90 Gbit/s, da routing performance skalerer lineært med antallet af CPU cores.

Da vi har konfigureret 3 x 10 Gbit/s i et LACP-bond, kan vi i sagens natur ikke route mere end lige under 30 Gbit/s.

Når vi kun kommer op på 19 Gbit/s i vores test, skyldes det umiddelbart en skæv fordeling af trafikken i vores LACP-bond, hvor det enkelte 10 Gbit/s interface bliver maxet ud.

Real life trafik burde fordeles mere ligeligt og dermed give en højere kapacitet.

Vi har derfor testet routeren på et par udvalgte kunder for at se, om trafikken i realiteten bliver jævnt fordelt hen over de enkelte CPU cores - her et udpluk fra /proc/interrupts:

Illustration: Yoel Caspersen

Det ser umiddelbart fint ud - og hvis vi implementerer et anti-DDoS-filter baseret på XDP, har vi efterhånden en rigtig fornuftig edge router.

Jeg kunne dog godt tænke mig at få lavet en grundig hastighedstest, hvor vi kommer helt ud i hjørnene af, hvad der kan lade sig gøre - gode forslag fra læserne modtages gerne!

Relateret indhold

Kommentarer (45)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Kenn Nielsen

Canonical, som står bag Ubuntu, har valgt at skifte de gamle ifupdown-værktøjer ud med Netplan. Det betyder også et farvel til den gamle konfiguration i /etc/network/interfaces, som jeg efterhånden kunne på fingerspidserne.

Hvis du ikke ønsker at 'ting' pludseligt ændrer sig - i systemd's hellige navn - kan du kigge på Devuan.

Men; Tak for nogle altid relevante - og lærerige - blogindlæg !

Jeg ser frem til de næste :-)

K

Yoel Caspersen Blogger

Hvis du ikke ønsker at 'ting' pludseligt ændrer sig - i systemd's hellige navn - kan du kigge på Devuan.

Tak for tippet.

Jeg er lidt splittet omkring ændringerne i Ubuntu - det var dejlig simpelt, dengang et netkort hed eth0, eth1 osv., og en service blev genstartet gennem /etc/init.d/-scriptet.

Omvendt er der også nogle af ændringerne, der giver mening - især hvis man vil bygge en software-router, hvor netværksstakken er mere kompleks end normalt.

Fx er det simpelt at tilføje en ekstra IP-adresse til et interface gennem ip(8):

ip addr add 192.168.10.1/24 dev ens5f0

Hvis man skal gøre tilføjelsen permanent i /etc/network/interfaces, skal man ud i nogle mærkelige hacks som fx alias af interface eller en post-up-kommando, der tilføjer den ekstra IP-adresse vha. ip(8).

Her er Netplan oplagt en forbedring - man lister blot de IP-adresser, interfacet skal have:

ens5f0:  
    dhcp4: false  
    addresses:  
       - 10.128.4.1/31  
       - 192.168.10.1/24

Til gengæld virker Netplan stadig en smule halv-bagt, når man ikke kan stole på, et interface altid kommer op efter netplan apply.

Ændringen af interface-navne fra eth0, eth1 osv til de mere kryptiske eno1, ens5f0 etc., giver god mening, når det begrundes med, at man gerne vil have konsistent navngivning af interfaces, selv om hardwaren udskiftes, men jeg er ikke sikker på, den øgede kompleksitet står mål med det problem, man gerne vil løse.

På brugerfladen har jeg selv droppet den rene Ubuntu, efter man begyndte at efterligne macOS. Her kører jeg Ubuntu Mate, fordi jeg godt kan lide den måde, vinduer etc. organiseres på - den klassiske vis, hvor man har en task bar i bunden, hvor hvert åbent vindue har sit eget ikon etc. Men det er nok primært et spørgsmål om vane.

Christoffer Kelm Kjeldgaard

Fantastisk fint indlæg - Det er længe siden jeg har arbejdet med MPLS-netværk, og det er spændende at følge med her.

Jeg tænker dog på investeringen af en software-router kan stå mål med hardware-routere når det gælder drift. Jeg skal være ærlig og sige at jeg ved ikke meget om hvad en tilsvarende hardware MPLS-router koster mere kontra en velbestykket server som denne.

Er der nogle fordele og indhente på hhv. strømforbrug og indkøbspris mellem de 2 løsninger?

Jeg er fuldt ud klar over, at en software-router giver langt mere fleksibilitet - Men den koster vel også mere at sætte op og konfigurere, hvor man må forvente at hardware-routere allerede er tilpasset til at konfigurationen skal være lettere tilgængelig.

Hvad er årsagen til at I har valgt Ubuntu som basissystem? Mange hælder mere til Red Hat's Enterprise Linux og lign. i henhold til stabilitet og support.

Yoel Caspersen Blogger

Jeg tænker dog på investeringen af en software-router kan stå mål med hardware-routere når det gælder drift. Jeg skal være ærlig og sige at jeg ved ikke meget om hvad en tilsvarende hardware MPLS-router koster mere kontra en velbestykket server som denne.

Det er et godt spørgsmål. Hvis vi kigger på den rå indkøbspris, kan en server som den nævnte erhverves til et sted mellem 20.000 og 30.000 kr.

En Juniper MX204 koster et godt stykke over 100.000 kr. Den kan til gengæld også flytte væsentligt mere trafik, men jeg gætter på, licensprisen stiger, jo flere features man skal bruge.

Strømforbruget er nok en smule lavere på en dedikeret hardware-router af nyere dato, men her gætter jeg. Strømforbruget på Supermicro-serveren er væsentligt lavere end strømforbruget på vores ZTE M9000-routere. De kan dog også flytte 200 Gbit/s trafik, så det er svært at sammenligne 1:1.

Som jeg ser det, ligger styrken i en software-router i den fleksibilitet, den kommer med. Vil man teste hastigheden på et specifikt link? Intet problem, man sætter blot en iperf3-instans op i begge ender og kører en test. Har man brug for at kigge på trafikken på et specifikt VLAN? Intet problem, vi starter blot en tcpdump. Crasher softwaren? Vi starter FRRouting med valgrind, finder fejlen og retter den. Mangler der en feature som fx pseudo-wires og VPLS? Well, hvis man virkelig vil, kan man kode den manglende feature selv.

Svagheden ved software-routere har historisk set været performance i form af pakker pr. sekund. Testen fra Jester Brouer m.f. viser i min optik, at det efterhånden er ved at være et løst problem.

Hvad er årsagen til at I har valgt Ubuntu som basissystem? Mange hælder mere til Red Hat's Enterprise Linux og lign. i henhold til stabilitet og support.

En kombination af vane og manglende tid til at sætte sig ind i nye platforme. Jeg har ikke arbejdet med Red Hat siden jeg i 2004 opdagede Debian og glæden ved apt-get pakkesystemet, men Red Hat burde umiddelbart være et mindst lige så godt valg til en software-router.

Michael Hansen

Jeg er lidt splittet omkring ændringerne i Ubuntu

Det er altid spændende indlæg du kommer med :)

Kan godt lide Ubuntu tør og prøve nogle nye ting af, nogle ting fejler (f.ex unity), andre er gode, men kan godt lide hvad de prøver på med netplan, men synes valget af yaml er lidt so-so til konfig filer der typisk er rettet med vi/nano, hvor syntax features er minimalt tilstede, har ikke hænder og føder nok til at tælle hvor mange gange jeg har misset at bruge det rigtig antal spaces til indentation der. Er nok på 60/40% at det er bedre end den gamle /etc/network/interfaces conf

Men kan godt lide de konsekvent bruger iproute2 utils, istedet for diverse wrappers som net-tools (ifconfig/route/arp cmds), der alligevel (hvis jeg forstår det korrekt) alligevel bare er wrappers nu om dage til iproute2.

Redhat har en god cheat sheet til iproute2
https://access.redhat.com/sites/default/files/attachments/rh_ip_command_...

Yoel Caspersen Blogger

men synes valget af yaml er lidt so-so til konfig filer der typisk er rettet med vi/nano, hvor syntax features er minimalt tilstede, har ikke hænder og føder på hvor mange gange jeg har misset at bruge det rigtig antal spaces til indentation der. Er nok på 60/40% at det er bedre end den gamle /etc/network/interfaces conf

Den kostede mig også lidt besvær til at starte med. Hvis man mixer tab og spaces fejler parsingen af filen, selv om den visuelt ser helt rigtig ud.

Det er i øvrigt et klassisk problem med komplekse konfigurationsfiler. Man kunne også have lavet dem i JSON (som fx DHCP-serveren Kea bruger), men det er heller ikke specielt brugervenligt, hvis man skal indtaste konfigurationen manuelt. Og XML er endnu værre...

Jens C. Hansen

og jeg har derfor skrevet mig bag øret, at jeg aldrig må køre netplan apply, mens routeren kører i produktion

alias 'netplan apply' = "echo Nope"

Tak til Kenn Nielsen, ellers havde jeg også foreslået Devuan.

Morten Brørup

Hej Yoel,

Godt at se, at du er kommet videre med dette projekt.

Husk at optimere netkortets parametre, dvs. DMA ring-størrelser (beskrevet her), interrupt coalesce osv., hvilket du kan gøre med ethtool.

Bemærk også, at det anses som god stil at disable GRO i Linux-baserede routere, selvom det koster performance.

PS: Jeg ser spændt frem til at læse mere om dit BNG-projekt, og hvor meget performance du og Jesper Brouer kan presse ud af XDP; for det er jo en glimrende anvendelse for XDP, der går langt udover de trivielle DDOS-anvendelseseksempler.

mvh
Morten Brørup
CTO, SmartShare Systems

Yoel Caspersen Blogger

Hej Morten, tak for de gode tips!

Bemærk også, at det anses som god stil at disable GRO i Linux-baserede routere, selvom det koster performance.

Jeg har faktisk også forsøgt at disable GRO:

ethtool -K ens5f0 gro off

Men dmesg antyder, at det ikke virkede:

i40e 0000:03:00.0: i40e_ptp_init: PTP not supported on ens5f0

Har du et godt bud på, hvad det kan skyldes?

PS: Jeg ser spændt frem til at læse mere om dit BNG-projekt, og hvor meget performance du og Jesper Brouer kan presse ud af XDP; for det er jo en glimrende anvendelse for XDP, der går langt udover de trivielle DDOS-anvendelseseksempler.

Ja, det er også et ret spændende projekt. Vi har fået styr på VLAN-manipulationen, men jeg mangler p.t. at få styr på håndteringen af DHCP-pakker. VLAN tags på pakkerne bruges til at identificere kunden i vores ende, og hvis vi stripper DHCP-pakkerne og sender dem videre i systemet, ved DHCP-serveren ikke hvilken kunde, den enkelte forespørgsel oprindeligt kom fra.

Løsningen bliver muligvis at redirecte DHCP-pakker til en AF_XDP-socket, hvorfra de kan læses i hel tilstand inkl. VLAN tags i user space.

Simon Lodal

Når du kun får 19gbit/s synes jeg det lyder som skæv fordeling af trafikken.

Har du kigget på CPU load, altså per kerne, per sekund (htop)? Kan være en af dine kerner maxer ud? Latens og drops begynder gerne rigtigt over 70%.

De ensartede antal interrupts siger ikke særlig meget om fordeling af trafikken. Du vil få ca samme antal interrupts om en cpu behandler 10kpps eller 100kpps, fordi netkortet batcher flere pakker i samme interrupt.

/proc/net/dev indeholder derimod både pakke- og byte-stats per interface og dermed pr kerne. Jeg bruger et script der parser den hvert sekund og udskriver forskellen. Ellers kan du også tælle pakker per kerne med iptables, men det går jeg ikke ud fra at du bruger.

Christoffer Kelm Kjeldgaard

Svagheden ved software-routere har historisk set været performance i form af pakker pr. sekund. Testen fra Jester Brouer m.f. viser i min optik, at det efterhånden er ved at være et løst problem.

Som gammel Cisco mand synes jeg det er smukt at der er ved at være styr på performance, så de store leverandører kan få noget tiltrængt konkurrence af fri og åben software.

Software routing er bleeding edge-teknologi, så vi er nødt til at have nye Linux-kerner, nye drivers, nye routing daemons etc...

Hvis bleeding edge kernel er kravet kan jeg anbefale Manjaro. Deres værktøj til kernel-management (mhwd-kernel) har jeg ikke set andre steder, der er der virkelig mulighed for at få nyeste kernel hurtigt - og det er meget let og hurtigt at skifte tilbage hvis det skulle vise at den ikke er stable.

Det er rolling release, så jeg ved ikke hvorvidt det egner sig specielt godt til drift af servere - Manjaro bruger også stadig NetworkManager, men det skulle da være muligt at installere og konfigurere Netplan uden større krumspring.

Morten Brørup

Hej Yoel,

Fejlbeskeden i dmsg siger ikke noget om GRO; men PTP (en tidsprotokol), som du nok ikke har brug for. Hvad siger en efterfølgende "ethtool -k"?

Nogle drivere er lidt tricky med den slags. For nogle drivere skal den slags opsætning af porten (ringstørrelser, GRO osv.) foregå inden du giver porten en IP-adresse, og dermed sætter driveren igang med at modtage pakker. Jeg har også set fejl i "ethtool" på dette område. Vi har på disse punkter været nødt til at ty til både kildekodeinspektion og rette lidt i en enkelt driver, der ikke ville makke ret.

Mht. DHCP-pakkerne skal du ganske rigtigt have VLAN tags med til DHCP-serveren. I modsætning til BPF kan man med XDP også skrive i pakken, så du kan evt. lade dit XDP-program tilføje VLAN-informationerne i datadelen af pakken (og opdatere diverse checksummer): Hvis du har god tid til at skrive XDP-programmet, tilføjer du det som DHCP Option 82. Alternativt - hvis du har mulighed for at rette i DHCP-serveren/-relæet på serveren - hægter du bare VLAN tags på til sidst i pakken efter DHCP End Option'en, og lader DHCP-serveren/-relæet læse videre, velvidende, at VLAN tags kommer efter End Option'en.

mvh
Morten Brørup
CTO, SmartShare Systems

Yoel Caspersen Blogger

Når du kun får 19gbit/s synes jeg det lyder som skæv fordeling af trafikken.

Har du kigget på CPU load, altså per kerne, per sekund (htop)? Kan være en af dine kerner maxer ud? Latens og drops begynder gerne rigtigt over 70%.

I min primitive test overfører jeg data gennem 2 iperf3-sessioner i hver sin retning. Det giver i sagens natur en skæv fordeling af trafikken, da al data tilhørende samme flow bruger samme link. Samtidig er det lidt tilfældigt fra test til test, hvordan trafikken fordeles, da hver test bruger et nyt portnummer og dermed ændrer hashingen i LACP-bondet.

En løsning på dette kunne være at bruge iperf3s -P option, som deler trafikken op i flere parallelle streams.

Jeg har dog opdaget, at jeg muligvis har sat netkortet i det forkerte PCI express slot - jeg skal lige have checket, om det påvirker performance.

Yoel Caspersen Blogger

Fejlbeskeden i dmsg siger ikke noget om GRO; men PTP (en tidsprotokol), som du nok ikke har brug for.

Det har du ret i, så vidt jeg kan se, er der muligvis tale om et problem forårsaget af for gammel firmware på kortet:

https://forums.intel.com/s/question/0D50P0000490VWTSA2/x710da2-with-i40e...

Hvad siger en efterfølgende "ethtool -k"?

Den siger blandt andet:

generic-receive-offload: off

Så det ser ud som om, det virker. Kan du huske, hvorfor GRO skal deaktiveres i en router? Intels tuning guide omtaler et "known kernel issue", men hvad går det egentlig ud på?

Yoel Caspersen Blogger

I modsætning til BPF kan man med XDP også skrive i pakken, så du kan evt. lade dit XDP-program tilføje VLAN-informationerne i datadelen af pakken (og opdatere diverse checksummer): Hvis du har god tid til at skrive XDP-programmet, tilføjer du det som DHCP Option 82.

Det var faktisk præcis min plan, men så vidt jeg kan forstå på Jesper Brouer, kan man på nuværende tidspunkt ikke tail-extende en pakke gennem XDP, og dermed er der ikke plads til at tilføje Option 82.

Der er dog flere løsninger, jeg overvejer. Den ene løsning kunne være at redirecte pakken til en AF_XDP-socket, så jeg kan modtage den i et user space-program og tilføje Option 82 her, før jeg sender den videre. Det ville nok være den mest elegante løsning, da den også kan bruges til andre pakketyper på sigt, som det ikke giver mening at behandle i XDP-programmet.

En anden løsning kunne være, at XDP-programmet gemmer DHCP-pakkerne i et map, som et user space-program efterfølgende læser pakkerne fra, tilføjer Option 82 og sender videre.

Baldur Norddahl

Det var faktisk præcis min plan, men så vidt jeg kan forstå på Jesper Brouer, kan man på nuværende tidspunkt ikke tail-extende en pakke gennem XDP, og dermed er der ikke plads til at tilføje Option 82.

Du kan bruge option 52 til at indikere at SNAME og FILE felterne indeholder yderligere options. Klienterne gør normalt aldrig dette, så der er generelt altid plads. Tilsammen er det ekstra 192 bytes som der allerede er allokeret plads til, men som ikke bruges.

Se sektion 4.1 i RFC 2131 og 9.3 i RFC 1533.

Option 52 fylder i sig selv 3 bytes. For at gøre plads til den, så kan du finde option 53 message type og flytte den til SNAME/FILE. Option 53 fylder også 3 bytes og er obligatorisk.

Så helt simpelt:

Parse DHCP pakke og find option 53. Hvis option 53 = value 1 DHCPDISCOVER så erstates option 53 med option 52. Herefter skrives en ny option 53 value 1 samt option 82 i SNAME/FILE.

Kristian Klausen

Jeg skiftede for en del år siden til Ubuntu, da jeg blev træt af at Debian havde gammel (outdated) software i de normale repositories. Er det blevet bedre sidenhen?

Software routing er bleeding edge-teknologi, så vi er nødt til at have nye Linux-kerner, nye drivers, nye routing daemons etc...


Det er sådan Debian sørger for at "tingene" ikke breaker, ved kun at opdatere pakkerne hvis det er yderst nødvendigt:

Basically, a package should only be uploaded to stable if one of the following happens:
* a truly critical functionality problem
* the package becomes uninstallable
* a released architecture lacks the package

De har dog nyere pakker i Backports, f.eks. pt Linux 4.9.12.

Angående netplan, så lyder det smart. Men det lugter godt nok at vendor lock-in, så jeg vil nok overveje bare at bruge systemd-networkd direkte. Men måske er det bare mig..?

Morten Brørup

Kan du huske, hvorfor GRO skal deaktiveres i en router? Intels tuning guide omtaler et "known kernel issue", men hvad går det egentlig ud på?


Jeg kan ikke huske, hvad det går ud på. Når jeg lige søger lidt på nettet, finder jeg noget om at den samlede pakke bliver markeret med at dens checksum ikke længere er gyldig; men at dette kun bliver korrekt håndteret i INPUT, men i FORWARD ender pakken med at blive droppet.

I en virtuel platform, hvor de virtuelle netværk mellem VM'erne typisk kan håndtere jumboframes, observerede vi problemer med at pakkerne blev store undervejs igennem VNF'erne (sandsynligvis på grund af GRO i en firewall-VNF), og at de ikke blev gjort til normalstørrelse inden de skulle ud af systemet igen, og derfor blev droppet på vej ud.

Så det kan også være noget med Path MTU Discovery, der er årsagen til at GRO skal deaktiveres.

mvh
Morten Brørup
CTO, SmartShare Systems

Morten Brørup

Parse DHCP pakke og find option 53. Hvis option 53 = value 1 DHCPDISCOVER så erstates option 53 med option 52. Herefter skrives en ny option 53 value 1 samt option 82 i SNAME/FILE.

Helt overordnet:

Hvis du vil gøre din VLAN-tagger/untagger-komponent transparent, så du kan benytte en almindelig DHCP-server/-relay i routeren, er DHCP Option 82 vejen frem. Og Baldurs forslag er en fremragende workaround på de begrænsede skrivemuligheder i XDP.

Hvis du alligevel skal have din egen software til exceptions kørende på routeren, er en AF_XDP-socket til exception-pakker nok et bedre bud end et map. For du har brug for en kø, og ikke en oplagstabel. Og som du selv skriver, er du dermed også forberedt til at håndtere andre exception-pakker i fremtiden.

mvh
Morten Brørup
CTO, SmartShare Systems

Yoel Caspersen Blogger

Angående netplan, så lyder det smart. Men det lugter godt nok at vendor lock-in, så jeg vil nok overveje bare at bruge systemd-networkd direkte. Men måske er det bare mig..?

Jeg har også overvejet tanken at bruge systemd-networkd direkte, men er indtil videre strandet ved, at der er et begrænset antal timer i døgnet. Dertil kommer et sagte håb om, at Netplan bliver bedre med tiden.

Og hvis nu bare Netplan virkede ordentligt, er det jo faktisk en ret god idé - at man kun behøver lære et enkelt værktøj at kende, uanset om ens distro kører NetworkManager eller systemd-networkd.

Kristian Klausen

Og hvis nu bare Netplan virkede ordentligt, er det jo faktisk en ret god idé - at man kun behøver lære et enkelt værktøj at kende, uanset om ens distro kører NetworkManager eller systemd-networkd.


I princippet ja, men de bruges groft sagt to forskellige steder: NetworkManger(desktop linux), systemd-networkd(servere). Jeg kan ikke se hvorfor man vil bruge Netplan i førstenævnte tilfælde, det virker lettere bare at bruge den grafiske brugergrænseflade.

Yoel Caspersen Blogger

Som gammel Cisco mand synes jeg det er smukt at der er ved at være styr på performance, så de store leverandører kan få noget tiltrængt konkurrence af fri og åben software.

Enig, og hvis på nogen måde skal undgå, at fordækte efterrretningstjenester har direkte adgang til vores netværksudstyr, er det også den eneste vej frem.

Jeg er med på, at server-platformen under software-routeren i sig selv også er sårbar - der er næppe nogen, der kan garantere, at der ikke er sårbarheder eller deciderede bagdøre i CPU, BIOS eller netkortets firmware - men med en hardware-router med proprietær firmware er det nærmeste garanteret, at der som minimum er sårbarheder, og med stor sandsynlighed (jf. Snowdens afsløringer) også bevidst placerede bagdøre.

Yoel Caspersen Blogger

Hvis du alligevel skal have din egen software til exceptions kørende på routeren, er en AF_XDP-socket til exception-pakker nok et bedre bud end et map. For du har brug for en kø, og ikke en oplagstabel. Og som du selv skriver, er du dermed også forberedt til at håndtere andre exception-pakker i fremtiden.

Map-løsningen kan evt. være en nødløsning, hvis man er nødt til at køre med en lidt ældre kerne - AF_XDP er først blevet introduceret for nylig.

Der er i øvrigt et eksempel på, hvordan man kan bruge et map til sende pakker fra kernel space til user space i form af en XDP-baseret tcpdump.

Morten, har du et par gode tips til, hvordan man kan teste performance på en software-router?

Brian Jensen

resultatet her undre mig.

intx-edge1# ping 10.128.3.0
PING 10.128.3.0 (10.128.3.0) 56(84) bytes of data.
64 bytes from 10.128.3.0: icmp_seq=1 ttl=253 time=0.731 ms
64 bytes from 10.128.3.0: icmp_seq=2 ttl=253 time=2.52 ms
64 bytes from 10.128.3.0: icmp_seq=3 ttl=253 time=0.785 ms
64 bytes from 10.128.3.0: icmp_seq=4 ttl=253 time=2.61 ms
^C

Hver andet ping virker meget højt, (1,8 ms er ca den latency jeg har over ipv6 mellem Kolding og Århus på vores netværk), og du har hver andet ping mere end det - jeg ved så ikke om det mønster fortsætter, men med det udstyr du kører ser det underligt ud.

Yoel Caspersen Blogger

Hver andet ping virker meget højt, (1,8 ms er ca den latency jeg har over ipv6 mellem Kolding og Århus på vores netværk), og du har hver andet ping mere end det - jeg ved så ikke om det mønster fortsætter, men med det udstyr du kører ser det underligt ud.

Godt spottet!

Det skyldes, at 10.128.3.0 i mit eksempel er en MPLS-switch fra ZTE. Den nedprioriterer svar på ping-pakker, og det er helt normalt at se ganske store afvigelser - jeg kommer bl.a. ind på dette i et tidligere indlæg om latency.

Der er tale om en sikkerhedsfeature, som skal forhindre at control planet på switchen eller routeren overbelastes ved et DoS-angreb, men det er p****irriterende, når man sidder og debugger på netværket. Her har software-routere en fordel - som regel kan man regne med pingtiden på en software-router.

Morten Brørup

Der er dog et lille aber-dabei: XDP-programmer kan ikke indeholde loops.


Det kan XDP-programmer strengt taget godt; men det skal være endelige loops, og man skal instruere compileren i at unrolle loopet.

Det er beskrevet i Ciliums glimrende BPF and XDP Reference Guide. Søg efter "There are no loops available" på siden.

mvh
Morten Brørup
CTO, SmartShare Systems

Morten Brørup

Map-løsningen kan evt. være en nødløsning, hvis man er nødt til at køre med en lidt ældre kerne - AF_XDP er først blevet introduceret for nylig.

Du er ved at udvikle et helt nyt produkt, og er relativt fri for legacy-bindinger, så du skal have et særdeles godt argument for at fravælge en nyere kerne, der indeholder en feature, som er særdeles brugbar for dit nye produkt nu, og som du kan se yderligere anvendelse for fremover.

mvh
Morten Brørup
CTO, [SmartShare Systems](https://www.smartsharesystems.com/]

Morten Brørup

Morten, har du et par gode tips til, hvordan man kan teste performance på en software-router?

Den helt rigtige løsning er en tester fra danske Xena Networks.

Den billige løsning er at høvle UDP-pakker igennem. Her kan du benytte et lille trick: Du behøver ikke at analysere de pakker, der kommer ud af din router. Du skal blot tælle dem, hvilket du kan gøre ved at koble en managed switch på routerens udgangsport og se på switchportens pakketællere.

De pakker, du smider ind i routeren, skal rende nogenlunde samme vej igennem din softwarerouter, som dine kunders trafik. For fx at teste performance med vores User Load Balancing ved 20.000 brugere, benytter vi trafikmønstre med 20.000 lokale IP-adresser. Og for at simulere 1 mio. samtidige flows, benytter vi 1 mio. 5-tupler.

Som pakkestørrelse kan du benytte IMIX eller de pakkestørrelser, du kender fra dit eget netværk.

Og mens du tester, kan det også være interessant at holde øje med andre parametre, fx CPU-belastningen på din softwarerouter.

Engelske Axtrinet laver også nogle billige, men simple testere. Jeg har ingen erfaringer med deres grej; men jeg har mødt dem på en messe, og folkene bag firmaet virker rimelig kompentente.

Af historiske årsager benytter vi stadig vores eget testsystem, som vi udviklede for mange år siden. Men nu er der jo også kommet projekter som TRex.

mvh
Morten Brørup
CTO, SmartShare Systems

Yoel Caspersen Blogger
Nicklas Seehusen

Spændende at se en software router der kan perform.
Jeg har generelt altid været skeptisk overfor software routere fordi der har været mere fokus på hvor mange gbit de kan flytte ved store pakke størrelser, frem for den performance værdi der faktisk er statisk - pakker per sekund (pps), og den har ikke været høj for software routers sammenlignet med hardware routers.
Man ser software routers i brug flere steder fordi det er nemt og billigt at få noget som i praksis flytter 5gbit ved blandede pakkestørrelser, men bagsiden af medaljen har dog været at der ikke skal meget mere end 300mbit flood af 64 byte pakker til at overbelaste sådan en før den er ude af service, hvilket de fleste danske fiberkunder kan producere fra deres hjemmeadresse. Så efter min mening har de ikke hørt til steder hvor de har en offentlig IP adresse, men det kan være det ændrer sig hvis sådan en XDP-software router kan flytte 1,3mpps per CPU core :)

Jeg synes da det ville være spændende hvis du prøvede at tæske den med små pakkestørrelser, næste gang du performance tester den!

Kommentar til din LACP bond:
Du vil ikke få perfekt load-balancing på din bond med 3 interfaces - det skal gå op i det binære tal system (1, 2, 4, 8) for at det blive ligeligt fordelt. Den xor hashing algoritme der bliver brugt bruger somregel 2 eller 3 bits hvilket giver 4 eller 8 udfald for hashingen. Hver af de udfald er bundet til et interface, så f.eks. hvis den bruger 2 bit har du 4 binære udfald: 00, 01, 10 og 11. De ville blive fordelt sådan her imellem interfacesne:
Interface 1: 00, 11
Interface 2: 01
Interface 3: 10

Så din load-sharing ratio imellem interfaces ville ende med at være 2:1:1 hvilket giver 20gbit til sammen og passer ret godt med de 19gbit du får i din test.
Hvis den bruger 3 bits (8 udfald) ville load-sharing ratio være 3:3:2 - dvs. en del mere ligeligt fordelt, selvom det stadig ikke er perfekt. Det er dog mest for eksemplets skyld da det ikke er en konfigurerbar parameter, men kommer an på implementeringen af LACP.

Jeg ville foreslå at trylle et ekstra 10G interface frem til bond'en, eller droppen bond'en og kigge på noget ECMP istedet.

Hvis du forsat vil køre bond ville jeg ændre min LACP hash-policy fra layer3+4 til layer2+3. Layer3+4 er ikke fuld supporteret af 802.3ad og kan under specifikke omstændigheder splitte flows ud over flere links og give out-of-order flows, hvilket ikke er tilfældet med layer2+3. Der burde være tilskrækkelig fordeling af flows med layer2+3 som hash policy, så ingen grund til at tænke i om de specifikke omstændigheder vil være et problem for dig i praksis.

Yoel Caspersen Blogger

Nicklas, tak for dine guldkorn. Det var kommentarer som din og mange andres her, jeg håbede på at modtage, da jeg skrev indlægget!

Så efter min mening har de ikke hørt til steder hvor de har en offentlig IP adresse, men det kan være det ændrer sig hvis sådan en XDP-software router kan flytte 1,3mpps per CPU core :)

Bemærk at de 1,3 Mpps er uden XDP-acceleration. Med XDP når vi jf. Brouer et al op på noget der ligner 3,4 Mpps hvilket i grove træk svarer til 1,74 Gbit/s pr. core eller ca. 10,5 Gbit/s totalt med 64 bytes pakker.

Derudover kan man bruge XDP til at stoppe eventuelle DoS-angreb - og her taler vi om line rate performance. Det kræver selvfølgelig, at man bruger energien på at bygge et DoS detection tool, fx med inspiration fra Cloudflare, som bruger XDP til præcis dette formål.

Med en hardware-router kan man selvfølgelig blot forwarde DoS-trafikken ind til den uheldige modtager, men der er jo en vis risiko for, at andre dele af nettet bliver ramt i processen ;-)

Jeg ville foreslå at trylle et ekstra 10G interface frem til bond'en, eller droppen bond'en og kigge på noget ECMP istedet.

Den detalje var jeg ikke opmærksom på - men af andre årsager har jeg allerede tilføjet den 4. port, således at hele netkortet nu indgår i bondet.

Netkortet er nu også flyttet til det korrekte PCI slot, så performance ikke begrænses her.

Hvis du forsat vil køre bond ville jeg ændre min LACP hash-policy fra layer3+4 til layer2+3. Layer3+4 er ikke fuld supporteret af 802.3ad og kan under specifikke omstændigheder splitte flows ud over flere links og give out-of-order flows, hvilket ikke er tilfældet med layer2+3.

Tak for tippet, det er hermed ændret. Årsagen til mit valg af layer3+4 er, at vi kører CGN-routere i vores net. Der vil således være tale om relativt store trafikmængder mellem relativt få IP-adresser - fx fra vores Netflix-cache til ydersiden af en CGN-router. Men vi må se, om det bliver et problem i praksis med layer2+3.

Baldur Norddahl

Den xor hashing algoritme der bliver brugt bruger somregel 2 eller 3 bits hvilket giver 4 eller 8 udfald for hashingen.

Mig bekendt er det fuldstændig implementationsspecifikt og er ikke defineret i nogen standard. For en software router giver det kun mening at hashe de valgte felter ind i en 32 eller 64 bit værdi og herefter tage modulus antal interfaces. Givet et stort nok antal flows, så vil det give en næsten perfekt fordeling af load.

For Linux kan vi bare finde kildekoden og det er præcis hvad de gør:

slave = slaves->arr[bond_xmit_hash(bond, skb) % count];

Hvor bond_xmit_hash beregner en 32 bit hash med xor og shift fra de valgte felter og count er antallet af aktive interfaces.

Claus Vaaning

Jeg startede med at rode med Linux på OpenSuSE, som jeg den dag i dag godt kan savne, men den linux havde store problemer med at køre et ISPConfig panel, og efter at jeg så prøvede Debian har jeg ikke brugt andet.

Det er rigtig nok at mange af deres pakker er gamle, f.x. kører den seneste udgave af Debian stadig PHP 7.0, som er obsolete. Til gengæld er det jo nemt at hente og kompilere de versioner man gerne vil have.

Og APT / APT-GET er genialt.

Log ind eller Opret konto for at kommentere
Brugerundersøgelse Version2
maximize minimize