doc
Some checks failed
Build and Deploy MITM Webserver / build (push) Has been cancelled
Build and Deploy MITM Webserver / traffic_target (push) Has been cancelled

This commit is contained in:
2026-05-23 12:19:22 +02:00
parent 6e7a1ccb1b
commit a4b19f8c3e
17 changed files with 7039 additions and 18 deletions

View File

@@ -1,20 +1,48 @@
\chapter*{List of Acronyms}
\addcontentsline{toc}{chapter}{List of Acronyms}
\begin{acronym}[HTTPS] % Give the longest label here so that the list is nicely aligned
\begin{acronym}[NFQUEUE] % Give the longest label here so that the list is nicely aligned
\acro{API}{Application Programming Interface}
\acro{ARP}{Address Resolution Protocol}
\acro{BPF}{Berkeley Packet Filter}
\acro{BPDU}{Bridge Protocol Data Unit}
\acro{CA}{Certificate Authority}
\acro{CPU}{Central Processing Unit}
\acro{DMA}{Direct Memory Access}
\acro{eBPF}{extended Berkeley Packet Filter}
\acro{FDB}{Forwarding Database}
\acro{FIB}{Forwarding Information Base}
\acro{HTML}{HyperText Markup Language}
\acro{HTTPS}{Hypertext Transfer Protocol Secure}
\acro{HTTP}{Hypertext Transfer Protocol}
\acro{IEEE}{Institute of Electrical and Electronics Engineers}
\acro{IP}{Internet Protocol}
\acro{IPv4}{Internet Protocol version 4}
\acro{IPv6}{Internet Protocol version 6}
\acro{LAN}{Local Area Network}
\acro{LSM}{Linux Security Module}
\acro{MAC}{Media Access Control}
\acro{MITM}{Man-in-the-Middle}
\acro{MTU}{Maximum Transmission Unit}
\acro{NAPI}{New API}
\acro{NAT}{Network Address Translation}
\acro{NFQUEUE}{Netfilter Queue}
\acro{NIC}{Network Interface Card}
\acro{OSI}{Open Systems Interconnection}
\acro{PVID}{Port VLAN Identifier}
\acro{RSTP}{Rapid Spanning Tree Protocol}
\acro{RSS}{Receive Side Scaling}
\acro{SPAN}{Switched Port Analyzer}
\acro{SSID}{Service Set Identifier}
\acro{SSL}{Secure Sockets Layer}
\acro{STP}{Spanning Tree Protocol}
\acro{TAP}{Test Access Point}
\acro{TCP}{Transmission Control Protocol}
\acro{TLS}{Transport Layer Security}
\acro{TTL}{Time To Live}
\acro{UDP}{User Datagram Protocol}
\acro{URI}{Uniform Resource Identifier}
\acro{URL}{Uniform Resource Locator}
\acro{VLAN}{Virtual Local Area Network}
\acro{XDP}{eXpress Data Path}
\end{acronym}

View File

@@ -3,7 +3,7 @@
In this chapter, the necessary background and foundational concepts underlying the research presented in this thesis are introduced. First, the theoretical frameworks and methodologies guiding the approach are discussed, followed by an overview of the key technologies and tools used in this work. The chapter is intended to establish a common understanding and provide context for the subsequent chapters, in which the specific contributions and findings of the research are presented.
\section{\ac{OSI} Model}
\section[OSI Model]{\ac{OSI} Model}
\label{sec:osi}
The \ac{OSI} Basic Reference Model provides a conceptual framework for describing communication between open systems in a structured and interoperable way. Instead of treating network communication as a single process, it divides it into seven layers with clearly separated responsibilities. This layered view simplifies the analysis of communication systems and provides a common terminology for discussing protocols and interfaces.
@@ -44,35 +44,122 @@ A key principle of the \ac{OSI} model is that each layer has a defined scope of
For the present thesis, the \ac{OSI} model is mainly used as a conceptual orientation for the discussion of communication layers and network functions. Even though the implemented system is better described using the practical \ac{TCP}/\ac{IP} stack, the \ac{OSI} structure remains useful for introducing the general principles of layered communication.
\section{Linux Kernel Networking}
\label{sec:linux-kernel-networking}
\section{Transparent Network Interception Models}
\label{sec:transparent-network-interception-models}
In Linux, networking is handled by a subsystem that spans user space sockets, protocol implementations, filtering and routing logic, network devices, device drivers, and the network interface card. A packet therefore does not move directly from an application to the transport medium or the other way around. Instead, it passes through a sequence of kernel-controlled processing stages on the egress and ingress paths \cite{stephan2024packetpath,linuxkernelnetworkingdocs}.
\subsection{Man-in-the-Middle Terminology}
A central data structure of this subsystem is \texttt{sk\_buff}. In Linux, \texttt{sk\_buff} is the main networking structure representing a packet, but it does not itself contain the packet bytes. Instead, it stores metadata and pointers to associated buffers that hold headers and payload. This design allows Linux to add, inspect, and remove headers efficiently by moving pointers rather than copying the entire packet, and it also enables efficient cloning when multiple processing stages need access to the same packet data \cite{linuxkernelskbuffdocs,stephan2024packetpath}.
The term \ac{MITM} describes a communication setting in which an intermediate system is positioned between two endpoints and can observe, relay, insert, or modify messages exchanged between them \cite{conti2016mitmsurvey}. In security literature, this position is often discussed as an adversarial capability \cite{conti2016mitmsurvey}. In the present thesis, the term is used in a controlled experimental sense: the system is intentionally placed in the communication path in order to observe, correlate, and selectively manipulate traffic. The relevant distinction is therefore not only whether traffic can be observed, but also at which layer the intermediate system is inserted and whether it becomes visible to the endpoints.
\subsection{Layers of a Packet}
\subsection[Passive Capture with TAP and SPAN]{Passive Capture with \ac{TAP} and \ac{SPAN}}
On an Ethernet-based system, a packet on the wire is processed as a stack of protocol layers. At the data link layer, the frame contains the Ethernet header with source and destination \ac{MAC} addresses and an EtherType field. Above this follows the network-layer header, for example an IPv4 header. On top of that is the transport-layer header, such as \ac{TCP} or \ac{UDP}. The remaining bytes form the payload delivered to the application. In Linux, lower-layer headers are added on the egress path when the packet moves toward the wire, whereas they are validated and stripped on the ingress path when the packet moves toward the socket \cite{stephan2024packetpath}. When a Linux system operates as a bridge, forwarding decisions are made at Layer 2 on the basis of the destination \ac{MAC} address, that is, before local delivery to higher layers becomes necessary \cite{linuxkernelbridgedocs}.
Passive monitoring systems obtain a copy of network traffic without becoming the forwarding element. A \ac{TAP} is a dedicated device inserted directly into the monitored physical link, for example between a host and a switch or between two switches. It copies the traffic that crosses this link to one or more monitoring interfaces while the original traffic continues between the connected endpoints. In contrast, \ac{SPAN}, also known as port mirroring, is configured on a switch. The monitored devices remain connected to their normal switch ports, and the switch duplicates selected ingress, egress, or bidirectional traffic from these ports to a separate monitoring port. The main difference is therefore where the traffic copy is produced. A \ac{TAP} observes the link directly at its physical position in the path, whereas \ac{SPAN} observes traffic indirectly from inside the switch forwarding and mirroring implementation. Neither mechanism gives the monitoring device direct control over the original forwarding decision, so passive capture cannot directly block or modify packets in the original stream. Zhang and Moore show that \ac{SPAN}-based monitoring can also introduce measurement artifacts, including inter-packet timings, packet reordering, and packet loss \cite{zhang2007portmirroring}.
\subsection{Egress Path}
\subsection{Layer-3 Routed Interception}
The egress path begins in user space when an application writes data to a socket, for example by using \texttt{write()}, \texttt{send()}, or \texttt{sendto()}. For IPv4 communication, such a socket is typically an \texttt{AF\_INET} socket. The system call enters the kernel and reaches the socket layer, where \texttt{sock\_sendmsg()} retrieves the socket context and forwards the packet to the transport-layer handler. At this point, Linux may already apply security-related checks through Linux Security Modules \cite{stephan2024packetpath}.
In a routed interception model, the intermediate system is part of the \ac{IP} forwarding path. An \ac{IP} router receives a packet, determines the next hop based on the destination \ac{IP} address and routing information, and transmits the packet through the selected outgoing interface \cite{rfc1812}. From the perspective of the endpoints, a routed intermediary therefore behaves as a router or gateway rather than as an Ethernet switch. Traffic must either be configured to use this system as its next hop, for example through a default gateway setting, or the surrounding network must otherwise be changed so that packets are routed through it.
At the transport layer, Linux constructs the transport header and prepares the packet for transmission. For \ac{TCP}, the kernel segments data if necessary, writes it into \texttt{sk\_buff} structures, enqueues it in the socket write queue, builds the \ac{TCP} header, and enforces protocol mechanisms such as maximum segment size, congestion control, and retransmission timers. For \ac{UDP}, the processing path is simpler: the kernel builds the datagram and corresponding transport header with less state and less locking overhead \cite{stephan2024packetpath}.
This placement has visible protocol effects. In \ac{IPv4}, every router that forwards a packet decrements the \ac{TTL} field \cite{rfc1812}. Therefore, a routed intermediary can appear as an additional \ac{IP} hop to tools and diagnostics that inspect hop-count behavior.
After transport-layer preparation, the packet enters the IP layer. Here Linux determines the route, typically by consulting the Forwarding Information Base if no suitable destination information is already cached in the packet context. Once a route is available, the kernel builds the IP header and passes the packet through netfilter hook stages such as \texttt{LOCAL\_OUT} and \texttt{POST\_ROUTING}. If necessary, Linux also resolves the next-hop destination at Layer 2, for example by using the neighbor subsystem and the \ac{ARP} to obtain the destination \ac{MAC} address. After that, the Ethernet header is added to the packet \cite{stephan2024packetpath}.
A routed intermediary may also modify packet headers. If \ac{NAT} is used, address information is rewritten as packets traverse the translator \cite{rfc3022}. Depending on the configuration, this can affect source or destination \ac{IP} addresses, transport-layer ports, and the reverse mapping needed for return traffic \cite{rfc3022}. Even without \ac{NAT}, routed forwarding changes the Layer-2 next hop because the packet is emitted through the outgoing link selected by the routing decision \cite{rfc1812}. Consequently, the intermediary is not merely observing an existing Ethernet segment; it actively participates in \ac{IP} forwarding. This makes routed interception useful when the intermediate system is intended to enforce Layer-3 policy, apply firewalling, perform \ac{NAT}, or deliberately act as a gateway.
The fully constructed frame then enters the network device transmission path. Linux passes it to \texttt{dev\_queue\_xmit()}, where traffic control and queueing disciplines can process it on egress. After queueing and possible post-processing such as checksum handling or VLAN tagging, the kernel calls the driver transmission function \texttt{ndo\_start\_xmit}. The driver places the packet into the transmit ring of the network interface card, maps the packet buffer for Direct Memory Access, and the hardware finally transmits the frame onto the physical medium \cite{stephan2024packetpath}.
\subsection{Proxy-Based Interception}
Proxy-based interception moves the intermediary even higher in the stack. An \ac{HTTP} proxy terminates or relays application-layer requests rather than merely forwarding Ethernet frames. For \ac{HTTPS}, interception typically requires a \ac{TLS} proxy that presents itself as the server to the client and as the client to the external server, thereby creating two separate \ac{TLS} connections \cite{waked2018tlsinterception}. This model can expose plaintext to the proxy when the client trusts a signing \ac{CA} controlled by the proxy \cite{waked2018tlsinterception}. At the same time, it changes the end-to-end security model of \ac{TLS} \cite{decarnedecarnavalet2023tlsinterception}. Empirical studies show that \ac{HTTPS} interception can be detected through inconsistencies between \ac{HTTP} \texttt{User-Agent} information and \ac{TLS} client behavior \cite{durumeric2017httpsinterception}, and that interception appliances may introduce certificate-validation and parameter-mapping weaknesses \cite{waked2018tlsinterception}. Proxy-based interception is therefore powerful for application-layer inspection, but it is not transparent in the same sense as Layer-2 forwarding.
\subsection{Transparent Layer-2 Inline Bridges}
A transparent inline bridge occupies the forwarding path without acting as an \ac{IP} router or application proxy. Such a bridge connects network segments at the data link layer and forwards frames based on bridge state and destination \ac{MAC} addresses \cite{ieee8021q2022}. The Linux bridge implements this behavior by learning source \ac{MAC} addresses, maintaining an \ac{FDB}, and forwarding, filtering, flooding, or locally delivering frames according to the bridge configuration \cite{linuxkernelbridgedocs}. In this model, the bridge does not have to be configured as the endpoints' \ac{IP} gateway or as an application proxy, because forwarding is performed below the \ac{IP} layer.
\subsection{Transparency and Detectability}
Transparency should not be understood as complete undetectability. An inline bridge can affect latency, packet ordering, loss behavior, link-state propagation, and bridge-control behavior. If \ac{STP} is enabled, \acp{BPDU} and forwarding-delay behavior may become externally visible \cite{linuxkernelbridgedocs}. If \ac{TLS} proxying is added on top of forwarding, certificate and handshake artifacts can reveal the interception point \cite{durumeric2017httpsinterception}. The transparency goal in this thesis is therefore narrower and technical: the system should forward traffic as a Layer-2 inline bridge without introducing an additional \ac{IP} hop, without requiring endpoint proxy configuration, and without terminating application-layer sessions unless a later manipulation component explicitly does so.
\section{Linux Packet Processing Path}
\label{sec:linux-packet-processing-path}
The following section explains how network packets are processed by the Linux kernel. First, the internal packet representation is described. Next, the receive path from the \ac{NIC} into the kernel is outlined. Then, the local delivery, forwarding, and bridge paths are distinguished. Lastly, the relevant programmable hook points are explained because they define where a transparent traffic capture and manipulation platform can observe, mark, forward, or drop packets.
Linux networking is not a single processing step. Instead, packets move through device drivers, protocol implementations, routing or bridge logic, filtering hooks, queueing disciplines, and user space socket interfaces \cite{linuxkernelnetworkingdocs}. The exact path depends on whether a packet is locally generated, locally delivered, routed, or bridged \cite{stephan2024packetpath}. This distinction is important for the present thesis because a transparent \ac{MITM} system should normally forward frames at Layer 2, while still observing and manipulating packets at selected kernel hook points.
\subsection{Packet Representation}
On an Ethernet-based system, the bytes on the wire are structured as a frame. The Ethernet header contains source and destination \ac{MAC} addresses and an \texttt{EtherType} field. Depending on the \texttt{EtherType}, the frame may contain an \ac{ARP} message, an \ac{IPv4} packet, an \ac{IPv6} packet, or another payload. For \ac{IP} traffic, the network-layer header is followed by a transport-layer header such as \ac{TCP} or \ac{UDP}. The remaining bytes form the payload delivered to the application or forwarded to another interface.
Inside the Linux kernel, packets are mainly represented by \texttt{struct sk\_buff} \cite{linuxkernelskbuffdocs}. This structure does not contain the packet bytes directly. Instead, it stores metadata and pointers to one or more buffers that contain the actual headers and payload \cite{linuxkernelskbuffdocs}. The \texttt{head}, \texttt{data}, \texttt{tail}, and \texttt{end} pointers describe the usable packet buffer, while header offsets such as \texttt{mac\_header}, \texttt{network\_header}, and \texttt{transport\_header} indicate where individual protocol headers begin \cite{linuxkernelskbuffdocs}. As a result, protocol layers can prepend or remove headers by adjusting pointers instead of copying the complete packet \cite{stephan2024packetpath}.
The \texttt{sk\_buff} also carries processing metadata such as the receiving or transmitting network device, the packet length, protocol information, checksum state, priority values, and marks \cite{linuxkernelskbuffdocs}. Such metadata is not visible on the wire, but it can influence routing, filtering, queueing, and later processing stages. This property is useful for packet correlation because a mark stored in \texttt{skb->mark} can follow a packet through multiple kernel stages without changing the actual Ethernet frame.
Furthermore, Linux can clone an \texttt{sk\_buff} efficiently. A clone gets its own metadata structure while sharing the packet data buffer until modification becomes necessary. This is relevant for packet capture. Passive observers such as raw packet sockets can receive a clone of the packet while the original packet continues through the normal kernel path. Hence, capturing a packet does not necessarily mean that the packet was consumed by the capture process \cite{linuxkernelskbuffdocs}.
\subsection{Ingress Path}
The ingress path begins when the network interface card receives an Ethernet frame from the physical medium. The hardware checks link-layer conditions such as the \ac{MAC} filter and moves the received bytes into system memory by Direct Memory Access. It then notifies the operating system, which allocates an \texttt{sk\_buff} and stores metadata such as the receiving interface, protocol information, and packet type. At this stage, Linux knows the position of the Ethernet header and can record it as the \texttt{mac\_header} of the packet \cite{stephan2024packetpath,linuxkernelskbuffdocs}.
The ingress path begins when the \ac{NIC} receives a frame from the physical medium. Modern \acp{NIC} often use multiple receive queues. With \ac{RSS}, the device can assign packets to queues based on a hash over packet header fields, allowing receive processing to be distributed over multiple \acp{CPU} \cite{linuxkernelscalingdocs}. The received bytes are transferred into main memory using \ac{DMA}, and the driver notifies the kernel that new receive work is available. Drivers commonly process this work through \ac{NAPI}, which combines interrupt notification with polling under load.
The packet is then passed into the receive path through functions such as \texttt{netif\_receive\_skb()}. During this stage, Linux can hand the packet to virtual interfaces, VLAN handling, or a receive handler associated with a master device. This is particularly relevant for bridge configurations, because an interface that is part of a Linux bridge can have its received frame intercepted for Layer-2 forwarding logic instead of immediate local delivery \cite{stephan2024packetpath,linuxkernelbridgedocs}.
Before the regular networking stack processes the packet, \ac{XDP} may run in supported drivers \cite{hoilandjorgensen2018xdp}. Native \ac{XDP} executes an \ac{eBPF} program very early in the receive path, before the kernel allocates the normal \texttt{sk\_buff} structure \cite{hoilandjorgensen2018xdp}. The program can return a verdict to pass the packet to the kernel stack, drop it, transmit it back out, or redirect it to another target \cite{hoilandjorgensen2018xdp}. This makes \ac{XDP} useful for high-performance packet processing \cite{scholz2018ebpfpacketfiltering}. However, the early position also means that normal \texttt{sk\_buff} metadata is not yet available in native mode.
If the packet is processed as an IP packet, Linux continues with \texttt{ip\_rcv()}. There, the kernel validates essential IP header fields such as version, length, and checksum, sets the pointer to the transport header, and applies the netfilter \texttt{PRE\_ROUTING} hook. The routing logic then decides whether the packet should be forwarded, locally delivered, or treated as multicast traffic. For local delivery, Linux may first reassemble fragmented packets and then applies the \texttt{LOCAL\_IN} hook before stripping the IP header and handing the packet to the appropriate transport-layer protocol handler \cite{stephan2024packetpath}.
If the packet continues into the regular networking stack, the driver creates or completes an \texttt{sk\_buff} and passes it into the generic receive path, commonly through functions such as \texttt{netif\_receive\_skb()} \cite{stephan2024packetpath}. At this stage, Linux has metadata about the receiving interface and can expose the packet to early ingress processing. This includes \texttt{tc} ingress programs and the \texttt{nftables} \texttt{netdev} \texttt{ingress} hook \cite{nftableshooks}. In contrast to native \ac{XDP}, these hooks operate after the \texttt{sk\_buff} exists and can therefore read or write metadata such as \texttt{skb->mark}.
At the transport layer, Linux validates the \ac{TCP} or \ac{UDP} header and associates the segment or datagram with the correct socket. For \ac{TCP}, this includes checksum validation, socket lookup, state-machine handling, and enqueuing the packet in the socket receive queue. For \ac{UDP}, the processing path is simpler, but it also includes checksum validation, socket lookup, and datagram consumption. Finally, when the user-space process executes a receiving system call such as \texttt{read()} or \texttt{recv()}, the kernel dequeues the data from the socket receive queue and copies it to user space \cite{stephan2024packetpath}.
After early ingress processing, the packet may be cloned for packet sockets, handled by \ac{VLAN} logic, passed to a receive handler associated with a master device, or delivered to a protocol handler \cite{stephan2024packetpath}. The receive handler is particularly relevant for Linux bridges. If the ingress interface is enslaved to a bridge, the bridge receive handler can take ownership of the packet before the packet is delivered to the local \ac{IP} stack \cite{linuxkernelbridgedocs}.
For the present thesis, this complete packet path is particularly important because the developed system relies on Linux kernel mechanisms at multiple points of the communication path. The system captures traffic at Layer 2, uses bridge-based forwarding, observes and correlates packets while they traverse ingress and egress processing stages, and manipulates traffic by attaching filtering and processing logic within the kernel-controlled forwarding path.
\subsection{Local Delivery and \ac{IP} Forwarding}
If the packet is an \ac{IP} packet and is not taken over by a bridge or another master device, the \ac{IP} receive function processes it. For \ac{IPv4}, this path includes \texttt{ip\_rcv()}. The kernel validates essential header fields, checks packet length and checksum information, sets the transport header pointer, and invokes the \texttt{netfilter} \texttt{PRE\_ROUTING} hook. Afterwards, the routing decision determines whether the packet is locally delivered, forwarded to another interface, or handled as multicast traffic \cite{stephan2024packetpath}.
For local delivery, the packet follows the input path. Fragmented packets may first be reassembled. The packet then reaches the \texttt{netfilter} \texttt{LOCAL\_IN} hook and is passed to the appropriate transport-layer handler. For \ac{TCP}, Linux performs socket lookup, checksum validation, state-machine processing, sequence-number handling, and receive-queue insertion. For \ac{UDP}, the path is shorter and mainly consists of checksum validation, socket lookup, and datagram delivery. Finally, a user-space application reads the data through a system call such as \texttt{recv()} or \texttt{read()} \cite{stephan2024packetpath}.
For routed forwarding, the packet follows a different path. After the routing decision, \texttt{netfilter} can inspect the packet at the \texttt{FORWARD} hook. If the packet is accepted, Linux applies post-routing processing, performs neighbor resolution if necessary, and sends the packet to the selected output device. The kernel documentation on \texttt{netfilter} \texttt{flowtable} processing describes this classic forwarding path as a sequence of ingress, prerouting, routing decision, forward, postrouting, and neighbor transmission, while also describing how \texttt{flowtable} offload can bypass parts of that path for later packets of a flow \cite{linuxkernelflowtabledocs}.
\subsection{Ethernet Switching Concepts}
Ethernet switching is based on forwarding at the data link layer. The \ac{IEEE} \texttt{802.1Q-2022} standard specifies the operation of \ac{MAC} bridges and \ac{VLAN} bridges, which interconnect \acp{LAN} below the \ac{MAC} service boundary \cite{ieee8021q2022}. From the perspective of higher-layer protocols, such a bridge should be transparent: endpoints do not need to know that an intermediate bridge forwards the frame. Consequently, forwarding decisions are based on Ethernet destination addresses and bridge state rather than on \ac{IP} routes.
A learning bridge builds forwarding state from the source address of received frames. When a frame enters a bridge port, the bridge can associate the source \ac{MAC} address with the ingress port and store this association in the \ac{FDB} \cite{linuxkernelbridgedocs}. In \ac{VLAN}-aware operation, the relevant forwarding identity also includes the \ac{VLAN}; the Linux switch device documentation describes a bridge \ac{FDB} entry as a \texttt{\{port, mac, vlan\}} forwarding destination \cite{linuxkernelswitchdevdocs}. This distinction matters because the same \ac{MAC} address can belong to different Layer-2 domains when \acp{VLAN} are used.
If the destination address is known, the bridge can forward a unicast frame only to the port associated with that destination. If the destination is located on the same port as the source, the frame can be filtered instead of being sent back to the segment from which it arrived. If no matching destination entry exists, the frame is an unknown unicast and must be flooded to eligible ports in the same forwarding domain. Broadcast frames are also flooded within that domain, and multicast frames are flooded or forwarded according to multicast bridge state \cite{linuxkernelswitchdevdocs}. Thus, a bridge extends a broadcast domain unless \ac{VLAN} filtering or another separation mechanism divides the traffic into distinct Layer-2 domains.
\ac{VLAN} awareness allows one physical or virtual bridge to represent multiple separated broadcast domains. With \texttt{vlan\_filtering} enabled, forwarding decisions depend on both the destination \ac{MAC} address and the \ac{VLAN} tag \cite{linuxkernelbridgedocs}. The \texttt{ip-link(8)} manual describes the same configuration point as \texttt{vlan\_filtering}; when it is disabled, the bridge does not consider the \ac{VLAN} tag during packet handling \cite{man7iplink}.
Layer-2 loops are especially problematic because Ethernet frames do not contain a hop limit comparable to the \ac{IP} \ac{TTL} field. In a looped topology, flooded broadcast, multicast, or unknown-unicast frames can therefore circulate and be replicated until the network becomes unusable. \ac{STP} was introduced to let bridges compute a loop-free active topology in an extended \ac{LAN} \cite{perlman1985spanningtree}. \ac{RSTP} later improved reconfiguration behavior and is part of the modern bridge standards lineage described by \texttt{802.1Q} \cite{ieee8021q2022}. In Linux, \ac{STP} controls bridge port states such as blocking, learning, and forwarding, and it uses \acp{BPDU} to exchange topology information \cite{linuxkernelbridgedocs}.
\subsection{Linux Bridge Forwarding Path}
A Linux bridge implements the switching behavior described above inside the kernel. The bridge receives Ethernet frames from enslaved interfaces, learns source addresses, consults the \ac{FDB}, and either forwards, filters, floods, or locally delivers frames depending on the destination address and bridge configuration \cite{linuxkernelbridgedocs}. The \texttt{bridge} command exposes this state through objects such as \texttt{fdb}, \texttt{vlan}, and \texttt{link} \cite{man7bridge}.
This Layer-2 behavior is central for transparent interception. When two hosts communicate through a Linux bridge, their packets do not need to be routed by the bridge. Therefore, no additional \ac{IP} hop is introduced and the \ac{TTL} or hop-limit value is not decremented by normal bridge forwarding. From the perspective of the endpoints, the bridge behaves like an Ethernet segment or switch, although the kernel can still inspect, mark, filter, and capture frames while they traverse the bridge.
The bridge path has its own \texttt{netfilter} integration \cite{nftablesbridgefiltering}. The \texttt{nftables} \texttt{bridge} family provides hook points before and after the \ac{FDB} decision \cite{nftablesbridgefiltering}. In the \texttt{prerouting} hook, packets can be filtered before the bridge decides the output port. In the \texttt{forward} hook, packets can be filtered when they are bridged from one port to another. The \texttt{input} hook covers frames passed to the local stack, \texttt{output} covers frames coming from the local stack toward a bridge port, and \texttt{postrouting} covers both locally generated and forwarded bridge traffic \cite{nftablesbridgefiltering}.
The distinction between the \texttt{inet}, \texttt{ip}, and \texttt{bridge} \texttt{nftables} families is important. Rules in the \texttt{ip} or \texttt{inet} family operate on packets that enter the \ac{IP} stack. Rules in the \texttt{bridge} family operate on Ethernet frames in the bridge path. A transparent bridge that should inspect traffic without acting as an \ac{IP} router therefore needs \texttt{bridge}-family rules for Layer-2 forwarding decisions.
For the setup used in the present thesis, \ac{STP} is not required because the bridge is used as a controlled inline bridge between two network segments and no redundant Layer-2 path is intentionally introduced. Disabling \ac{STP} through \texttt{stp\_state} avoids topology negotiation, \ac{BPDU} processing, and forwarding-delay behavior that would otherwise add configuration-dependent effects to packet timing \cite{man7iplink}. This is only safe under the assumption that the physical and virtual topology is loop-free. If additional bridge ports or redundant links are added, \ac{STP} or \ac{RSTP} should remain enabled because Linux uses it to prevent loops and broadcast storms in Ethernet networks \cite{linuxkernelbridgedocs}.
\subsection{Egress Path}
The egress path depends on where the packet originates. For locally generated traffic, the path begins when an application writes to a socket. The socket layer calls functions such as \texttt{sock\_sendmsg()}, which select the transport-layer implementation. At this point, \acp{LSM} may already apply security checks. The \ac{TCP} implementation segments data, maintains connection state, enforces congestion-control behavior, and enqueues \texttt{sk\_buff} structures in the socket write queue. The \ac{UDP} implementation builds datagrams with less connection state and less protocol machinery \cite{stephan2024packetpath}.
After transport-layer processing, the packet enters the \ac{IP} output path. Linux determines the route, often by consulting the \ac{FIB}, and builds the \ac{IP} header. \texttt{Netfilter} can inspect locally generated traffic at \texttt{LOCAL\_OUT} and later at \texttt{POST\_ROUTING}. If the destination is on an Ethernet network, the neighbor subsystem resolves the next-hop \ac{MAC} address, for example through \ac{ARP}. Then the Ethernet header is prepared and the packet is passed to the device transmission path \cite{stephan2024packetpath}.
For both locally generated and forwarded packets, the final transmission path goes through the network device queueing layer. Linux calls \texttt{dev\_queue\_xmit()}, where queueing disciplines can schedule, delay, classify, or drop packets. \texttt{tc} egress programs can also run at this stage. Afterwards, the driver transmission function, commonly exposed as \texttt{ndo\_start\_xmit}, places the packet into the transmit ring of the \ac{NIC}. The packet buffer is mapped for \ac{DMA}, and the hardware transmits the frame onto the physical medium \cite{stephan2024packetpath}.
For bridged packets, the local socket and transport-layer construction steps are skipped. The packet already exists as an Ethernet frame. After the bridge has selected an output port and the frame has passed the relevant bridge filtering hooks, the packet enters the output device path and is eventually queued for transmission on the selected interface. Consequently, \texttt{tc} egress and device-level queueing remain relevant even for purely bridged traffic.
\subsection{Programmable Hook Points}
Linux provides several hook points that allow packet processing to be extended without modifying the kernel source code. \ac{eBPF}, the successor of \ac{BPF}, is one of the main mechanisms for this \cite{man7tcbpf}. It allows user-supplied programs to be loaded into the kernel and executed at designated hooks after verification by the kernel \cite{gbadamosi2024ebpfruntime}. The verifier is intended to ensure that programs cannot corrupt kernel memory or run without bounds, while just-in-time compilation can provide efficient execution \cite{man7tcbpf}.
\texttt{Netfilter} and \texttt{nftables} provide another programmable processing layer. The \texttt{nftables} hook model distinguishes packet families, hook names, chain types, and priorities. Locally delivered packets pass through \texttt{prerouting} and \texttt{input}; forwarded routed packets pass through \texttt{prerouting}, \texttt{forward}, and \texttt{postrouting}; locally generated packets pass through \texttt{output} and \texttt{postrouting}. Within a hook, priorities determine the order in which \texttt{nftables} chains and internal \texttt{netfilter} operations run \cite{nftableshooks}.
The earliest hook point considered here is \ac{XDP}. Native \ac{XDP} programs are executed in the driver receive path before the normal \texttt{sk\_buff} is allocated \cite{hoilandjorgensen2018xdp}. This position allows very early pass, drop, transmit, and redirect decisions \cite{hoilandjorgensen2018xdp}. Because of this position, \ac{XDP} is suitable for high packet-rate processing \cite{scholz2018ebpfpacketfiltering}. However, because the packet has not yet entered the regular \texttt{sk\_buff}-based networking stack, normal \texttt{sk\_buff} metadata is not available in native \ac{XDP} mode.
After an \texttt{sk\_buff} exists, \texttt{tc} ingress and egress programs can process packets as \ac{eBPF} classifiers \cite{man7tcbpf}. The ingress side is reached shortly after the packet enters the receive path, while the egress side is reached after routing or bridge forwarding has selected an output interface \cite{stephan2024packetpath}. Since these programs operate on an \texttt{\_\_sk\_buff} context, they can inspect packet bytes and use metadata such as \texttt{skb->mark} \cite{man7tcbpf}. This makes \texttt{tc}/\ac{eBPF} useful for low-overhead telemetry and packet correlation without changing the frame transmitted on the wire.
For bridged traffic, \texttt{nftables} \texttt{bridge} hooks provide the main verdict mechanism. Rules in the \texttt{bridge} family are evaluated in the bridge path and can therefore affect Ethernet frames that are forwarded between bridge ports without entering the routed \ac{IP} path \cite{nftablesbridgefiltering}. In particular, \texttt{bridge}-family rules can be attached before or after the \ac{FDB} decision \cite{nftablesbridgefiltering}. They can be used to accept, drop, or redirect frames at Layer 2 \cite{westphal2016bridgefiltering}.
For passive raw capture, Linux provides packet sockets through \texttt{AF\_PACKET}. Packet sockets are used to receive or send raw packets at the device-driver level and can be bound to a specific interface \cite{man7packet}. This makes them suitable for Layer-2 observation of Ethernet frames. In the context of a forwarding bridge, such capture is conceptually separate from the bridge forwarding decision, because observing a packet through a packet socket does not itself define the packet's forwarding verdict.
Lastly, \texttt{tracepoint} hooks expose selected kernel events to tracing tools and \ac{eBPF} programs \cite{linuxkerneltracepointsdocs}. They are useful for events that are difficult to infer from raw packet captures alone, for example packet free or drop paths. In such cases, \texttt{tracepoint}-based telemetry can complement ingress and egress observations by providing metadata about what happened to an \texttt{sk\_buff} inside the kernel \cite{gbadamosi2024ebpfruntime}.
\ac{NFQUEUE} is built on top of \texttt{netfilter}. A rule can queue a packet to user space, where an application inspects the packet and returns a verdict such as accept, drop, or modified accept. This is more flexible than a purely in-kernel rule, but it also introduces user-kernel transfer overhead and makes packet latency depend on the user-space application. Therefore, \ac{NFQUEUE} is suitable for programmable manipulation, while early in-kernel hooks are better suited for low-overhead telemetry or simple filtering.
For the present thesis, these hook points explain the structure of the developed system. Raw packet capture observes frame contents, \texttt{tc}/\ac{eBPF} telemetry observes kernel metadata on ingress and egress, \texttt{nftables} \texttt{bridge} rules can decide the fate of bridged packets, and packet marks can connect observations from different stages of the same kernel path. Since a single Ethernet frame can be captured, cloned, forwarded, marked, and later observed again on another interface, reliable correlation requires an explicit packet identity or a stable reconstruction from packet fields.

View File

@@ -39,6 +39,26 @@
doi = {10.17487/RFC1122}
}
@techreport{rfc1812,
author = {Baker, Fred},
title = {Requirements for {IP} Version 4 Routers},
type = {RFC},
number = {1812},
institution = {RFC Editor},
date = {1995-06},
doi = {10.17487/RFC1812}
}
@techreport{rfc3022,
author = {Srisuresh, Pyda and Egevang, Kjeld},
title = {Traditional {IP} Network Address Translator ({Traditional NAT})},
type = {RFC},
number = {3022},
institution = {RFC Editor},
date = {2001-01},
doi = {10.17487/RFC3022}
}
@inproceedings{stephan2024packetpath,
author = {Stephan, Alexander and W{\"u}strich, Lars},
title = {The Path of a Packet Through the Linux Kernel},
@@ -48,6 +68,149 @@
url = {https://www.net.in.tum.de/fileadmin/TUM/NET/NET-2024-04-1/NET-2024-04-1_16.pdf}
}
@inproceedings{hoilandjorgensen2018xdp,
author = {H{\o}iland-J{\o}rgensen, Toke and Brouer, Jesper Dangaard and Borkmann, Daniel and Fastabend, John and Herbert, Tom and Ahern, David and Miller, David},
title = {The {eXpress} Data Path: Fast Programmable Packet Processing in the Operating System Kernel},
booktitle = {Proceedings of the 14th International Conference on Emerging Networking Experiments and Technologies},
series = {CoNEXT '18},
pages = {54--66},
publisher = {Association for Computing Machinery},
location = {Heraklion, Greece},
date = {2018},
doi = {10.1145/3281411.3281443},
url = {https://doi.org/10.1145/3281411.3281443}
}
@inproceedings{scholz2018ebpfpacketfiltering,
author = {Scholz, Dominik and Raumer, Daniel and Emmerich, Paul and Kurtz, Alexander and Lesiak, Krzysztof and Carle, Georg},
title = {Performance Implications of Packet Filtering with {Linux eBPF}},
booktitle = {2018 30th International Teletraffic Congress},
series = {ITC 30},
pages = {209--217},
publisher = {IEEE},
location = {Vienna, Austria},
date = {2018},
doi = {10.1109/ITC30.2018.00039},
url = {https://www.net.in.tum.de/fileadmin/bibtex/publications/papers/ITC30-Packet-Filtering-eBPF-XDP.pdf}
}
@online{gbadamosi2024ebpfruntime,
author = {Gbadamosi, Bolaji and Leonardi, Luigi and Pulls, Tobias and H{\o}iland-J{\o}rgensen, Toke and Ferlin-Reiter, Simone and Sorce, Simo and Brunstr{\"o}m, Anna},
title = {The {eBPF} Runtime in the {Linux} Kernel},
date = {2024-10-03},
eprint = {2410.00026},
eprinttype = {arXiv},
doi = {10.48550/arXiv.2410.00026},
url = {https://arxiv.org/abs/2410.00026},
urldate = {2026-05-15}
}
@inproceedings{westphal2016bridgefiltering,
author = {Westphal, Florian},
title = {Bridge Filtering with {nftables}},
booktitle = {Proceedings of Netdev 1.1},
location = {Seville, Spain},
date = {2016},
url = {https://netdevconf.org/1.1/proceedings/papers/Bridge-filter-with-nftables.pdf},
urldate = {2026-05-15}
}
@article{conti2016mitmsurvey,
author = {Conti, Mauro and Dragoni, Nicola and Lesyk, Viktor},
title = {A Survey of {Man In The Middle} Attacks},
journaltitle = {IEEE Communications Surveys \& Tutorials},
volume = {18},
number = {3},
pages = {2027--2051},
date = {2016},
doi = {10.1109/COMST.2016.2548426},
url = {https://doi.org/10.1109/COMST.2016.2548426}
}
@article{nam2012arpmitm,
author = {Nam, Seung Yeob and Jurayev, Sirojiddin and Kim, Seung-Sik and Choi, Kwonhue and Choi, Gyu Sang},
title = {Mitigating {ARP} Poisoning-Based {Man-in-the-Middle} Attacks in Wired or Wireless {LAN}},
journaltitle = {EURASIP Journal on Wireless Communications and Networking},
volume = {2012},
number = {1},
eid = {89},
date = {2012},
doi = {10.1186/1687-1499-2012-89},
url = {https://doi.org/10.1186/1687-1499-2012-89}
}
@inproceedings{zhang2007portmirroring,
author = {Zhang, Jian and Moore, Andrew W.},
title = {Traffic Trace Artifacts due to Monitoring Via Port Mirroring},
booktitle = {2007 Workshop on End-to-End Monitoring Techniques and Services},
series = {E2EMON '07},
pages = {1--8},
publisher = {IEEE},
date = {2007},
doi = {10.1109/E2EMON.2007.375317},
url = {https://www.cl.cam.ac.uk/research/srg/netos/papers/2007-zhang2007traffic.pdf},
urldate = {2026-05-16}
}
@inproceedings{durumeric2017httpsinterception,
author = {Durumeric, Zakir and Ma, Zane and Springall, Drew and Barnes, Richard and Sullivan, Nick and Bursztein, Elie and Bailey, Michael and Halderman, J. Alex and Paxson, Vern},
title = {The Security Impact of {HTTPS} Interception},
booktitle = {Proceedings of the Network and Distributed System Security Symposium},
series = {NDSS '17},
date = {2017},
doi = {10.14722/ndss.2017.23456},
url = {https://doi.org/10.14722/ndss.2017.23456}
}
@inproceedings{waked2018tlsinterception,
author = {Waked, Louis and Mannan, Mohammad and Youssef, Amr},
title = {To Intercept or Not to Intercept: Analyzing {TLS} Interception in Network Appliances},
booktitle = {Proceedings of the 2018 {ACM Asia} Conference on Computer and Communications Security},
series = {ASIACCS '18},
pages = {399--412},
publisher = {Association for Computing Machinery},
location = {Incheon, Republic of Korea},
date = {2018},
doi = {10.1145/3196494.3196528},
url = {https://doi.org/10.1145/3196494.3196528}
}
@article{decarnedecarnavalet2023tlsinterception,
author = {de Carn{\'e} de Carnavalet, Xavier and van Oorschot, Paul C.},
title = {A Survey and Analysis of {TLS} Interception Mechanisms and Motivations},
journaltitle = {ACM Computing Surveys},
volume = {55},
number = {13s},
articleno = {269},
pages = {1--40},
date = {2023},
doi = {10.1145/3580522},
url = {https://doi.org/10.1145/3580522}
}
@manual{ieee8021q2022,
author = {{IEEE}},
title = {{IEEE Standard for Local and Metropolitan Area Networks--Bridges and Bridged Networks}},
organization = {IEEE},
type = {IEEE Std 802.1Q-2022},
date = {2022-12-22},
url = {https://standards.ieee.org/ieee/802.1Q/10323/},
urldate = {2026-05-16}
}
@inproceedings{perlman1985spanningtree,
author = {Perlman, Radia},
title = {An Algorithm for Distributed Computation of a Spanningtree in an Extended {LAN}},
booktitle = {Proceedings of the Ninth Symposium on Data Communications},
series = {SIGCOMM '85},
pages = {44--53},
publisher = {Association for Computing Machinery},
location = {Whistler Mountain, British Columbia, Canada},
date = {1985},
doi = {10.1145/319056.319004},
url = {https://doi.org/10.1145/319056.319004}
}
@online{linuxkernelnetworkingdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Networking --- The Linux Kernel documentation},
@@ -71,3 +234,83 @@
url = {https://docs.kernel.org/networking/bridge.html},
urldate = {2026-04-18}
}
@online{linuxkernelswitchdevdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Ethernet switch device driver model (switchdev) --- The Linux Kernel documentation},
year = {2026},
url = {https://www.kernel.org/doc/html/latest/networking/switchdev.html},
urldate = {2026-05-16}
}
@online{linuxkernelflowtabledocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Netfilter's Flowtable Infrastructure --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/nf_flowtable.html},
urldate = {2026-05-15}
}
@online{linuxkernelscalingdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Scaling in the Linux Networking Stack --- The Linux Kernel documentation},
year = {2026},
url = {https://docs.kernel.org/networking/scaling.html},
urldate = {2026-05-15}
}
@online{linuxkerneltracepointsdocs,
author = {{The Linux Kernel Documentation Authors}},
title = {Using the Linux Kernel Tracepoints --- The Linux Kernel documentation},
year = {2026},
url = {https://www.kernel.org/doc/html/latest/trace/tracepoints.html},
urldate = {2026-05-16}
}
@online{man7packet,
author = {{Linux man-pages project}},
title = {packet(7) --- Linux manual page},
date = {2025-09-21},
url = {https://man7.org/linux/man-pages/man7/packet.7.html},
urldate = {2026-05-16}
}
@online{man7tcbpf,
author = {{Linux man-pages project}},
title = {tc-bpf(8) --- Linux manual page},
date = {2025-08-08},
url = {https://man7.org/linux/man-pages/man8/tc-bpf.8.html},
urldate = {2026-05-16}
}
@online{man7bridge,
author = {{Linux man-pages project}},
title = {bridge(8) --- Linux manual page},
date = {2012-08-01},
url = {https://man7.org/linux/man-pages/man8/bridge.8.html},
urldate = {2026-05-16}
}
@online{man7iplink,
author = {{Linux man-pages project}},
title = {ip-link(8) --- Linux manual page},
date = {2012-12-13},
url = {https://man7.org/linux/man-pages/man8/ip-link.8.html},
urldate = {2026-05-16}
}
@online{nftableshooks,
author = {{The nftables Project}},
title = {Netfilter Hooks},
year = {2023},
url = {https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks},
urldate = {2026-05-15}
}
@online{nftablesbridgefiltering,
author = {{The nftables Project}},
title = {Bridge Filtering},
year = {2021},
url = {https://wiki.nftables.org/wiki-nftables/index.php/Bridge_filtering},
urldate = {2026-05-15}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,91 @@
setup,category,metric,unit,direction,payload_size_bytes,protocol,count,mean,median,min,max,std
bridge-new,flent,data_file_exists,bool,,,,3,1.0,1.0,1.0,1.0,0.0
bridge-new,iperf_tcp,retransmits,count,forward,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_tcp,retransmits,count,reverse,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_tcp,throughput,Mbit/s,forward,,,1,941.2170773518191,941.2170773518191,941.2170773518191,941.2170773518191,
bridge-new,iperf_tcp,throughput,Mbit/s,reverse,,,1,941.223044856063,941.223044856063,941.223044856063,941.223044856063,
bridge-new,iperf_udp,jitter,ms,forward,,,1,329.1133542566476,329.1133542566476,329.1133542566476,329.1133542566476,
bridge-new,iperf_udp,jitter,ms,reverse,,,1,0.011945675546752457,0.011945675546752457,0.011945675546752457,0.011945675546752457,
bridge-new,iperf_udp,loss,percent,forward,,,1,0.00552541229203311,0.00552541229203311,0.00552541229203311,0.00552541229203311,
bridge-new,iperf_udp,loss,percent,reverse,,,1,0.0,0.0,0.0,0.0,
bridge-new,iperf_udp,throughput,Mbit/s,forward,,,1,691.7975032635362,691.7975032635362,691.7975032635362,691.7975032635362,
bridge-new,iperf_udp,throughput,Mbit/s,reverse,,,1,899.980891114048,899.980891114048,899.980891114048,899.980891114048,
bridge-new,ping,jitter_mean_abs_delta,ms,,56.0,,1,0.25014242848569707,0.25014242848569707,0.25014242848569707,0.25014242848569707,
bridge-new,ping,jitter_mean_abs_delta,ms,,512.0,,1,0.20838367673534708,0.20838367673534708,0.20838367673534708,0.20838367673534708,
bridge-new,ping,jitter_mean_abs_delta,ms,,1472.0,,1,0.18928945789157833,0.18928945789157833,0.18928945789157833,0.18928945789157833,
bridge-new,ping,loss,percent,,56.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,loss,percent,,512.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,loss,percent,,1472.0,,1,0.0,0.0,0.0,0.0,
bridge-new,ping,rtt_iqr,ms,,56.0,,1,0.20999999999999974,0.20999999999999974,0.20999999999999974,0.20999999999999974,
bridge-new,ping,rtt_iqr,ms,,512.0,,1,0.17000000000000015,0.17000000000000015,0.17000000000000015,0.17000000000000015,
bridge-new,ping,rtt_iqr,ms,,1472.0,,1,0.15999999999999992,0.15999999999999992,0.15999999999999992,0.15999999999999992,
bridge-new,ping,rtt_mad,ms,,56.0,,1,0.06999999999999984,0.06999999999999984,0.06999999999999984,0.06999999999999984,
bridge-new,ping,rtt_mad,ms,,512.0,,1,0.050000000000000266,0.050000000000000266,0.050000000000000266,0.050000000000000266,
bridge-new,ping,rtt_mad,ms,,1472.0,,1,0.040000000000000036,0.040000000000000036,0.040000000000000036,0.040000000000000036,
bridge-new,ping,rtt_max,ms,,56.0,,1,2.24,2.24,2.24,2.24,
bridge-new,ping,rtt_max,ms,,512.0,,1,2.31,2.31,2.31,2.31,
bridge-new,ping,rtt_max,ms,,1472.0,,1,2.36,2.36,2.36,2.36,
bridge-new,ping,rtt_mean,ms,,56.0,,1,1.7996464,1.7996464,1.7996464,1.7996464,
bridge-new,ping,rtt_mean,ms,,512.0,,1,1.866984,1.866984,1.866984,1.866984,
bridge-new,ping,rtt_mean,ms,,1472.0,,1,1.910105,1.910105,1.910105,1.910105,
bridge-new,ping,rtt_median,ms,,56.0,,1,1.98,1.98,1.98,1.98,
bridge-new,ping,rtt_median,ms,,512.0,,1,2.03,2.03,2.03,2.03,
bridge-new,ping,rtt_median,ms,,1472.0,,1,2.08,2.08,2.08,2.08,
bridge-new,ping,rtt_min,ms,,56.0,,1,0.279,0.279,0.279,0.279,
bridge-new,ping,rtt_min,ms,,512.0,,1,0.306,0.306,0.306,0.306,
bridge-new,ping,rtt_min,ms,,1472.0,,1,0.373,0.373,0.373,0.373,
bridge-new,ping,rtt_p95,ms,,56.0,,1,2.09,2.09,2.09,2.09,
bridge-new,ping,rtt_p95,ms,,512.0,,1,2.13,2.13,2.13,2.13,
bridge-new,ping,rtt_p95,ms,,1472.0,,1,2.18,2.18,2.18,2.18,
bridge-new,ping,rtt_p99,ms,,56.0,,1,2.14,2.14,2.14,2.14,
bridge-new,ping,rtt_p99,ms,,512.0,,1,2.17,2.17,2.17,2.17,
bridge-new,ping,rtt_p99,ms,,1472.0,,1,2.21,2.21,2.21,2.21,
bridge-new,ping,rtt_stdev,ms,,56.0,,1,0.42052572542496,0.42052572542496,0.42052572542496,0.42052572542496,
bridge-new,ping,rtt_stdev,ms,,512.0,,1,0.38826014131180947,0.38826014131180947,0.38826014131180947,0.38826014131180947,
bridge-new,ping,rtt_stdev,ms,,1472.0,,1,0.40225082364120024,0.40225082364120024,0.40225082364120024,0.40225082364120024,
bridge-new,sockperf,avg_latency_usec,us,,,tcp,1,242.02,242.02,242.02,242.02,
direct,flent,data_file_exists,bool,,,,3,1.0,1.0,1.0,1.0,0.0
direct,iperf_tcp,retransmits,count,forward,,,1,0.0,0.0,0.0,0.0,
direct,iperf_tcp,retransmits,count,reverse,,,1,0.0,0.0,0.0,0.0,
direct,iperf_tcp,throughput,Mbit/s,forward,,,1,941.4052500378058,941.4052500378058,941.4052500378058,941.4052500378058,
direct,iperf_tcp,throughput,Mbit/s,reverse,,,1,941.4233862520524,941.4233862520524,941.4233862520524,941.4233862520524,
direct,iperf_udp,jitter,ms,forward,,,1,0.010443516671235937,0.010443516671235937,0.010443516671235937,0.010443516671235937,
direct,iperf_udp,jitter,ms,reverse,,,1,0.010410725838564765,0.010410725838564765,0.010410725838564765,0.010410725838564765,
direct,iperf_udp,loss,percent,forward,,,1,0.0,0.0,0.0,0.0,
direct,iperf_udp,loss,percent,reverse,,,1,0.002895969068476154,0.002895969068476154,0.002895969068476154,0.002895969068476154,
direct,iperf_udp,throughput,Mbit/s,forward,,,1,899.951785108759,899.951785108759,899.951785108759,899.951785108759,
direct,iperf_udp,throughput,Mbit/s,reverse,,,1,899.961104896446,899.961104896446,899.961104896446,899.961104896446,
direct,ping,jitter_mean_abs_delta,ms,,56.0,,1,0.16798879775955192,0.16798879775955192,0.16798879775955192,0.16798879775955192,
direct,ping,jitter_mean_abs_delta,ms,,512.0,,1,0.18655691138227648,0.18655691138227648,0.18655691138227648,0.18655691138227648,
direct,ping,jitter_mean_abs_delta,ms,,1472.0,,1,0.18377075415083016,0.18377075415083016,0.18377075415083016,0.18377075415083016,
direct,ping,loss,percent,,56.0,,1,0.0,0.0,0.0,0.0,
direct,ping,loss,percent,,512.0,,1,0.0,0.0,0.0,0.0,
direct,ping,loss,percent,,1472.0,,1,0.0,0.0,0.0,0.0,
direct,ping,rtt_iqr,ms,,56.0,,1,0.14000000000000012,0.14000000000000012,0.14000000000000012,0.14000000000000012,
direct,ping,rtt_iqr,ms,,512.0,,1,0.16000000000000014,0.16000000000000014,0.16000000000000014,0.16000000000000014,
direct,ping,rtt_iqr,ms,,1472.0,,1,0.1200000000000001,0.1200000000000001,0.1200000000000001,0.1200000000000001,
direct,ping,rtt_mad,ms,,56.0,,1,0.040000000000000036,0.040000000000000036,0.040000000000000036,0.040000000000000036,
direct,ping,rtt_mad,ms,,512.0,,1,0.08000000000000007,0.08000000000000007,0.08000000000000007,0.08000000000000007,
direct,ping,rtt_mad,ms,,1472.0,,1,0.05999999999999983,0.05999999999999983,0.05999999999999983,0.05999999999999983,
direct,ping,rtt_max,ms,,56.0,,1,1.74,1.74,1.74,1.74,
direct,ping,rtt_max,ms,,512.0,,1,1.78,1.78,1.78,1.78,
direct,ping,rtt_max,ms,,1472.0,,1,1.81,1.81,1.81,1.81,
direct,ping,rtt_mean,ms,,56.0,,1,1.3608360000000002,1.3608360000000002,1.3608360000000002,1.3608360000000002,
direct,ping,rtt_mean,ms,,512.0,,1,1.3263896000000002,1.3263896000000002,1.3263896000000002,1.3263896000000002,
direct,ping,rtt_mean,ms,,1472.0,,1,1.335693,1.335693,1.335693,1.335693,
direct,ping,rtt_median,ms,,56.0,,1,1.51,1.51,1.51,1.51,
direct,ping,rtt_median,ms,,512.0,,1,1.48,1.48,1.48,1.48,
direct,ping,rtt_median,ms,,1472.0,,1,1.43,1.43,1.43,1.43,
direct,ping,rtt_min,ms,,56.0,,1,0.027,0.027,0.027,0.027,
direct,ping,rtt_min,ms,,512.0,,1,0.043,0.043,0.043,0.043,
direct,ping,rtt_min,ms,,1472.0,,1,0.077,0.077,0.077,0.077,
direct,ping,rtt_p95,ms,,56.0,,1,1.59,1.59,1.59,1.59,
direct,ping,rtt_p95,ms,,512.0,,1,1.6,1.6,1.6,1.6,
direct,ping,rtt_p95,ms,,1472.0,,1,1.63,1.63,1.63,1.63,
direct,ping,rtt_p99,ms,,56.0,,1,1.66,1.66,1.66,1.66,
direct,ping,rtt_p99,ms,,512.0,,1,1.65,1.65,1.65,1.65,
direct,ping,rtt_p99,ms,,1472.0,,1,1.68,1.68,1.68,1.68,
direct,ping,rtt_stdev,ms,,56.0,,1,0.38241341543944507,0.38241341543944507,0.38241341543944507,0.38241341543944507,
direct,ping,rtt_stdev,ms,,512.0,,1,0.41370645730808175,0.41370645730808175,0.41370645730808175,0.41370645730808175,
direct,ping,rtt_stdev,ms,,1472.0,,1,0.36380108603059363,0.36380108603059363,0.36380108603059363,0.36380108603059363,
direct,sockperf,avg_latency_usec,us,,,tcp,1,21.286,21.286,21.286,21.286,
1 setup category metric unit direction payload_size_bytes protocol count mean median min max std
2 bridge-new flent data_file_exists bool 3 1.0 1.0 1.0 1.0 0.0
3 bridge-new iperf_tcp retransmits count forward 1 0.0 0.0 0.0 0.0
4 bridge-new iperf_tcp retransmits count reverse 1 0.0 0.0 0.0 0.0
5 bridge-new iperf_tcp throughput Mbit/s forward 1 941.2170773518191 941.2170773518191 941.2170773518191 941.2170773518191
6 bridge-new iperf_tcp throughput Mbit/s reverse 1 941.223044856063 941.223044856063 941.223044856063 941.223044856063
7 bridge-new iperf_udp jitter ms forward 1 329.1133542566476 329.1133542566476 329.1133542566476 329.1133542566476
8 bridge-new iperf_udp jitter ms reverse 1 0.011945675546752457 0.011945675546752457 0.011945675546752457 0.011945675546752457
9 bridge-new iperf_udp loss percent forward 1 0.00552541229203311 0.00552541229203311 0.00552541229203311 0.00552541229203311
10 bridge-new iperf_udp loss percent reverse 1 0.0 0.0 0.0 0.0
11 bridge-new iperf_udp throughput Mbit/s forward 1 691.7975032635362 691.7975032635362 691.7975032635362 691.7975032635362
12 bridge-new iperf_udp throughput Mbit/s reverse 1 899.980891114048 899.980891114048 899.980891114048 899.980891114048
13 bridge-new ping jitter_mean_abs_delta ms 56.0 1 0.25014242848569707 0.25014242848569707 0.25014242848569707 0.25014242848569707
14 bridge-new ping jitter_mean_abs_delta ms 512.0 1 0.20838367673534708 0.20838367673534708 0.20838367673534708 0.20838367673534708
15 bridge-new ping jitter_mean_abs_delta ms 1472.0 1 0.18928945789157833 0.18928945789157833 0.18928945789157833 0.18928945789157833
16 bridge-new ping loss percent 56.0 1 0.0 0.0 0.0 0.0
17 bridge-new ping loss percent 512.0 1 0.0 0.0 0.0 0.0
18 bridge-new ping loss percent 1472.0 1 0.0 0.0 0.0 0.0
19 bridge-new ping rtt_iqr ms 56.0 1 0.20999999999999974 0.20999999999999974 0.20999999999999974 0.20999999999999974
20 bridge-new ping rtt_iqr ms 512.0 1 0.17000000000000015 0.17000000000000015 0.17000000000000015 0.17000000000000015
21 bridge-new ping rtt_iqr ms 1472.0 1 0.15999999999999992 0.15999999999999992 0.15999999999999992 0.15999999999999992
22 bridge-new ping rtt_mad ms 56.0 1 0.06999999999999984 0.06999999999999984 0.06999999999999984 0.06999999999999984
23 bridge-new ping rtt_mad ms 512.0 1 0.050000000000000266 0.050000000000000266 0.050000000000000266 0.050000000000000266
24 bridge-new ping rtt_mad ms 1472.0 1 0.040000000000000036 0.040000000000000036 0.040000000000000036 0.040000000000000036
25 bridge-new ping rtt_max ms 56.0 1 2.24 2.24 2.24 2.24
26 bridge-new ping rtt_max ms 512.0 1 2.31 2.31 2.31 2.31
27 bridge-new ping rtt_max ms 1472.0 1 2.36 2.36 2.36 2.36
28 bridge-new ping rtt_mean ms 56.0 1 1.7996464 1.7996464 1.7996464 1.7996464
29 bridge-new ping rtt_mean ms 512.0 1 1.866984 1.866984 1.866984 1.866984
30 bridge-new ping rtt_mean ms 1472.0 1 1.910105 1.910105 1.910105 1.910105
31 bridge-new ping rtt_median ms 56.0 1 1.98 1.98 1.98 1.98
32 bridge-new ping rtt_median ms 512.0 1 2.03 2.03 2.03 2.03
33 bridge-new ping rtt_median ms 1472.0 1 2.08 2.08 2.08 2.08
34 bridge-new ping rtt_min ms 56.0 1 0.279 0.279 0.279 0.279
35 bridge-new ping rtt_min ms 512.0 1 0.306 0.306 0.306 0.306
36 bridge-new ping rtt_min ms 1472.0 1 0.373 0.373 0.373 0.373
37 bridge-new ping rtt_p95 ms 56.0 1 2.09 2.09 2.09 2.09
38 bridge-new ping rtt_p95 ms 512.0 1 2.13 2.13 2.13 2.13
39 bridge-new ping rtt_p95 ms 1472.0 1 2.18 2.18 2.18 2.18
40 bridge-new ping rtt_p99 ms 56.0 1 2.14 2.14 2.14 2.14
41 bridge-new ping rtt_p99 ms 512.0 1 2.17 2.17 2.17 2.17
42 bridge-new ping rtt_p99 ms 1472.0 1 2.21 2.21 2.21 2.21
43 bridge-new ping rtt_stdev ms 56.0 1 0.42052572542496 0.42052572542496 0.42052572542496 0.42052572542496
44 bridge-new ping rtt_stdev ms 512.0 1 0.38826014131180947 0.38826014131180947 0.38826014131180947 0.38826014131180947
45 bridge-new ping rtt_stdev ms 1472.0 1 0.40225082364120024 0.40225082364120024 0.40225082364120024 0.40225082364120024
46 bridge-new sockperf avg_latency_usec us tcp 1 242.02 242.02 242.02 242.02
47 direct flent data_file_exists bool 3 1.0 1.0 1.0 1.0 0.0
48 direct iperf_tcp retransmits count forward 1 0.0 0.0 0.0 0.0
49 direct iperf_tcp retransmits count reverse 1 0.0 0.0 0.0 0.0
50 direct iperf_tcp throughput Mbit/s forward 1 941.4052500378058 941.4052500378058 941.4052500378058 941.4052500378058
51 direct iperf_tcp throughput Mbit/s reverse 1 941.4233862520524 941.4233862520524 941.4233862520524 941.4233862520524
52 direct iperf_udp jitter ms forward 1 0.010443516671235937 0.010443516671235937 0.010443516671235937 0.010443516671235937
53 direct iperf_udp jitter ms reverse 1 0.010410725838564765 0.010410725838564765 0.010410725838564765 0.010410725838564765
54 direct iperf_udp loss percent forward 1 0.0 0.0 0.0 0.0
55 direct iperf_udp loss percent reverse 1 0.002895969068476154 0.002895969068476154 0.002895969068476154 0.002895969068476154
56 direct iperf_udp throughput Mbit/s forward 1 899.951785108759 899.951785108759 899.951785108759 899.951785108759
57 direct iperf_udp throughput Mbit/s reverse 1 899.961104896446 899.961104896446 899.961104896446 899.961104896446
58 direct ping jitter_mean_abs_delta ms 56.0 1 0.16798879775955192 0.16798879775955192 0.16798879775955192 0.16798879775955192
59 direct ping jitter_mean_abs_delta ms 512.0 1 0.18655691138227648 0.18655691138227648 0.18655691138227648 0.18655691138227648
60 direct ping jitter_mean_abs_delta ms 1472.0 1 0.18377075415083016 0.18377075415083016 0.18377075415083016 0.18377075415083016
61 direct ping loss percent 56.0 1 0.0 0.0 0.0 0.0
62 direct ping loss percent 512.0 1 0.0 0.0 0.0 0.0
63 direct ping loss percent 1472.0 1 0.0 0.0 0.0 0.0
64 direct ping rtt_iqr ms 56.0 1 0.14000000000000012 0.14000000000000012 0.14000000000000012 0.14000000000000012
65 direct ping rtt_iqr ms 512.0 1 0.16000000000000014 0.16000000000000014 0.16000000000000014 0.16000000000000014
66 direct ping rtt_iqr ms 1472.0 1 0.1200000000000001 0.1200000000000001 0.1200000000000001 0.1200000000000001
67 direct ping rtt_mad ms 56.0 1 0.040000000000000036 0.040000000000000036 0.040000000000000036 0.040000000000000036
68 direct ping rtt_mad ms 512.0 1 0.08000000000000007 0.08000000000000007 0.08000000000000007 0.08000000000000007
69 direct ping rtt_mad ms 1472.0 1 0.05999999999999983 0.05999999999999983 0.05999999999999983 0.05999999999999983
70 direct ping rtt_max ms 56.0 1 1.74 1.74 1.74 1.74
71 direct ping rtt_max ms 512.0 1 1.78 1.78 1.78 1.78
72 direct ping rtt_max ms 1472.0 1 1.81 1.81 1.81 1.81
73 direct ping rtt_mean ms 56.0 1 1.3608360000000002 1.3608360000000002 1.3608360000000002 1.3608360000000002
74 direct ping rtt_mean ms 512.0 1 1.3263896000000002 1.3263896000000002 1.3263896000000002 1.3263896000000002
75 direct ping rtt_mean ms 1472.0 1 1.335693 1.335693 1.335693 1.335693
76 direct ping rtt_median ms 56.0 1 1.51 1.51 1.51 1.51
77 direct ping rtt_median ms 512.0 1 1.48 1.48 1.48 1.48
78 direct ping rtt_median ms 1472.0 1 1.43 1.43 1.43 1.43
79 direct ping rtt_min ms 56.0 1 0.027 0.027 0.027 0.027
80 direct ping rtt_min ms 512.0 1 0.043 0.043 0.043 0.043
81 direct ping rtt_min ms 1472.0 1 0.077 0.077 0.077 0.077
82 direct ping rtt_p95 ms 56.0 1 1.59 1.59 1.59 1.59
83 direct ping rtt_p95 ms 512.0 1 1.6 1.6 1.6 1.6
84 direct ping rtt_p95 ms 1472.0 1 1.63 1.63 1.63 1.63
85 direct ping rtt_p99 ms 56.0 1 1.66 1.66 1.66 1.66
86 direct ping rtt_p99 ms 512.0 1 1.65 1.65 1.65 1.65
87 direct ping rtt_p99 ms 1472.0 1 1.68 1.68 1.68 1.68
88 direct ping rtt_stdev ms 56.0 1 0.38241341543944507 0.38241341543944507 0.38241341543944507 0.38241341543944507
89 direct ping rtt_stdev ms 512.0 1 0.41370645730808175 0.41370645730808175 0.41370645730808175 0.41370645730808175
90 direct ping rtt_stdev ms 1472.0 1 0.36380108603059363 0.36380108603059363 0.36380108603059363 0.36380108603059363
91 direct sockperf avg_latency_usec us tcp 1 21.286 21.286 21.286 21.286

View File

@@ -0,0 +1,95 @@
setup,category,metric,value,unit,direction,payload_size_bytes,protocol,test,source
direct,flent,data_file_exists,1.0,bool,,,,rrul,measurments/20260508-221054-direct/summary.json
direct,flent,data_file_exists,1.0,bool,,,,tcp_upload,measurments/20260508-221054-direct/summary.json
direct,flent,data_file_exists,1.0,bool,,,,tcp_download,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,retransmits,0.0,count,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,retransmits,0.0,count,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,throughput,941.4052500378058,Mbit/s,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_tcp,throughput,941.4233862520524,Mbit/s,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,jitter,0.010443516671235937,ms,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,jitter,0.010410725838564765,ms,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,loss,0.0,percent,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,loss,0.002895969068476154,percent,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,throughput,899.951785108759,Mbit/s,forward,,,,measurments/20260508-221054-direct/summary.json
direct,iperf_udp,throughput,899.961104896446,Mbit/s,reverse,,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.16798879775955192,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.18655691138227648,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,jitter_mean_abs_delta,0.18377075415083016,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,loss,0.0,percent,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.14000000000000012,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.16000000000000014,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_iqr,0.1200000000000001,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.040000000000000036,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.08000000000000007,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mad,0.05999999999999983,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.74,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.78,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_max,1.81,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.3608360000000002,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.3263896000000002,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_mean,1.335693,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.51,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.48,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_median,1.43,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.027,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.043,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_min,0.077,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.59,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.6,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p95,1.63,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.66,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.65,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_p99,1.68,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.38241341543944507,ms,,56.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.41370645730808175,ms,,512.0,,,measurments/20260508-221054-direct/summary.json
direct,ping,rtt_stdev,0.36380108603059363,ms,,1472.0,,,measurments/20260508-221054-direct/summary.json
direct,sockperf,avg_latency_usec,21.286,us,,,tcp,,measurments/20260508-221054-direct/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,rrul,measurments/20260508-215553-bridge-new/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,tcp_upload,measurments/20260508-215553-bridge-new/summary.json
bridge-new,flent,data_file_exists,1.0,bool,,,,tcp_download,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,retransmits,0.0,count,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,retransmits,0.0,count,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,throughput,941.2170773518191,Mbit/s,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_tcp,throughput,941.223044856063,Mbit/s,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,jitter,329.1133542566476,ms,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,jitter,0.011945675546752457,ms,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,loss,0.00552541229203311,percent,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,loss,0.0,percent,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,throughput,691.7975032635362,Mbit/s,forward,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,iperf_udp,throughput,899.980891114048,Mbit/s,reverse,,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.25014242848569707,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.20838367673534708,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,jitter_mean_abs_delta,0.18928945789157833,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,loss,0.0,percent,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.20999999999999974,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.17000000000000015,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_iqr,0.15999999999999992,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.06999999999999984,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.050000000000000266,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mad,0.040000000000000036,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.24,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.31,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_max,2.36,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.7996464,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.866984,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_mean,1.910105,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,1.98,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,2.03,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_median,2.08,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.279,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.306,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_min,0.373,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.09,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.13,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p95,2.18,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.14,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.17,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_p99,2.21,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.42052572542496,ms,,56.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.38826014131180947,ms,,512.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,ping,rtt_stdev,0.40225082364120024,ms,,1472.0,,,measurments/20260508-215553-bridge-new/summary.json
bridge-new,sockperf,avg_latency_usec,242.02,us,,,tcp,,measurments/20260508-215553-bridge-new/summary.json
1 setup category metric value unit direction payload_size_bytes protocol test source
2 direct flent data_file_exists 1.0 bool rrul measurments/20260508-221054-direct/summary.json
3 direct flent data_file_exists 1.0 bool tcp_upload measurments/20260508-221054-direct/summary.json
4 direct flent data_file_exists 1.0 bool tcp_download measurments/20260508-221054-direct/summary.json
5 direct iperf_tcp retransmits 0.0 count forward measurments/20260508-221054-direct/summary.json
6 direct iperf_tcp retransmits 0.0 count reverse measurments/20260508-221054-direct/summary.json
7 direct iperf_tcp throughput 941.4052500378058 Mbit/s forward measurments/20260508-221054-direct/summary.json
8 direct iperf_tcp throughput 941.4233862520524 Mbit/s reverse measurments/20260508-221054-direct/summary.json
9 direct iperf_udp jitter 0.010443516671235937 ms forward measurments/20260508-221054-direct/summary.json
10 direct iperf_udp jitter 0.010410725838564765 ms reverse measurments/20260508-221054-direct/summary.json
11 direct iperf_udp loss 0.0 percent forward measurments/20260508-221054-direct/summary.json
12 direct iperf_udp loss 0.002895969068476154 percent reverse measurments/20260508-221054-direct/summary.json
13 direct iperf_udp throughput 899.951785108759 Mbit/s forward measurments/20260508-221054-direct/summary.json
14 direct iperf_udp throughput 899.961104896446 Mbit/s reverse measurments/20260508-221054-direct/summary.json
15 direct ping jitter_mean_abs_delta 0.16798879775955192 ms 56.0 measurments/20260508-221054-direct/summary.json
16 direct ping jitter_mean_abs_delta 0.18655691138227648 ms 512.0 measurments/20260508-221054-direct/summary.json
17 direct ping jitter_mean_abs_delta 0.18377075415083016 ms 1472.0 measurments/20260508-221054-direct/summary.json
18 direct ping loss 0.0 percent 56.0 measurments/20260508-221054-direct/summary.json
19 direct ping loss 0.0 percent 512.0 measurments/20260508-221054-direct/summary.json
20 direct ping loss 0.0 percent 1472.0 measurments/20260508-221054-direct/summary.json
21 direct ping rtt_iqr 0.14000000000000012 ms 56.0 measurments/20260508-221054-direct/summary.json
22 direct ping rtt_iqr 0.16000000000000014 ms 512.0 measurments/20260508-221054-direct/summary.json
23 direct ping rtt_iqr 0.1200000000000001 ms 1472.0 measurments/20260508-221054-direct/summary.json
24 direct ping rtt_mad 0.040000000000000036 ms 56.0 measurments/20260508-221054-direct/summary.json
25 direct ping rtt_mad 0.08000000000000007 ms 512.0 measurments/20260508-221054-direct/summary.json
26 direct ping rtt_mad 0.05999999999999983 ms 1472.0 measurments/20260508-221054-direct/summary.json
27 direct ping rtt_max 1.74 ms 56.0 measurments/20260508-221054-direct/summary.json
28 direct ping rtt_max 1.78 ms 512.0 measurments/20260508-221054-direct/summary.json
29 direct ping rtt_max 1.81 ms 1472.0 measurments/20260508-221054-direct/summary.json
30 direct ping rtt_mean 1.3608360000000002 ms 56.0 measurments/20260508-221054-direct/summary.json
31 direct ping rtt_mean 1.3263896000000002 ms 512.0 measurments/20260508-221054-direct/summary.json
32 direct ping rtt_mean 1.335693 ms 1472.0 measurments/20260508-221054-direct/summary.json
33 direct ping rtt_median 1.51 ms 56.0 measurments/20260508-221054-direct/summary.json
34 direct ping rtt_median 1.48 ms 512.0 measurments/20260508-221054-direct/summary.json
35 direct ping rtt_median 1.43 ms 1472.0 measurments/20260508-221054-direct/summary.json
36 direct ping rtt_min 0.027 ms 56.0 measurments/20260508-221054-direct/summary.json
37 direct ping rtt_min 0.043 ms 512.0 measurments/20260508-221054-direct/summary.json
38 direct ping rtt_min 0.077 ms 1472.0 measurments/20260508-221054-direct/summary.json
39 direct ping rtt_p95 1.59 ms 56.0 measurments/20260508-221054-direct/summary.json
40 direct ping rtt_p95 1.6 ms 512.0 measurments/20260508-221054-direct/summary.json
41 direct ping rtt_p95 1.63 ms 1472.0 measurments/20260508-221054-direct/summary.json
42 direct ping rtt_p99 1.66 ms 56.0 measurments/20260508-221054-direct/summary.json
43 direct ping rtt_p99 1.65 ms 512.0 measurments/20260508-221054-direct/summary.json
44 direct ping rtt_p99 1.68 ms 1472.0 measurments/20260508-221054-direct/summary.json
45 direct ping rtt_stdev 0.38241341543944507 ms 56.0 measurments/20260508-221054-direct/summary.json
46 direct ping rtt_stdev 0.41370645730808175 ms 512.0 measurments/20260508-221054-direct/summary.json
47 direct ping rtt_stdev 0.36380108603059363 ms 1472.0 measurments/20260508-221054-direct/summary.json
48 direct sockperf avg_latency_usec 21.286 us tcp measurments/20260508-221054-direct/summary.json
49 bridge-new flent data_file_exists 1.0 bool rrul measurments/20260508-215553-bridge-new/summary.json
50 bridge-new flent data_file_exists 1.0 bool tcp_upload measurments/20260508-215553-bridge-new/summary.json
51 bridge-new flent data_file_exists 1.0 bool tcp_download measurments/20260508-215553-bridge-new/summary.json
52 bridge-new iperf_tcp retransmits 0.0 count forward measurments/20260508-215553-bridge-new/summary.json
53 bridge-new iperf_tcp retransmits 0.0 count reverse measurments/20260508-215553-bridge-new/summary.json
54 bridge-new iperf_tcp throughput 941.2170773518191 Mbit/s forward measurments/20260508-215553-bridge-new/summary.json
55 bridge-new iperf_tcp throughput 941.223044856063 Mbit/s reverse measurments/20260508-215553-bridge-new/summary.json
56 bridge-new iperf_udp jitter 329.1133542566476 ms forward measurments/20260508-215553-bridge-new/summary.json
57 bridge-new iperf_udp jitter 0.011945675546752457 ms reverse measurments/20260508-215553-bridge-new/summary.json
58 bridge-new iperf_udp loss 0.00552541229203311 percent forward measurments/20260508-215553-bridge-new/summary.json
59 bridge-new iperf_udp loss 0.0 percent reverse measurments/20260508-215553-bridge-new/summary.json
60 bridge-new iperf_udp throughput 691.7975032635362 Mbit/s forward measurments/20260508-215553-bridge-new/summary.json
61 bridge-new iperf_udp throughput 899.980891114048 Mbit/s reverse measurments/20260508-215553-bridge-new/summary.json
62 bridge-new ping jitter_mean_abs_delta 0.25014242848569707 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
63 bridge-new ping jitter_mean_abs_delta 0.20838367673534708 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
64 bridge-new ping jitter_mean_abs_delta 0.18928945789157833 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
65 bridge-new ping loss 0.0 percent 56.0 measurments/20260508-215553-bridge-new/summary.json
66 bridge-new ping loss 0.0 percent 512.0 measurments/20260508-215553-bridge-new/summary.json
67 bridge-new ping loss 0.0 percent 1472.0 measurments/20260508-215553-bridge-new/summary.json
68 bridge-new ping rtt_iqr 0.20999999999999974 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
69 bridge-new ping rtt_iqr 0.17000000000000015 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
70 bridge-new ping rtt_iqr 0.15999999999999992 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
71 bridge-new ping rtt_mad 0.06999999999999984 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
72 bridge-new ping rtt_mad 0.050000000000000266 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
73 bridge-new ping rtt_mad 0.040000000000000036 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
74 bridge-new ping rtt_max 2.24 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
75 bridge-new ping rtt_max 2.31 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
76 bridge-new ping rtt_max 2.36 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
77 bridge-new ping rtt_mean 1.7996464 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
78 bridge-new ping rtt_mean 1.866984 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
79 bridge-new ping rtt_mean 1.910105 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
80 bridge-new ping rtt_median 1.98 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
81 bridge-new ping rtt_median 2.03 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
82 bridge-new ping rtt_median 2.08 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
83 bridge-new ping rtt_min 0.279 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
84 bridge-new ping rtt_min 0.306 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
85 bridge-new ping rtt_min 0.373 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
86 bridge-new ping rtt_p95 2.09 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
87 bridge-new ping rtt_p95 2.13 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
88 bridge-new ping rtt_p95 2.18 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
89 bridge-new ping rtt_p99 2.14 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
90 bridge-new ping rtt_p99 2.17 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
91 bridge-new ping rtt_p99 2.21 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
92 bridge-new ping rtt_stdev 0.42052572542496 ms 56.0 measurments/20260508-215553-bridge-new/summary.json
93 bridge-new ping rtt_stdev 0.38826014131180947 ms 512.0 measurments/20260508-215553-bridge-new/summary.json
94 bridge-new ping rtt_stdev 0.40225082364120024 ms 1472.0 measurments/20260508-215553-bridge-new/summary.json
95 bridge-new sockperf avg_latency_usec 242.02 us tcp measurments/20260508-215553-bridge-new/summary.json

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -0,0 +1,910 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="510.348pt" height="297.523321pt" viewBox="0 0 510.348 297.523321" xmlns="http://www.w3.org/2000/svg" version="1.1">
<metadata>
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:date>2026-05-10T16:24:20.591445</dc:date>
<dc:format>image/svg+xml</dc:format>
<dc:creator>
<cc:Agent>
<dc:title>Matplotlib v3.6.3, https://matplotlib.org/</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs>
<style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
</defs>
<g id="figure_1">
<g id="patch_1">
<path d="M 0 297.523321
L 510.348 297.523321
L 510.348 0
L 0 0
z
" style="fill: #ffffff"/>
</g>
<g id="axes_1">
<g id="patch_2">
<path d="M 45.588 253.3425
L 503.148 253.3425
L 503.148 20.4945
L 45.588 20.4945
z
" style="fill: #ffffff"/>
</g>
<g id="matplotlib.axis_1">
<g id="xtick_1">
<g id="text_1">
<!-- direct -->
<g style="fill: #262626" transform="translate(149.605476 278.333286) rotate(-25) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-64" d="M 2906 2969
L 2906 4863
L 3481 4863
L 3481 0
L 2906 0
L 2906 525
Q 2725 213 2448 61
Q 2172 -91 1784 -91
Q 1150 -91 751 415
Q 353 922 353 1747
Q 353 2572 751 3078
Q 1150 3584 1784 3584
Q 2172 3584 2448 3432
Q 2725 3281 2906 2969
z
M 947 1747
Q 947 1113 1208 752
Q 1469 391 1925 391
Q 2381 391 2643 752
Q 2906 1113 2906 1747
Q 2906 2381 2643 2742
Q 2381 3103 1925 3103
Q 1469 3103 1208 2742
Q 947 2381 947 1747
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-69" d="M 603 3500
L 1178 3500
L 1178 0
L 603 0
L 603 3500
z
M 603 4863
L 1178 4863
L 1178 4134
L 603 4134
L 603 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-72" d="M 2631 2963
Q 2534 3019 2420 3045
Q 2306 3072 2169 3072
Q 1681 3072 1420 2755
Q 1159 2438 1159 1844
L 1159 0
L 581 0
L 581 3500
L 1159 3500
L 1159 2956
Q 1341 3275 1631 3429
Q 1922 3584 2338 3584
Q 2397 3584 2469 3576
Q 2541 3569 2628 3553
L 2631 2963
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-65" d="M 3597 1894
L 3597 1613
L 953 1613
Q 991 1019 1311 708
Q 1631 397 2203 397
Q 2534 397 2845 478
Q 3156 559 3463 722
L 3463 178
Q 3153 47 2828 -22
Q 2503 -91 2169 -91
Q 1331 -91 842 396
Q 353 884 353 1716
Q 353 2575 817 3079
Q 1281 3584 2069 3584
Q 2775 3584 3186 3129
Q 3597 2675 3597 1894
z
M 3022 2063
Q 3016 2534 2758 2815
Q 2500 3097 2075 3097
Q 1594 3097 1305 2825
Q 1016 2553 972 2059
L 3022 2063
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-63" d="M 3122 3366
L 3122 2828
Q 2878 2963 2633 3030
Q 2388 3097 2138 3097
Q 1578 3097 1268 2742
Q 959 2388 959 1747
Q 959 1106 1268 751
Q 1578 397 2138 397
Q 2388 397 2633 464
Q 2878 531 3122 666
L 3122 134
Q 2881 22 2623 -34
Q 2366 -91 2075 -91
Q 1284 -91 818 406
Q 353 903 353 1747
Q 353 2603 823 3093
Q 1294 3584 2113 3584
Q 2378 3584 2631 3529
Q 2884 3475 3122 3366
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-74" d="M 1172 4494
L 1172 3500
L 2356 3500
L 2356 3053
L 1172 3053
L 1172 1153
Q 1172 725 1289 603
Q 1406 481 1766 481
L 2356 481
L 2356 0
L 1766 0
Q 1100 0 847 248
Q 594 497 594 1153
L 594 3053
L 172 3053
L 172 3500
L 594 3500
L 594 4494
L 1172 4494
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-64"/>
<use xlink:href="#DejaVuSans-69" x="63.476562"/>
<use xlink:href="#DejaVuSans-72" x="91.259766"/>
<use xlink:href="#DejaVuSans-65" x="130.123047"/>
<use xlink:href="#DejaVuSans-63" x="191.646484"/>
<use xlink:href="#DejaVuSans-74" x="246.626953"/>
</g>
</g>
</g>
<g id="xtick_2">
<g id="text_2">
<!-- bridge-new -->
<g style="fill: #262626" transform="translate(367.30762 288.664665) rotate(-25) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-62" d="M 3116 1747
Q 3116 2381 2855 2742
Q 2594 3103 2138 3103
Q 1681 3103 1420 2742
Q 1159 2381 1159 1747
Q 1159 1113 1420 752
Q 1681 391 2138 391
Q 2594 391 2855 752
Q 3116 1113 3116 1747
z
M 1159 2969
Q 1341 3281 1617 3432
Q 1894 3584 2278 3584
Q 2916 3584 3314 3078
Q 3713 2572 3713 1747
Q 3713 922 3314 415
Q 2916 -91 2278 -91
Q 1894 -91 1617 61
Q 1341 213 1159 525
L 1159 0
L 581 0
L 581 4863
L 1159 4863
L 1159 2969
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-67" d="M 2906 1791
Q 2906 2416 2648 2759
Q 2391 3103 1925 3103
Q 1463 3103 1205 2759
Q 947 2416 947 1791
Q 947 1169 1205 825
Q 1463 481 1925 481
Q 2391 481 2648 825
Q 2906 1169 2906 1791
z
M 3481 434
Q 3481 -459 3084 -895
Q 2688 -1331 1869 -1331
Q 1566 -1331 1297 -1286
Q 1028 -1241 775 -1147
L 775 -588
Q 1028 -725 1275 -790
Q 1522 -856 1778 -856
Q 2344 -856 2625 -561
Q 2906 -266 2906 331
L 2906 616
Q 2728 306 2450 153
Q 2172 0 1784 0
Q 1141 0 747 490
Q 353 981 353 1791
Q 353 2603 747 3093
Q 1141 3584 1784 3584
Q 2172 3584 2450 3431
Q 2728 3278 2906 2969
L 2906 3500
L 3481 3500
L 3481 434
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-2d" d="M 313 2009
L 1997 2009
L 1997 1497
L 313 1497
L 313 2009
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6e" d="M 3513 2113
L 3513 0
L 2938 0
L 2938 2094
Q 2938 2591 2744 2837
Q 2550 3084 2163 3084
Q 1697 3084 1428 2787
Q 1159 2491 1159 1978
L 1159 0
L 581 0
L 581 3500
L 1159 3500
L 1159 2956
Q 1366 3272 1645 3428
Q 1925 3584 2291 3584
Q 2894 3584 3203 3211
Q 3513 2838 3513 2113
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-77" d="M 269 3500
L 844 3500
L 1563 769
L 2278 3500
L 2956 3500
L 3675 769
L 4391 3500
L 4966 3500
L 4050 0
L 3372 0
L 2619 2869
L 1863 0
L 1184 0
L 269 3500
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-62"/>
<use xlink:href="#DejaVuSans-72" x="63.476562"/>
<use xlink:href="#DejaVuSans-69" x="104.589844"/>
<use xlink:href="#DejaVuSans-64" x="132.373047"/>
<use xlink:href="#DejaVuSans-67" x="195.849609"/>
<use xlink:href="#DejaVuSans-65" x="259.326172"/>
<use xlink:href="#DejaVuSans-2d" x="320.849609"/>
<use xlink:href="#DejaVuSans-6e" x="356.933594"/>
<use xlink:href="#DejaVuSans-65" x="420.3125"/>
<use xlink:href="#DejaVuSans-77" x="481.835938"/>
</g>
</g>
</g>
</g>
<g id="matplotlib.axis_2">
<g id="ytick_1">
<g id="line2d_1">
<path d="M 45.588 253.3425
L 503.148 253.3425
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_3">
<!-- 0 -->
<g style="fill: #262626" transform="translate(31.689 256.685812) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-30" d="M 2034 4250
Q 1547 4250 1301 3770
Q 1056 3291 1056 2328
Q 1056 1369 1301 889
Q 1547 409 2034 409
Q 2525 409 2770 889
Q 3016 1369 3016 2328
Q 3016 3291 2770 3770
Q 2525 4250 2034 4250
z
M 2034 4750
Q 2819 4750 3233 4129
Q 3647 3509 3647 2328
Q 3647 1150 3233 529
Q 2819 -91 2034 -91
Q 1250 -91 836 529
Q 422 1150 422 2328
Q 422 3509 836 4129
Q 1250 4750 2034 4750
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-30"/>
</g>
</g>
</g>
<g id="ytick_2">
<g id="line2d_2">
<path d="M 45.588 207.528104
L 503.148 207.528104
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_4">
<!-- 50 -->
<g style="fill: #262626" transform="translate(26.09 210.871417) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-35" d="M 691 4666
L 3169 4666
L 3169 4134
L 1269 4134
L 1269 2991
Q 1406 3038 1543 3061
Q 1681 3084 1819 3084
Q 2600 3084 3056 2656
Q 3513 2228 3513 1497
Q 3513 744 3044 326
Q 2575 -91 1722 -91
Q 1428 -91 1123 -41
Q 819 9 494 109
L 494 744
Q 775 591 1075 516
Q 1375 441 1709 441
Q 2250 441 2565 725
Q 2881 1009 2881 1497
Q 2881 1984 2565 2268
Q 2250 2553 1709 2553
Q 1456 2553 1204 2497
Q 953 2441 691 2322
L 691 4666
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-35"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
</g>
</g>
</g>
<g id="ytick_3">
<g id="line2d_3">
<path d="M 45.588 161.713709
L 503.148 161.713709
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_5">
<!-- 100 -->
<g style="fill: #262626" transform="translate(20.491 165.057021) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-31" d="M 794 531
L 1825 531
L 1825 4091
L 703 3866
L 703 4441
L 1819 4666
L 2450 4666
L 2450 531
L 3481 531
L 3481 0
L 794 0
L 794 531
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-31"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_4">
<g id="line2d_4">
<path d="M 45.588 115.899313
L 503.148 115.899313
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_6">
<!-- 150 -->
<g style="fill: #262626" transform="translate(20.491 119.242626) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-31"/>
<use xlink:href="#DejaVuSans-35" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_5">
<g id="line2d_5">
<path d="M 45.588 70.084918
L 503.148 70.084918
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_7">
<!-- 200 -->
<g style="fill: #262626" transform="translate(20.491 73.42823) scale(0.088 -0.088)">
<defs>
<path id="DejaVuSans-32" d="M 1228 531
L 3431 531
L 3431 0
L 469 0
L 469 531
Q 828 903 1448 1529
Q 2069 2156 2228 2338
Q 2531 2678 2651 2914
Q 2772 3150 2772 3378
Q 2772 3750 2511 3984
Q 2250 4219 1831 4219
Q 1534 4219 1204 4116
Q 875 4013 500 3803
L 500 4441
Q 881 4594 1212 4672
Q 1544 4750 1819 4750
Q 2544 4750 2975 4387
Q 3406 4025 3406 3419
Q 3406 3131 3298 2873
Q 3191 2616 2906 2266
Q 2828 2175 2409 1742
Q 1991 1309 1228 531
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-32"/>
<use xlink:href="#DejaVuSans-30" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="ytick_6">
<g id="line2d_6">
<path d="M 45.588 24.270522
L 503.148 24.270522
" clip-path="url(#p093f8268c7)" style="fill: none; stroke: #cccccc; stroke-opacity: 0.25; stroke-width: 0.8; stroke-linecap: round"/>
</g>
<g id="text_8">
<!-- 250 -->
<g style="fill: #262626" transform="translate(20.491 27.613835) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-32"/>
<use xlink:href="#DejaVuSans-35" x="63.623047"/>
<use xlink:href="#DejaVuSans-30" x="127.246094"/>
</g>
</g>
</g>
<g id="text_9">
<!-- Average latency [us] -->
<g style="fill: #262626" transform="translate(14.4945 186.6015) rotate(-90) scale(0.096 -0.096)">
<defs>
<path id="DejaVuSans-41" d="M 2188 4044
L 1331 1722
L 3047 1722
L 2188 4044
z
M 1831 4666
L 2547 4666
L 4325 0
L 3669 0
L 3244 1197
L 1141 1197
L 716 0
L 50 0
L 1831 4666
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-76" d="M 191 3500
L 800 3500
L 1894 563
L 2988 3500
L 3597 3500
L 2284 0
L 1503 0
L 191 3500
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-61" d="M 2194 1759
Q 1497 1759 1228 1600
Q 959 1441 959 1056
Q 959 750 1161 570
Q 1363 391 1709 391
Q 2188 391 2477 730
Q 2766 1069 2766 1631
L 2766 1759
L 2194 1759
z
M 3341 1997
L 3341 0
L 2766 0
L 2766 531
Q 2569 213 2275 61
Q 1981 -91 1556 -91
Q 1019 -91 701 211
Q 384 513 384 1019
Q 384 1609 779 1909
Q 1175 2209 1959 2209
L 2766 2209
L 2766 2266
Q 2766 2663 2505 2880
Q 2244 3097 1772 3097
Q 1472 3097 1187 3025
Q 903 2953 641 2809
L 641 3341
Q 956 3463 1253 3523
Q 1550 3584 1831 3584
Q 2591 3584 2966 3190
Q 3341 2797 3341 1997
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-20" transform="scale(0.015625)"/>
<path id="DejaVuSans-6c" d="M 603 4863
L 1178 4863
L 1178 0
L 603 0
L 603 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-79" d="M 2059 -325
Q 1816 -950 1584 -1140
Q 1353 -1331 966 -1331
L 506 -1331
L 506 -850
L 844 -850
Q 1081 -850 1212 -737
Q 1344 -625 1503 -206
L 1606 56
L 191 3500
L 800 3500
L 1894 763
L 2988 3500
L 3597 3500
L 2059 -325
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-5b" d="M 550 4863
L 1875 4863
L 1875 4416
L 1125 4416
L 1125 -397
L 1875 -397
L 1875 -844
L 550 -844
L 550 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-75" d="M 544 1381
L 544 3500
L 1119 3500
L 1119 1403
Q 1119 906 1312 657
Q 1506 409 1894 409
Q 2359 409 2629 706
Q 2900 1003 2900 1516
L 2900 3500
L 3475 3500
L 3475 0
L 2900 0
L 2900 538
Q 2691 219 2414 64
Q 2138 -91 1772 -91
Q 1169 -91 856 284
Q 544 659 544 1381
z
M 1991 3584
L 1991 3584
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-73" d="M 2834 3397
L 2834 2853
Q 2591 2978 2328 3040
Q 2066 3103 1784 3103
Q 1356 3103 1142 2972
Q 928 2841 928 2578
Q 928 2378 1081 2264
Q 1234 2150 1697 2047
L 1894 2003
Q 2506 1872 2764 1633
Q 3022 1394 3022 966
Q 3022 478 2636 193
Q 2250 -91 1575 -91
Q 1294 -91 989 -36
Q 684 19 347 128
L 347 722
Q 666 556 975 473
Q 1284 391 1588 391
Q 1994 391 2212 530
Q 2431 669 2431 922
Q 2431 1156 2273 1281
Q 2116 1406 1581 1522
L 1381 1569
Q 847 1681 609 1914
Q 372 2147 372 2553
Q 372 3047 722 3315
Q 1072 3584 1716 3584
Q 2034 3584 2315 3537
Q 2597 3491 2834 3397
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-5d" d="M 1947 4863
L 1947 -844
L 622 -844
L 622 -397
L 1369 -397
L 1369 4416
L 622 4416
L 622 4863
L 1947 4863
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-41"/>
<use xlink:href="#DejaVuSans-76" x="62.533203"/>
<use xlink:href="#DejaVuSans-65" x="121.712891"/>
<use xlink:href="#DejaVuSans-72" x="183.236328"/>
<use xlink:href="#DejaVuSans-61" x="224.349609"/>
<use xlink:href="#DejaVuSans-67" x="285.628906"/>
<use xlink:href="#DejaVuSans-65" x="349.105469"/>
<use xlink:href="#DejaVuSans-20" x="410.628906"/>
<use xlink:href="#DejaVuSans-6c" x="442.416016"/>
<use xlink:href="#DejaVuSans-61" x="470.199219"/>
<use xlink:href="#DejaVuSans-74" x="531.478516"/>
<use xlink:href="#DejaVuSans-65" x="570.6875"/>
<use xlink:href="#DejaVuSans-6e" x="632.210938"/>
<use xlink:href="#DejaVuSans-63" x="695.589844"/>
<use xlink:href="#DejaVuSans-79" x="750.570312"/>
<use xlink:href="#DejaVuSans-20" x="809.75"/>
<use xlink:href="#DejaVuSans-5b" x="841.537109"/>
<use xlink:href="#DejaVuSans-75" x="880.550781"/>
<use xlink:href="#DejaVuSans-73" x="943.929688"/>
<use xlink:href="#DejaVuSans-5d" x="996.029297"/>
</g>
</g>
</g>
<g id="patch_3">
<path d="M 68.466 253.3425
L 251.49 253.3425
L 251.49 233.838396
L 68.466 233.838396
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_4">
<path d="M 297.246 253.3425
L 480.27 253.3425
L 480.27 31.5825
L 297.246 31.5825
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_5">
<path d="M 159.978 253.3425
L 159.978 253.3425
L 159.978 253.3425
L 159.978 253.3425
z
" clip-path="url(#p093f8268c7)" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="patch_6">
<path d="M 45.588 253.3425
L 45.588 20.4945
" style="fill: none; stroke: #cccccc; stroke-linejoin: miter; stroke-linecap: square"/>
</g>
<g id="patch_7">
<path d="M 45.588 253.3425
L 503.148 253.3425
" style="fill: none; stroke: #cccccc; stroke-linejoin: miter; stroke-linecap: square"/>
</g>
<g id="text_10">
<!-- Sockperf Application Latency -->
<g style="fill: #262626" transform="translate(204.45675 14.4945) scale(0.096 -0.096)">
<defs>
<path id="DejaVuSans-53" d="M 3425 4513
L 3425 3897
Q 3066 4069 2747 4153
Q 2428 4238 2131 4238
Q 1616 4238 1336 4038
Q 1056 3838 1056 3469
Q 1056 3159 1242 3001
Q 1428 2844 1947 2747
L 2328 2669
Q 3034 2534 3370 2195
Q 3706 1856 3706 1288
Q 3706 609 3251 259
Q 2797 -91 1919 -91
Q 1588 -91 1214 -16
Q 841 59 441 206
L 441 856
Q 825 641 1194 531
Q 1563 422 1919 422
Q 2459 422 2753 634
Q 3047 847 3047 1241
Q 3047 1584 2836 1778
Q 2625 1972 2144 2069
L 1759 2144
Q 1053 2284 737 2584
Q 422 2884 422 3419
Q 422 4038 858 4394
Q 1294 4750 2059 4750
Q 2388 4750 2728 4690
Q 3069 4631 3425 4513
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6f" d="M 1959 3097
Q 1497 3097 1228 2736
Q 959 2375 959 1747
Q 959 1119 1226 758
Q 1494 397 1959 397
Q 2419 397 2687 759
Q 2956 1122 2956 1747
Q 2956 2369 2687 2733
Q 2419 3097 1959 3097
z
M 1959 3584
Q 2709 3584 3137 3096
Q 3566 2609 3566 1747
Q 3566 888 3137 398
Q 2709 -91 1959 -91
Q 1206 -91 779 398
Q 353 888 353 1747
Q 353 2609 779 3096
Q 1206 3584 1959 3584
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-6b" d="M 581 4863
L 1159 4863
L 1159 1991
L 2875 3500
L 3609 3500
L 1753 1863
L 3688 0
L 2938 0
L 1159 1709
L 1159 0
L 581 0
L 581 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-70" d="M 1159 525
L 1159 -1331
L 581 -1331
L 581 3500
L 1159 3500
L 1159 2969
Q 1341 3281 1617 3432
Q 1894 3584 2278 3584
Q 2916 3584 3314 3078
Q 3713 2572 3713 1747
Q 3713 922 3314 415
Q 2916 -91 2278 -91
Q 1894 -91 1617 61
Q 1341 213 1159 525
z
M 3116 1747
Q 3116 2381 2855 2742
Q 2594 3103 2138 3103
Q 1681 3103 1420 2742
Q 1159 2381 1159 1747
Q 1159 1113 1420 752
Q 1681 391 2138 391
Q 2594 391 2855 752
Q 3116 1113 3116 1747
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-66" d="M 2375 4863
L 2375 4384
L 1825 4384
Q 1516 4384 1395 4259
Q 1275 4134 1275 3809
L 1275 3500
L 2222 3500
L 2222 3053
L 1275 3053
L 1275 0
L 697 0
L 697 3053
L 147 3053
L 147 3500
L 697 3500
L 697 3744
Q 697 4328 969 4595
Q 1241 4863 1831 4863
L 2375 4863
z
" transform="scale(0.015625)"/>
<path id="DejaVuSans-4c" d="M 628 4666
L 1259 4666
L 1259 531
L 3531 531
L 3531 0
L 628 0
L 628 4666
z
" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#DejaVuSans-53"/>
<use xlink:href="#DejaVuSans-6f" x="63.476562"/>
<use xlink:href="#DejaVuSans-63" x="124.658203"/>
<use xlink:href="#DejaVuSans-6b" x="179.638672"/>
<use xlink:href="#DejaVuSans-70" x="237.548828"/>
<use xlink:href="#DejaVuSans-65" x="301.025391"/>
<use xlink:href="#DejaVuSans-72" x="362.548828"/>
<use xlink:href="#DejaVuSans-66" x="403.662109"/>
<use xlink:href="#DejaVuSans-20" x="438.867188"/>
<use xlink:href="#DejaVuSans-41" x="470.654297"/>
<use xlink:href="#DejaVuSans-70" x="539.0625"/>
<use xlink:href="#DejaVuSans-70" x="602.539062"/>
<use xlink:href="#DejaVuSans-6c" x="666.015625"/>
<use xlink:href="#DejaVuSans-69" x="693.798828"/>
<use xlink:href="#DejaVuSans-63" x="721.582031"/>
<use xlink:href="#DejaVuSans-61" x="776.5625"/>
<use xlink:href="#DejaVuSans-74" x="837.841797"/>
<use xlink:href="#DejaVuSans-69" x="877.050781"/>
<use xlink:href="#DejaVuSans-6f" x="904.833984"/>
<use xlink:href="#DejaVuSans-6e" x="966.015625"/>
<use xlink:href="#DejaVuSans-20" x="1029.394531"/>
<use xlink:href="#DejaVuSans-4c" x="1061.181641"/>
<use xlink:href="#DejaVuSans-61" x="1116.894531"/>
<use xlink:href="#DejaVuSans-74" x="1178.173828"/>
<use xlink:href="#DejaVuSans-65" x="1217.382812"/>
<use xlink:href="#DejaVuSans-6e" x="1278.90625"/>
<use xlink:href="#DejaVuSans-63" x="1342.285156"/>
<use xlink:href="#DejaVuSans-79" x="1397.265625"/>
</g>
</g>
<g id="legend_1">
<g id="patch_8">
<path d="M 51.748 54.14225
L 94.424 54.14225
Q 96.184 54.14225 96.184 52.38225
L 96.184 26.6545
Q 96.184 24.8945 94.424 24.8945
L 51.748 24.8945
Q 49.988 24.8945 49.988 26.6545
L 49.988 52.38225
Q 49.988 54.14225 51.748 54.14225
z
" style="fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="text_11">
<!-- protocol -->
<g style="fill: #262626" transform="translate(53.508 35.709) scale(0.096 -0.096)">
<use xlink:href="#DejaVuSans-70"/>
<use xlink:href="#DejaVuSans-72" x="63.476562"/>
<use xlink:href="#DejaVuSans-6f" x="102.339844"/>
<use xlink:href="#DejaVuSans-74" x="163.521484"/>
<use xlink:href="#DejaVuSans-6f" x="202.730469"/>
<use xlink:href="#DejaVuSans-63" x="263.912109"/>
<use xlink:href="#DejaVuSans-6f" x="318.892578"/>
<use xlink:href="#DejaVuSans-6c" x="380.074219"/>
</g>
</g>
<g id="patch_9">
<path d="M 53.828438 48.792125
L 71.428438 48.792125
L 71.428438 42.632125
L 53.828438 42.632125
z
" style="fill: #2f837f; stroke: #ffffff; stroke-width: 0.8; stroke-linejoin: miter"/>
</g>
<g id="text_12">
<!-- tcp -->
<g style="fill: #262626" transform="translate(78.468438 48.792125) scale(0.088 -0.088)">
<use xlink:href="#DejaVuSans-74"/>
<use xlink:href="#DejaVuSans-63" x="39.208984"/>
<use xlink:href="#DejaVuSans-70" x="94.189453"/>
</g>
</g>
</g>
</g>
</g>
<defs>
<clipPath id="p093f8268c7">
<rect x="45.588" y="20.4945" width="457.56" height="232.848"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,136 @@
# Bachelor Thesis Style Baseline
Source: Marcus Jan Almert, "An Investigation of the Security of Smart Doorbells", bachelor's thesis, 2022.
Use this note as the baseline when drafting or revising the master's thesis. The goal is not to copy sentences from the bachelor's thesis, but to preserve its academic voice, explanatory rhythm, and technical clarity.
## Overall Voice
- Formal, technical, and objective.
- Prefer an impersonal academic perspective: "this thesis", "the present thesis", "the analysis", "the developed system".
- Avoid first-person singular. First-person plural is rare and should only be used when the surrounding section genuinely calls for it.
- Use present tense for general concepts, protocols, system properties, and chapter purpose.
- Use past tense for performed experiments, observations, implementations, and measurements.
- Use cautious language when evidence is partial: "could", "may", "potentially", "was not proven", "was observed".
## Chapter and Section Openings
The bachelor's thesis often starts chapters with a short roadmap:
- State what the chapter or section explains.
- Then list the sequence of topics with "First", "Next", "Then", "Lastly", or "Thereafter".
- Keep the opening practical and close to the technical purpose of the chapter.
Preferred pattern:
> The following chapter explains essential concepts used in this thesis. First, ..., Next, ..., Lastly, ...
For the master's thesis, prefer this direct roadmap style over broader phrases such as "foundational concepts underlying the research".
## Paragraph Rhythm
- Begin paragraphs with a clear topic sentence.
- Follow with mechanism, implementation detail, or evidence.
- End with consequence, relevance, or transition to the next point.
- Background paragraphs are medium length and explanatory.
- Analysis and evaluation paragraphs are more compact and evidence-driven.
- Use lists only when they make capabilities, attack effects, requirements, or result categories easier to scan.
## Common Transitions
Useful connective phrases matching the bachelor's thesis style:
- "For this purpose, ..."
- "Using this setup, ..."
- "As described in Section ..."
- "In the following section, ..."
- "Furthermore, ..."
- "Additionally, ..."
- "However, ..."
- "In contrast, ..."
- "Consequently, ..."
- "Therefore, ..."
- "Lastly, ..."
- "This allows ..."
- "This is evidenced by ..."
- "An example of ... is shown in ..."
- "Similar to ..."
Use these naturally; do not over-stack them in every paragraph.
## Technical Explanation Style
- Define a concept before relying on it later.
- Introduce acronyms on first use, then use the acronym consistently.
- In LaTeX, introduce acronyms with the `acronym` package using `\ac{...}` or `\acp{...}`. Do not write acronym short forms manually in running text when an acronym entry exists.
- Write tool names, command names, kernel symbols, hook names, protocol constants, and code-level identifiers in `\texttt{...}`. This includes names such as `\texttt{nftables}`, `\texttt{tc}`, `\texttt{sk_buff}`, and `\texttt{AF_PACKET}`. Acronym short forms such as `NFQUEUE` should still be produced with `\ac{NFQUEUE}`, because the thesis settings render acronym short forms in typewriter font automatically.
- Prefer exact technical nouns over stylistic synonym changes.
- When explaining protocols or implementation paths, move from general role to concrete fields, functions, tools, or messages.
- Use listings, tables, and figures to make protocol messages, APIs, measurements, and system paths concrete.
- Mention tool names and versions when they matter for reproducibility.
## Evidence and Claim Strength
- Tie claims to observations, measurements, listings, figures, tables, or cited sources.
- Avoid unsupported adjectives such as "robust", "novel", "seamless", or "powerful" unless the section proves them.
- Distinguish clearly between demonstrated findings and plausible implications.
- For security-related statements, state the adversary capability or system assumption before the impact.
## Citation Style
- Use numeric citation style through LaTeX references.
- Place citations near the factual claim they support.
- Standards, protocol details, and external tool behavior should be cited.
- Implementation descriptions and own measurements usually do not need external citations, but should reference the relevant listing, figure, table, or section.
## Analysis Section Pattern
The bachelor's thesis uses a repeatable analysis rhythm:
1. Introduce the investigated object, version, setup, or scope.
2. Describe the observed behavior.
3. Explain the technical mechanism.
4. Demonstrate the issue or result with concrete evidence.
5. State the impact or relevance.
6. If appropriate, compare to earlier sections.
For the master's thesis, this maps well to platform features and evaluation sections:
1. Introduce the component or measurement scenario.
2. Describe where it sits in the packet path or application architecture.
3. Explain how it was implemented or measured.
4. Show the relevant data, interface, figure, or listing.
5. State what this means for correctness, timing, usability, or security analysis.
## Summary and Future Work Pattern
The conclusion style is concise and retrospective:
- Restate the thesis goal.
- Summarize the method.
- Summarize the main findings or contributions.
- Name limitations or unresolved questions.
- Present future work as concrete continuation paths.
Prefer "A future work possibility would be ..." or "Another future work possibility would be ..." when matching the older style, but use it sparingly to avoid repetition.
## Phrases to Prefer
- "The goal of this thesis was ..."
- "To achieve this, ..."
- "The analysis considered ..."
- "It was shown that ..."
- "It was discovered that ..."
- "The following section focuses on ..."
- "For the present thesis, ..."
- "This is particularly important because ..."
- "In preparation for ..."
- "The captured data was then examined for ..."
## Phrases to Avoid or Reduce
- Marketing-style claims: "seamless", "cutting-edge", "state-of-the-art" unless cited and justified.
- Overly abstract openings: "This chapter establishes the theoretical foundation for ..."
- Personal narration: "I implemented", "we wanted to".
- Unqualified certainty for uncertain findings: use cautious modality where appropriate.
- Long rhetorical motivation before the technical problem is clear.

549
tools/plot_benchmark_results.py Executable file
View File

@@ -0,0 +1,549 @@
#!/usr/bin/env python3
"""Create thesis-ready plots from network_timing_benchmark.py results.
The script reads one or more benchmark result directories containing
`summary.json`, extracts the most relevant metrics, writes CSV files for
checking, and exports publication-friendly figures.
"""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
from typing import Any
def import_plotting_stack() -> tuple[Any, Any, Any]:
try:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
except ModuleNotFoundError as exc:
missing = exc.name or "plotting dependency"
print(
f"Missing Python package: {missing}\n\n"
"Install the plotting dependencies with:\n"
" python3 -m pip install pandas matplotlib seaborn\n\n"
"On Ubuntu with apt packages, this usually also works:\n"
" sudo apt install python3-pandas python3-matplotlib python3-seaborn",
file=sys.stderr,
)
raise SystemExit(2) from exc
return pd, plt, sns
def safe_name(value: str) -> str:
return re.sub(r"[^A-Za-z0-9_.-]+", "_", value).strip("_") or "plot"
def find_summary_files(input_paths: list[Path]) -> list[Path]:
files: list[Path] = []
for path in input_paths:
if path.is_file() and path.name == "summary.json":
files.append(path)
elif path.is_dir():
files.extend(path.rglob("summary.json"))
return sorted(set(files))
def infer_setup_name(summary_path: Path, payload: dict[str, Any]) -> str:
label = str(payload.get("label") or "").strip()
if label:
return label
folder = summary_path.parent.name
match = re.match(r"^\d{8}-\d{6}-(?P<label>.+)$", folder)
if match:
return match.group("label")
return folder
def setup_sort_key(setup: str) -> tuple[int, str]:
normalized = setup.lower()
order = {
"direct": 0,
"baseline": 0,
"bridge": 1,
"bridge-only": 1,
"bridge-new": 1,
"af_packet": 2,
"af-packet": 2,
"tc_ebpf": 3,
"tc-ebpf": 3,
"ebpf": 3,
"nfqueue": 4,
"nftables": 5,
}
for key, rank in order.items():
if key in normalized:
return rank, normalized
return 99, normalized
def add_metric(
rows: list[dict[str, Any]],
*,
setup: str,
source: Path,
category: str,
metric: str,
value: Any,
unit: str,
direction: str | None = None,
payload_size_bytes: int | None = None,
protocol: str | None = None,
test: str | None = None,
) -> None:
if value is None:
return
try:
number = float(value)
except (TypeError, ValueError):
return
rows.append(
{
"setup": setup,
"category": category,
"metric": metric,
"value": number,
"unit": unit,
"direction": direction,
"payload_size_bytes": payload_size_bytes,
"protocol": protocol,
"test": test,
"source": str(source),
}
)
def extract_summary(summary_path: Path) -> list[dict[str, Any]]:
payload = json.loads(summary_path.read_text(encoding="utf-8"))
setup = infer_setup_name(summary_path, payload)
rows: list[dict[str, Any]] = []
for result in payload.get("tests", []):
if result.get("skipped"):
continue
result_type = result.get("type")
if result_type == "ping":
size = result.get("payload_size_bytes")
try:
size = int(size) if size is not None else None
except (TypeError, ValueError):
size = None
rtt = result.get("rtt_ms", {}) or {}
jitter = result.get("jitter", {}) or {}
for metric in ("mean", "median", "p95", "p99", "min", "max", "stdev", "mad", "iqr"):
add_metric(
rows,
setup=setup,
source=summary_path,
category="ping",
metric=f"rtt_{metric}",
value=rtt.get(metric),
unit="ms",
payload_size_bytes=size,
)
add_metric(
rows,
setup=setup,
source=summary_path,
category="ping",
metric="jitter_mean_abs_delta",
value=jitter.get("mean_abs_delta_ms"),
unit="ms",
payload_size_bytes=size,
)
add_metric(
rows,
setup=setup,
source=summary_path,
category="ping",
metric="loss",
value=result.get("loss_percent"),
unit="percent",
payload_size_bytes=size,
)
elif result_type in {"iperf_tcp", "iperf_udp"}:
category = result_type
direction = result.get("direction", "forward")
add_metric(
rows,
setup=setup,
source=summary_path,
category=category,
metric="throughput",
value=result.get("mbit_per_second"),
unit="Mbit/s",
direction=direction,
)
if result_type == "iperf_tcp":
add_metric(
rows,
setup=setup,
source=summary_path,
category=category,
metric="retransmits",
value=result.get("retransmits"),
unit="count",
direction=direction,
)
else:
add_metric(
rows,
setup=setup,
source=summary_path,
category=category,
metric="jitter",
value=result.get("jitter_ms"),
unit="ms",
direction=direction,
)
add_metric(
rows,
setup=setup,
source=summary_path,
category=category,
metric="loss",
value=result.get("lost_percent"),
unit="percent",
direction=direction,
)
elif result_type == "sockperf":
protocol = result.get("protocol")
extracted = result.get("extracted", {}) or {}
for metric, unit in (
("avg_latency_usec", "us"),
("min_latency_usec", "us"),
("max_latency_usec", "us"),
):
add_metric(
rows,
setup=setup,
source=summary_path,
category="sockperf",
metric=metric,
value=extracted.get(metric),
unit=unit,
protocol=protocol,
)
elif result_type == "arping":
rtt = result.get("rtt_ms", {}) or {}
for metric in ("mean", "median", "p95", "p99"):
add_metric(
rows,
setup=setup,
source=summary_path,
category="arping",
metric=f"rtt_{metric}",
value=rtt.get(metric),
unit="ms",
)
elif result_type == "flent":
add_metric(
rows,
setup=setup,
source=summary_path,
category="flent",
metric="data_file_exists",
value=1 if result.get("data_file_exists") else 0,
unit="bool",
test=result.get("test"),
)
return rows
def save_figure(fig: Any, output_dir: Path, name: str, formats: list[str], dpi: int) -> None:
for fmt in formats:
path = output_dir / f"{name}.{fmt}"
fig.savefig(path, dpi=dpi, bbox_inches="tight")
print(f"wrote {path}")
def maybe_warn_empty(df: Any, name: str) -> bool:
if df.empty:
print(f"skipping {name}: no data")
return True
return False
def plot_ping_percentiles(pd: Any, plt: Any, sns: Any, metrics: Any, output_dir: Path, formats: list[str], dpi: int) -> None:
df = metrics[
(metrics["category"] == "ping")
& (metrics["metric"].isin(["rtt_median", "rtt_p95", "rtt_p99"]))
].copy()
if maybe_warn_empty(df, "ping percentiles"):
return
df["payload"] = df["payload_size_bytes"].astype("Int64").astype(str) + " B"
df["percentile"] = df["metric"].map(
{
"rtt_median": "median",
"rtt_p95": "p95",
"rtt_p99": "p99",
}
)
grid = sns.catplot(
data=df,
kind="bar",
x="setup",
y="value",
hue="percentile",
col="payload",
col_wrap=3,
errorbar=None,
height=3.2,
aspect=1.2,
palette="crest",
order=sorted(df["setup"].unique(), key=setup_sort_key),
)
grid.set_axis_labels("", "RTT [ms]")
grid.set_titles("{col_name}")
for ax in grid.axes.flat:
ax.tick_params(axis="x", rotation=25)
ax.grid(axis="y", alpha=0.25)
grid.figure.suptitle("Ping RTT Percentiles", y=1.04)
save_figure(grid.figure, output_dir, "ping_rtt_percentiles", formats, dpi)
plt.close(grid.figure)
def plot_added_delay(pd: Any, plt: Any, sns: Any, metrics: Any, output_dir: Path, formats: list[str], dpi: int, baseline: str) -> None:
df = metrics[
(metrics["category"] == "ping")
& (metrics["metric"] == "rtt_median")
].copy()
if maybe_warn_empty(df, "added one-way delay"):
return
baseline_candidates = df[df["setup"].str.lower() == baseline.lower()]
if baseline_candidates.empty:
baseline_candidates = df[df["setup"].str.lower().str.contains(baseline.lower(), regex=False)]
if baseline_candidates.empty:
print(f"skipping added delay: baseline setup '{baseline}' not found")
return
baseline_by_payload = baseline_candidates.groupby("payload_size_bytes")["value"].mean()
df["baseline_rtt_ms"] = df["payload_size_bytes"].map(baseline_by_payload)
df = df.dropna(subset=["baseline_rtt_ms"])
df["added_one_way_ms"] = (df["value"] - df["baseline_rtt_ms"]) / 2.0
df = df[df["setup"].str.lower() != baseline.lower()]
if maybe_warn_empty(df, "added one-way delay"):
return
df["payload"] = df["payload_size_bytes"].astype("Int64").astype(str) + " B"
fig, ax = plt.subplots(figsize=(8.2, 4.4))
sns.barplot(
data=df,
x="setup",
y="added_one_way_ms",
hue="payload",
errorbar=None,
palette="flare",
order=sorted(df["setup"].unique(), key=setup_sort_key),
ax=ax,
)
ax.axhline(0, color="0.2", linewidth=0.8)
ax.set_xlabel("")
ax.set_ylabel("Added one-way delay [ms]")
ax.set_title(f"Estimated Added One-Way Delay vs {baseline}")
ax.tick_params(axis="x", rotation=25)
ax.grid(axis="y", alpha=0.25)
save_figure(fig, output_dir, "added_one_way_delay", formats, dpi)
plt.close(fig)
def plot_throughput(pd: Any, plt: Any, sns: Any, metrics: Any, output_dir: Path, formats: list[str], dpi: int) -> None:
df = metrics[
(metrics["category"].isin(["iperf_tcp", "iperf_udp"]))
& (metrics["metric"] == "throughput")
].copy()
if maybe_warn_empty(df, "throughput"):
return
df["traffic"] = df["category"].map({"iperf_tcp": "TCP", "iperf_udp": "UDP"}) + " " + df["direction"].fillna("")
fig, ax = plt.subplots(figsize=(9.2, 4.8))
sns.barplot(
data=df,
x="setup",
y="value",
hue="traffic",
errorbar=None,
palette="mako",
order=sorted(df["setup"].unique(), key=setup_sort_key),
ax=ax,
)
ax.set_xlabel("")
ax.set_ylabel("Throughput [Mbit/s]")
ax.set_title("Throughput by Setup")
ax.tick_params(axis="x", rotation=25)
ax.grid(axis="y", alpha=0.25)
save_figure(fig, output_dir, "throughput", formats, dpi)
plt.close(fig)
def plot_udp_quality(pd: Any, plt: Any, sns: Any, metrics: Any, output_dir: Path, formats: list[str], dpi: int) -> None:
df = metrics[
(metrics["category"] == "iperf_udp")
& (metrics["metric"].isin(["jitter", "loss"]))
].copy()
if maybe_warn_empty(df, "UDP quality"):
return
df["direction"] = df["direction"].fillna("forward")
df["metric_label"] = df["metric"].map({"jitter": "Jitter [ms]", "loss": "Loss [%]"})
grid = sns.catplot(
data=df,
kind="bar",
x="setup",
y="value",
hue="direction",
col="metric_label",
sharey=False,
errorbar=None,
height=3.8,
aspect=1.25,
palette="rocket",
order=sorted(df["setup"].unique(), key=setup_sort_key),
)
grid.set_axis_labels("", "")
grid.set_titles("{col_name}")
for ax in grid.axes.flat:
ax.tick_params(axis="x", rotation=25)
ax.grid(axis="y", alpha=0.25)
grid.figure.suptitle("UDP Jitter and Loss", y=1.04)
save_figure(grid.figure, output_dir, "udp_jitter_loss", formats, dpi)
plt.close(grid.figure)
def plot_sockperf(pd: Any, plt: Any, sns: Any, metrics: Any, output_dir: Path, formats: list[str], dpi: int) -> None:
df = metrics[
(metrics["category"] == "sockperf")
& (metrics["metric"] == "avg_latency_usec")
].copy()
if maybe_warn_empty(df, "sockperf"):
return
fig, ax = plt.subplots(figsize=(8.2, 4.2))
sns.barplot(
data=df,
x="setup",
y="value",
hue="protocol",
errorbar=None,
palette="viridis",
order=sorted(df["setup"].unique(), key=setup_sort_key),
ax=ax,
)
ax.set_xlabel("")
ax.set_ylabel("Average latency [us]")
ax.set_title("Sockperf Application Latency")
ax.tick_params(axis="x", rotation=25)
ax.grid(axis="y", alpha=0.25)
save_figure(fig, output_dir, "sockperf_latency", formats, dpi)
plt.close(fig)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Plot benchmark summaries for thesis figures.")
parser.add_argument(
"inputs",
nargs="*",
type=Path,
default=[Path("measurments"), Path("measurements")],
help="Result directories or summary.json files. Defaults to ./measurments and ./measurements.",
)
parser.add_argument(
"--out-dir",
type=Path,
default=Path("documentation/thesis/figures/benchmark"),
help="Directory for generated plots and CSV files.",
)
parser.add_argument(
"--baseline",
default="direct",
help="Setup name used as baseline for added-delay plots.",
)
parser.add_argument(
"--formats",
default="pdf,svg,png",
help="Comma-separated output formats, e.g. pdf,svg,png.",
)
parser.add_argument("--dpi", type=int, default=220, help="DPI for raster outputs such as PNG.")
return parser
def main() -> int:
parser = build_parser()
args = parser.parse_args()
pd, plt, sns = import_plotting_stack()
summary_files = find_summary_files(args.inputs)
if not summary_files:
parser.error("no summary.json files found in the provided inputs")
formats = [item.strip().lower() for item in args.formats.split(",") if item.strip()]
if not formats:
parser.error("--formats must contain at least one format")
args.out_dir.mkdir(parents=True, exist_ok=True)
sns.set_theme(
context="paper",
style="whitegrid",
font_scale=1.0,
rc={
"figure.dpi": args.dpi,
"savefig.dpi": args.dpi,
"axes.spines.right": False,
"axes.spines.top": False,
},
)
rows: list[dict[str, Any]] = []
for path in summary_files:
rows.extend(extract_summary(path))
metrics = pd.DataFrame(rows)
if metrics.empty:
parser.error("summary files were found, but no plottable metrics were extracted")
metrics["setup"] = metrics["setup"].astype(str)
metrics = metrics.sort_values(
by=["setup", "category", "metric", "payload_size_bytes", "direction", "protocol"],
key=lambda col: col.map(lambda value: setup_sort_key(str(value)) if col.name == "setup" else value),
)
metrics_csv = args.out_dir / "benchmark_metrics.csv"
metrics.to_csv(metrics_csv, index=False)
print(f"wrote {metrics_csv}")
summary_csv = args.out_dir / "benchmark_metric_summary.csv"
grouped = (
metrics.groupby(["setup", "category", "metric", "unit", "direction", "payload_size_bytes", "protocol"], dropna=False)[
"value"
]
.agg(["count", "mean", "median", "min", "max", "std"])
.reset_index()
)
grouped.to_csv(summary_csv, index=False)
print(f"wrote {summary_csv}")
plot_ping_percentiles(pd, plt, sns, metrics, args.out_dir, formats, args.dpi)
plot_added_delay(pd, plt, sns, metrics, args.out_dir, formats, args.dpi, args.baseline)
plot_throughput(pd, plt, sns, metrics, args.out_dir, formats, args.dpi)
plot_udp_quality(pd, plt, sns, metrics, args.out_dir, formats, args.dpi)
plot_sockperf(pd, plt, sns, metrics, args.out_dir, formats, args.dpi)
print(f"Processed {len(summary_files)} summary files.")
return 0
if __name__ == "__main__":
raise SystemExit(main())