Improve the way you make use of FreeBSD in your company.
Find out more about what makes us the most reliable FreeBSD development organization, and take the next step in engaging with us for your next FreeBSD project.
FreeBSD Support FreeBSD DevelopmentAdditional Articles
Here are more interesting articles on FreeBSD that you may find useful:
- Network Offload and Socket Splicing (SO_SPLICE) in FreeBSD
- Core Infrastructure: Why You Need to Control Your NTP
- Why FreeBSD is the Right Choice for Embedded Devices
- Controlling Your Core Infrastructure: DNS
- Winter 2024 Roundup: Storage and Network Diagnostics
The FreeBSD operating system has long been recognized for its capabilities, serving as the foundation for various high-performance network infrastructures. A pivotal component of FreeBSD’s networking prowess is its modular framework known as Netgraph. To better understand the significance of Netgraph, we’ll want to compare it to Linux’s Netfilter and see how it behaves in real-world scenarios, especially in environments such as Juniper’s JunOS and Cisco’s IOS XR.
Netgraph: An Overview
Introduced in FreeBSD 3.4 (1999), Netgraph is a graph-based kernel networking subsystem that provides a flexible framework for implementing new networking protocols. It allows developers to create complex networking topologies by connecting various processing modules, known as nodes, in a graph structure. This modularity facilitates rapid development and deployment of new networking features, making it a powerful tool for developers.

At its core, FreeBSD Netgraph operates on the principle of nodes and hooks. Each node represents a specific networking function or protocol, and hooks are the connections between these nodes. This design allows for the dynamic assembly of complex networking configurations by linking various nodes together. For example, you can construct a network path where packets pass through a series of nodes, each handling distinct operations such as encryption, compression, or protocol translation.
Control messages facilitate communication between nodes, enabling configuration and management of the network graph. This messaging system allows for real-time adjustments to the network topology, providing administrators with granular control over data flow and processing.
A Quick Lesson in Mathematics and Graph Theory
Understanding Netgraph requires an examination of its mathematical underpinnings, particularly in graph theory, queuing theory, and discrete mathematics. If you’re anything like me, you might have skipped a lot of your graph theory fundamentals for something more fun—like basics of microchips or the art of skipping class. But let’s try to keep it clean here.
Netgraph in FreeBSD models networking as a directed graph G = (V, E) , where nodes (V) represent network components, and edges (E) are data flow connections. Each node has finite-degree connectivity, forming a dynamic adjacency graph that allows real-time modifications.
Packet traversal follows graph traversal algorithms such as Depth-First Search (DFS) for dynamic routing, and Minimum Spanning Tree (MST) algorithms to prevent loops. The adjacency matrix Aij dynamically updates, ensuring the network remains connected:
Netgraph nodes process packets using queueing theory, with each node acting as an M/M/1 queue, where:
where:
- λ (\lambda)is the packet arrival rate
- μ (\mu)is the service rate
Maintaining μ (\mu) > λ (\lambda) prevents congestion.
Compared to Linux’s Netfilter, which applies static rules using hook-based filtering, Netgraph enables real-time graph restructuring, making it more efficient for complex routing scenarios. Dijkstra’s algorithm is often used for load-balancing paths dynamically.
This graph-based, dynamic architecture gives Netgraph an advantage in modular and high-performance networking applications, particularly in carrier-grade systems like Juniper’s Junos OS (we’ll get back to this in a minute).
Eh, How About Netfilter?
While Netgraph offers a flexible, graph-based approach to networking, Linux employs a different framework known as Netfilter. Netfilter provides a set of hooks within the Linux kernel’s networking stack, allowing modules to register callback functions that can inspect and manipulate packets at various stages of processing. This framework is leveraged by tools like iptables and nftables, which are used to define firewall rules and perform packet filtering.
The primary distinction between Netgraph and Netfilter lies in their architecture. Netgraph’s node-and-hook model offers a more granular and customizable approach, enabling the construction of intricate processing pipelines within the kernel. In contrast, Netfilter’s hook-based system is designed primarily for packet filtering and NAT, providing a more straightforward mechanism for intercepting and modifying packets as they traverse the networking stack.
And How Can I Relate to This Information? Well, JunOS and IOS XR
If you’ve worked in networking long enough, you’re bound to have encountered one of these two, if not both. Where Netgraph becomes obvious is in how it has influenced the design of several commercial network operating systems. Juniper Networks’ Junos OS is built upon the FreeBSD kernel and leverages its networking capabilities to deliver high-performance routing and switching solutions.
Junos OS uses a modular architecture that separates the control and forwarding planes, enhancing system stability and performance. Similarly, Cisco’s IOS XR employs a microkernel architecture that separates the control and data planes, akin to the design principles employed by Juniper. This separation enhances system stability and performance, allowing for more efficient processing of network traffic.
FreeBSD Netgraph: The Good, the Bad and the Use Cases
Netgraph works particularly well in very specific scenarios, namely:
- Flexibility: The ability to dynamically assemble and reconfigure networking components allows for rapid adaptation to changing requirements.
- Modularity: Developers can create reusable nodes that perform specific functions, promoting code reuse and simplifying maintenance.
- Performance: Operating within the kernel space enables high-speed processing of network packets, reducing latency and overhead.
- Extensibility: New protocols and features can be integrated seamlessly by developing additional nodes and connecting them to the existing graph.
But, as with all good things, there’s a few challenges too:
- Complexity: The graph-based architecture can become intricate, making it challenging to design and manage large-scale configurations.
- Debugging: Troubleshooting issues within a complex network graph may require specialized tools and expertise.
- Documentation: Comprehensive documentation and community support are essential to effectively leverage Netgraph’s capabilities.
Beyond a list of what it does, let’s bring it back to real life and talk about two specific scenarios where you might see Netgraph in action:
Adventures with VPNs
Picture a VPN. Traditionally, all packets are encapsulated and encrypted, then tunneled through a single gateway before reaching their destination. This introduces latency and congestion, as every request—whether it’s a video call or a background Windows update—competes for the same encrypted tunnel.
With Netgraph, traffic is dynamically categorized at the kernel level using graph-based packet flow processing. A node handles IP classification, determining whether a packet is destined for an internal resource or the open internet. If the destination is a corporate server, Netgraph directs the packet into an encryption node, encapsulating it before forwarding. If it’s general traffic—like streaming or software updates—Netgraph reroutes it through the standard network stack, bypassing VPN encryption altogether.
This reduces unnecessary encapsulation overhead, lowers processing time per packet, and prevents VPN tunnel congestion. Unlike static split-tunneling, which relies on predefined IP lists, Netgraph can dynamically reconfigure traffic flows in real time based on current network conditions.
Traditional Gateway-Based Firewalling (We’ll Ignore Your Any-Any Rule!)
Traditional firewalls rely on rule-based packet filtering, where traffic is checked against predefined access control lists (ACLs). This works, but every rule addition means a complete table refresh, and deep packet inspection requires high CPU overhead.
With Netgraph, firewall rules are implemented using graph nodes that dynamically process packets inline at the kernel level. Instead of running a linear check against a static ruleset, Netgraph organizes traffic into processing chains, where each node applies a function—NAT, filtering, or bandwidth shaping—before passing it forward.
For example, a classification node inspects L3/L4 headers in real time, tagging packets for filtering. A rate-limiting node ensures that non-essential traffic (like streaming) gets throttled, while work-critical traffic moves through priority queues. If an admin modifies a rule, Netgraph updates the node connections dynamically—without requiring a firewall restart or disrupting established flows.
This means instant rule enforcement, lower CPU load, and no need to flush entire rulesets on policy changes—unlike traditional firewall implementations.
Closing Thoughts
FreeBSD Netgraph represents a powerful and flexible framework within FreeBSD’s networking stack, offering a unique approach to constructing and managing network functionalities. Its influence is evident in the design of advanced network operating systems like Junos OS and IOS XR. By understanding the architecture and capabilities of Netgraph, network engineers and developers can harness its potential to build sophisticated and efficient networking solutions.
If you’d like to get hands-on with Netgraph, check out our article, Using Netgraph for FreeBSD’s Bhyve Networking.