ltcp/bericht/nftables/nftables-perf.tex

238 lines
10 KiB
TeX

\subsubsection{Performance-Vergleich}
\paragraph{Testaufbau}
Um die Performance der beiden Firewall-Lösungen vergleichen zu könne, habe ich jeweils zwei unserer Zotac-Boards mit der Onboard-Netzwerkkarte an einen zusätzlichen Firewall-Rechner, der mir bereitgestellt wurde, verbunden. Die Spezifikationen der Zotac-Boards sind dem Abschnitt »Hardware« zu entnehmen. \\
Der zusätzliche Rechner war mit einem Intel Core 2 Duo E6750 mit 2,66 GHz, 2 GiB RAM ausgestattet und zwei Intel Gigabit-Netzwerkkarten ausgestattet (Intel 82566DM-2 und 82572EI). Die beiden Intel-Netzwerkkarten wurden direkt mit den beiden Zotac-Boards verbunden.
Der Firewall-Rechner wurde über die Onboard-Netzwerkkarte und die beiden Zotac-Boards über USB-Netzwerkkarten mit einem Switch und darüber mit der Headnode verbunden um einen Zugriff von außen bereitzustellen. \\
Der Firewall-Rechner soll nun über \texttt{iptables} und \texttt{nftables} den Datenverkehr zwischen den beiden Nodes kontrollieren. Die beiden Netzwerk-Interfaces der Firewall waren im Bridge-Modus verbunden. \\
\includegraphics{bilder/nft-layout.pdf}
\paragraph{Verwendete Software} Um schnell genug eine große Anzahl an Paketen pro Sekunde (PPS) erzeugen zu können um die Firewall-Lösungen zu benchmarken, habe ich \texttt{pktgen} verwendet. Hierbei handelt es sich um einen Paketgenerator, der als Kernel-Modul geladen wird und dadurch direkt im Kernel (ohne teure Kontext-Switches ins Userland) ausgeführt wird.
Zur Überwachung der Messdaten (Datenrate und PPS) habe ich auf allen vier Netzwerkschnittstellen das Tool \texttt{ifpps} aus dem \texttt{netsniff-ng}-Bundle laufen lassen.
\pagebreak
\paragraph{Testeinstellung} Zunächst habe ich die Datenrate und die PPS in Abhängigkeit der Ethernet Frame-Größe gemessen um festzustellen, mit welcher Paketgröße die Messungen am besten durchzuführen sind. \\ \\
\pgfplotstableread{
size rate pps
1500 986.004 82167
1450 985.7216 84976
1400 984.7376 87923
1350 984.2904 91138
1300 983.4968 94567
1250 982.78 98278
1200 982.08 102300
1150 981.18 106650
1100 980.2496 111392
1050 979.2384 116576
1000 978.304 122288
950 977.36 128600
900 975.0024 135417
850 974.27 143275
800 972.5888 151967
750 970.572 161762
700 968.3856 172926
650 966.2328 185814
600 963.1056 200647
550 959.7588 218127
500 955.604 238901
450 951.588 264330
400 945.3248 295414
350 937.3336 334762
300 923.2584 384691
250 855.588 427794
200 662.5952 433335
150 527.3604 439467
100 354.96 443700
50 207.176 446500
}\sizeratepps
\begin{tikzpicture}
\pgfplotsset{
y axis style/.style={
yticklabel style=#1,
y axis line style=#1,
ylabel style=#1,
ytick style=#1
}
}
\begin{axis}[
width=15cm, height=10cm,
title=Sender,
xmin=1,
xmax=1500,
xlabel={Ethernet Frame-Größe},
xtick={100,300,500,700,900,1100,1300,1500},
ymin=0,
axis y line*=left,
ylabel={Datenrate [MBit/s]},
y axis style=blue!75!black,
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
scaled ticks=false
]
\addplot[smooth,blue] table[x={size}, y={rate}] {\sizeratepps};
\end{axis}
\begin{axis}[
width=15cm, height=10cm,
xmin=1,
xmax=1500,
axis x line=none,
ymin=0,ymax=500000,
ytick pos=right,
axis y line* = right,
ylabel={PPS},
ylabel near ticks,
ytick={100000,200000,300000,400000},
y axis style=red!75!black,
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
scaled ticks=false
]
\addplot[smooth,red] table[x={size}, y={pps}] {\sizeratepps};
\end{axis}
\end{tikzpicture}
\vspace{1cm}
\pgfplotstableread{
size rate pps
1500 982.38 81865
1450 981.1512 84582
1400 983.4272 87806
1350 981.936 90920
1300 979.9816 94229
1250 977.44 97744
1200 980.7936 102166
1150 978.5396 106363
1100 975.6472 110869
1050 972.3588 115757
1000 977.192 122149
950 974.0312 128162
900 970.6896 134818
850 965.4368 141976
800 970.8992 151703
750 966.756 161126
700 960.9544 171599
650 956.2592 183896
600 961.4736 200307
550 954.8088 217002
500 946.992 236748
450 928.7784 257994
400 823.2672 257271
350 722.5316 258047
300 615.1632 256318
250 492.206 246103
200 406.3824 253989
150 299.2116 249343
100 205.8888 257361
50 123.79728 257911
}\sizerateppsrecv
\begin{tikzpicture}
\pgfplotsset{
y axis style/.style={
yticklabel style=#1,
y axis line style=#1,
ylabel style=#1,
ytick style=#1
}
}
\begin{axis}[
width=15cm, height=10cm,
title=Empfänger,
xmin=1,
xmax=1500,
xlabel={Ethernet Frame-Größe},
xtick={100,300,500,700,900,1100,1300,1500},
ymin=0,
axis y line*=left,
ylabel={Datenrate [MBit/s]},
y axis style=blue!75!black,
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
scaled ticks=false
]
\addplot[smooth,blue] table[x={size}, y={rate}] {\sizerateppsrecv};
\end{axis}
\begin{axis}[
width=15cm, height=10cm,
xmin=1,
xmax=1500,
axis x line=none,
ymin=0,ymax=500000,
ytick pos=right,
axis y line* = right,
ylabel={PPS},
ylabel near ticks,
ytick={100000,200000,300000,400000},
y axis style=red!75!black,
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
scaled ticks=false
]
\addplot[smooth,red] table[x={size}, y={pps}] {\sizerateppsrecv};
\end{axis}
\end{tikzpicture}
\pagebreak
Wie aus den Diagrammen ersichtlich wird, wird bei Frame-Größen, die an die MTU des Ethernets (1500 Bytes) heranreichen, das Gigabit-Netzwerk mit ca. 980 MBit/s und ca. 82000 PPS fast komplett ausgereizt. Je kleiner die Frame-Größe wird, desto größer wird zunächst die Anzahl der PPS, da das Netzwerk immer noch gut ausgelastet wird; die Datenrate sinkt zunächst zur langsam. \\
Beim Sender beginnt jedoch bei Frame-Größe kleiner 300 Byte die Datenrate linear zu sinken. Die PPS stagnieren dann bei ca. 450000 Paketen. Dies ist mit der Leistungsfähigkeit der Atom-Prozessoren zu erklären, da diese ab dieser Grenze komplett ausgelastet sind und die Pakete nicht schneller erzeugen können. \\
Beim Empfänger geschieht dieser Einbrauch schon bei ca. 450 Byte Frame-Größe. Hier stagniert die PPS bei ca. 250000. Auch dies lässt sich mit der Auslastung des Prozessors erklären. Der Unterschied zum Sender besteht darin, dass bei diesem die Pakete lediglich statisch zusammengesetzt und losgeschickt werden müssen. Beim Empfänger hingegen muss das Betriebssystem die Pakete zunächst auswerten, was den Bearbeitungszeit verlängert. Dadurch kommen beim Empfänger wesentlich weniger Pakete an, als der Sender losschickt. (Die übrigen Pakete werden gedroppt.) \\
Um eine größtmögliche Auslastung des Gigabit-Netzwerkes zu ermöglichen und gleichzeitig die maximale Anzahl an PPS zu erhalten, habe ich also für die folgenden Benchmarks die Ethernet Frame-Größe auf 450 festgesetzt.
\paragraph{Anfängliche Probleme} Anfangs habe ich auf dem Empfänger keine »Anwendung« laufen lassen, die die Pakete des Senders entgegennimmt. Deshalb musste der Kernel zusätzliche ein ICMP-Paket mit »Connection Refused«-Flag an den Sender zurückschicken und daraufhin weitere Fehlerbehandlungen durchführen. Auf diese Weise habe ich am Empfänger zunächst nur ca. 110000 PPS empfangen können. Als Lösungsansatz habe ich dann \texttt{netcat} auf dem Port am Empfänger laufen lassen und die Daten nach \texttt{/dev/null} umgeleitet. Damit kamen keine Fehler mehr zustande und es konnten ca. 150000 PPS empfangen werden. Dies liegt jedoch immer noch weit unter den am Sender losgeschickten 450000 PPS und ist damit zu erklären, dass es für jedes Paket zu einem Kontex-Switch vom Kernel zu \texttt{netcat} kam und deshalb wieder die Bearbeitungszeit pro Paket stieg. \\
Letztendlich habe ich dazu entschieden, auf der Empfängerseite mit \texttt{iptables} die Pakete, die auf dem entsprechenden Port angekommen, direkt zu droppen. Damit konnten nun die zuvor erwähnten ca. 250000 PPS empfangen werden.
\pagebreak
\paragraph{Einfache Drop-Regeln} Für den nachfolgenden Benchmark habe ich entsprechend viele Regeln generieren lassen, die besagen, dass von (zufällig gewählten) IP-Adressen alle Pakete gedropt werden sollen. \\
\pgfplotstableread{benchmarks/nft/ipt-nft-simple-drop.txt}{\nftsimpledrop}
\begin{minipage}{\textwidth}
\flushright
\begin{tikzpicture}
\begin{axis}[
name=plot1,
xtick={5000,10000,15000,20000,25000,30000},
xmin=200, xmax=30000,
ymin=0,
xlabel={Anzahl der Firewall-Regeln}, ylabel={Datenrate [MBit/s]},
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
width=15cm, height=10cm,
legend entries={iptables,nftables},
scaled ticks=false
]
\addplot[smooth,blue] table [x={rules}, y={iptrate}] {\nftsimpledrop};
\addplot[smooth,red] table [x={rules}, y={nftrate}] {\nftsimpledrop};
\end{axis}
\begin{axis}[
name=plot2,
at=(plot1.below south), anchor=above north,
yshift=-0.5cm,
xtick={5000,10000,15000,20000,25000,30000},
xmin=200, xmax=30000,
ymin=0,
xlabel={Anzahl der Firewall-Regeln}, ylabel={PPS},
tick label style={/pgf/number format/fixed,/pgf/number format/1000 sep = \thinspace},
width=15cm, height=10cm,
legend entries={iptables,nftables},
scaled ticks=false
]
\addplot[smooth,blue] table [x={rules}, y={iptpps}] {\nftsimpledrop};
\addplot[smooth,red] table [x={rules}, y={nftpps}] {\nftsimpledrop};
\end{axis}
\end{tikzpicture}
\end{minipage} \\
Die Datenrate und die Anzahl an PPS liegen initial bei den bereits zuvor gemessenen ca. 980 MBit/s und 250000 Paketen pro Sekunde. Jedoch bricht die Leistungsfähigkeit bei beiden Firewall-Lösungen schnell erheblich ein. So kann \texttt{iptables} bei 5000 Regeln nur noch ca. 100 MBit/s bei 28000 Paketen verarbeiten, \texttt{nftables} schafft hier nur ca. 50 MBit/s bei 14000 Paketen.