Clarifying Kernel-Space vs User-Space Networking in macOS: Impact on Applications with Multiple Network Connections

Hi,

I have been reviewing some previous discussions around networking in macOS, and I’d like to clarify my understanding of the differences between the kernel-space network stack and user-space network stack and validate this understanding based on the information shared in earlier threads.

I’m also curious about how these differences impact macOS applications, particularly those requiring maintaining many simultaneous network connections.

Understanding Kernel-Space vs User-Space Network Stack

Kernel-Space Network Stack (BSD Sockets): The kernel-space networking stack refers to the traditional networking layer that runs in the kernel and handles network communication via BSD sockets. This stack is lower-level and interacts directly with the operating system's networking drivers and hardware. All network connections managed through this stack require a socket (essentially a file descriptor) to be opened, which places limits on the number of file descriptors that can be used (for example, the default 64K limit for sockets). The kernel network stack is traditionally used on macOS (and other UNIX-based systems) for networking tasks, such as when you use system APIs like BSD sockets.

User-Space Network Stack (Network Framework): The user-space network stack in macOS (via the Network framework) allows applications to handle networking tasks without directly using the kernel. This provides more flexibility and performance benefits for certain types of network operations, as the networking stack is managed in user space rather than kernel space. This approach reduces overhead and allows more control over networking configurations. In theory, with user-space networking, the application wouldn't be bound by kernel-level socket limits, and it could handle many more simultaneous connections efficiently.

In previous posts on that thread, Quinn mentioned that the Network framework in macOS can rely on the user-space stack (by default) for network operations, but there are still cases where macOS falls back to using the kernel stack (i.e., BSD sockets) under certain conditions. One key example is when the built-in firewall is enabled. This prevents user-space networking from functioning as expected, and the system defaults to using the kernel's BSD sockets for network communication.

In the same discussion, it was also highlighted that NECP (Network Extension Control Plane) could place further limitations on user-space networking, and eventually, systems may run into issues like ENOSPC errors due to excessive simultaneous network flows. This suggests that while user-space networking can offer more flexibility, it's not immune to limits imposed by other system resources or configurations.

Given the information above, I wanted to confirm:

  1. Is the above understanding correct and does the macOS Network framework still use the user-space networking stack in macOS 14 and beyond?

  2. Under what conditions would the system fall back to using the kernel stack (BSD sockets) instead of the user-space stack? For example, does enabling the firewall still disable user-space networking?

  3. What is the practical impact of this fallback on applications that require many simultaneous network connections? Specifically, are there any limitations like the 64K socket limit that developers should be aware of when the system uses the user space stack, and what are the best practices to manage large numbers of connections?

Answered by DTS Engineer in 823183022

Let’s start with some specific points:

Written by harshal_goyal in 773493021
One key example is when the built-in firewall is enabled.

I believe that changed in macOS 15.

Written by harshal_goyal in 773493021
it was also highlighted that NECP (Network Extension Control Plane) could place further limitations on user-space networking

That’s not quite right. That NECP limit applies to the process as a whole, regardless of which networking stack ends up in use.

Speaking of the NECP flow limit, I last looked into that in the macOS 14 timeframe (for example, this thread). I believe that we changed the specific error from ENOSPC to ENOMEM in macOS 15 (r. 126628989). I’m not aware of any other recent changes.

Coming back to your questions:

Written by harshal_goyal in 773493021
1. Is the above understanding correct … ?

Essentially, yes.

Written by harshal_goyal in 773493021
2. Under what conditions would the system fall back to using the kernel stack (BSD sockets) instead of the user-space stack?

That is an implementation detail that can and does change over time. For example, right now I believe that loopback connections still go via the kernel, but it’s not hard to imagine that changing.

Written by harshal_goyal in 773493021
3. What is the practical impact of this fallback on applications that require many simultaneous network connections?

It’s hard to answer such a general question. However, I suspect that the most pressing limit right now is the NECP one.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Let’s start with some specific points:

Written by harshal_goyal in 773493021
One key example is when the built-in firewall is enabled.

I believe that changed in macOS 15.

Written by harshal_goyal in 773493021
it was also highlighted that NECP (Network Extension Control Plane) could place further limitations on user-space networking

That’s not quite right. That NECP limit applies to the process as a whole, regardless of which networking stack ends up in use.

Speaking of the NECP flow limit, I last looked into that in the macOS 14 timeframe (for example, this thread). I believe that we changed the specific error from ENOSPC to ENOMEM in macOS 15 (r. 126628989). I’m not aware of any other recent changes.

Coming back to your questions:

Written by harshal_goyal in 773493021
1. Is the above understanding correct … ?

Essentially, yes.

Written by harshal_goyal in 773493021
2. Under what conditions would the system fall back to using the kernel stack (BSD sockets) instead of the user-space stack?

That is an implementation detail that can and does change over time. For example, right now I believe that loopback connections still go via the kernel, but it’s not hard to imagine that changing.

Written by harshal_goyal in 773493021
3. What is the practical impact of this fallback on applications that require many simultaneous network connections?

It’s hard to answer such a general question. However, I suspect that the most pressing limit right now is the NECP one.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @DTS Engineer ,

Thanks for your insights on the changes in macOS. I have a couple of follow-up questions:

  1. Can you share more details on the changes made with macOS 15 regarding user space network stack and Network Framework?
  2. I’ve been testing network stack behavior on two different macOS machines—one running Sonoma 14.5 and another running Sequoia 15.3—and observed the following:
    • On the Sonoma machine, when the firewall is inactive, the network flow goes to the user-space stack, and I see that skywalkctl is enabled. However, when the firewall is active, it falls back to using the kernel-space BSD sockets instead of the user-space stack.
    • On the Sequoia machine, the firewall status doesn’t seem to affect this, and it always uses the user-space stack.

In terms of managing network connections and the send/receive processes, are there any differences we, as developers, should be aware of when the application uses the kernel stack vs the user-space stack? Specifically, are there any new practices or considerations introduced in macOS 15 that would impact how we handle these aspects?

Written by harshal_goyal in 823185022
Can you share more details on the changes made with macOS 15 [networking]?

Not really. Any given major OS release has more changes than I can reasonably recap, even if I was aware of them, which I’m not.

Written by harshal_goyal in 823185022
should be aware of when the application uses the kernel stack vs the user-space stack?

Not if we’re doing our job correctly (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Clarifying Kernel-Space vs User-Space Networking in macOS: Impact on Applications with Multiple Network Connections
 
 
Q