Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve arp_responder.py performance #17280

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

saiarcot895
Copy link
Contributor

@saiarcot895 saiarcot895 commented Mar 3, 2025

Description of PR

Summary:
Fixes # (issue)

Type of change

  • Bug fix
  • Testbed and Framework(new/improvement)
  • New Test case
    • Skipped for non-supported platforms
  • Test case improvement

Back port request

  • 202012
  • 202205
  • 202305
  • 202311
  • 202405
  • 202411

Approach

What is the motivation for this PR?

Improve the overall performance of arp_responder.py.

How did you do it?

  1. Reuse the socket that is receiving ARP/NDP requests for sending ARP/NDP responses. This avoids opening a socket, binding it to an interface, sending the packet, and closing it everytime, and just requires one syscall to send the packet.
  2. Use the libpcap socket backend in scapy. With libpcap, instead of needing to use recvmsg syscalls to get packets one at a time, a RX ring buffer is set up as shared memory between userspace and kernel space. The kernel then writes incoming packets into that ring buffer, and then userspace reads it from there. All this happens with only one syscall to select (or equivalent) to know when data (one or more packets) is available, instead of 2 syscalls per packet. The downside is that this does increase memory usage, for the ring buffer to be created. A similar thing can be done for TX, but is a bit harder and is currently not supported by libpcap (so packets being sent out will still use the regular sendmsg syscall.
  3. Enhance the BPF filter created for each socket by specifying which IPv4/IPv6 addresses we care about. That way, the kernel can do some filtering of packets within kernel space, and not need to signal us saying there's a packet available, only for us to get it and discard it. In the case of large VLANs and many hosts per port, this helps significantly.

How did you verify/test it?

Tested with multiple advanced reboot warm upgrade runs.

Any platform specific information?

Supported testbed topology if it's a new test case?

Documentation

Instead of having scapy.sendp create a socket, bind it, send the packet,
and then close the packet every time, just reuse the listening socket
that's been created.

Signed-off-by: Saikrishna Arcot <[email protected]>
Use the libpcap backend in arp_responder, which sets up a ring buffer
for incoming packets. This is expected to be more efficient
than making many recvmsg syscalls, especially during ARP/NDP floods.

Signed-off-by: Saikrishna Arcot <[email protected]>
Enhance the BPF filter for arp_responder to only get ARP/ICMP packets
for the IPv4/IPv6 addresses that it is interested in. This is especially
useful in large VLANs with many hosts.

Signed-off-by: Saikrishna Arcot <[email protected]>
@mssonicbld
Copy link
Collaborator

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants