Skip to content

Commit

Permalink
[image_config]: Enable Receive Packet Steering (RPS)
Browse files Browse the repository at this point in the history
 * This patch enables Receive Packet Steering (RPS) which helps to distribute
   softirq processing for CPU bound packets to all available cores. This will
   help prevent kernel packet drops when there are bouts of intense CPU bound
   packets.

   Ref: https://lwn.net/Articles/362339/
        https://docs.kernel.org/networking/scaling.html

Signed-off-by: Prabhat Aravind <paravind@microsoft.com>
  • Loading branch information
prabhataravind committed Oct 17, 2024
1 parent 4e39a16 commit 336e4d0
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
7 changes: 6 additions & 1 deletion files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,10 @@ sudo cp $IMAGE_CONFIGS/resolv-config/update-containers $FILESYSTEM_ROOT/etc/reso
sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/interfaces
sudo mkdir -p $FILESYSTEM_ROOT/etc/network/interfaces.d

# System'd network udev rules
# Systemd network udev rules
sudo cp $IMAGE_CONFIGS/systemd/network/* $FILESYSTEM_ROOT_ETC/systemd/network/
sudo mkdir -p $FILESYSTEM_ROOT_ETC/udev/rules.d
sudo cp $IMAGE_CONFIGS/udev/rules.d/* $FILESYSTEM_ROOT_ETC/udev/rules.d/

# copy core file uploader files
sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM
Expand Down Expand Up @@ -723,6 +725,9 @@ sudo cp $IMAGE_CONFIGS/backend_acl/backend-acl.service $FILESYSTEM_ROOT_USR_LIB_
sudo cp $IMAGE_CONFIGS/backend_acl/backend_acl.py $FILESYSTEM_ROOT/usr/bin/backend_acl.py
echo "backend-acl.service" | sudo tee -a $GENERATED_SERVICE_FILE

# Copy RPS script file
sudo cp $IMAGE_CONFIGS/rps/rps.py $FILESYSTEM_ROOT/usr/bin/rps.py

# Copy SNMP configuration files
sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/

Expand Down
110 changes: 110 additions & 0 deletions files/image_config/rps/rps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
"""
Script to enable Receive Packet Steering (RPS).
This script reads the number of available CPUs in the system
and configures RPS on all front-panel ports using sysfs.
"""
import os
import sys
import syslog


def write_syslog(message, *args):
"""
Write a message to syslog.
Args:
message (str): Message string to be logged
args: Optional args
Returns:
None
"""

if args:
message %= args
syslog.syslog(syslog.LOG_NOTICE, message)


def get_num_cpus():
"""
Get number of CPUs in the system.
Returns:
ncpus (int): Number of CPUs
"""
ncpus = 0
cpu_count = os.cpu_count()
if cpu_count is not None:
ncpus = cpu_count

return ncpus


def get_cpumask(ncpus):
"""
Get a hex cpumask string.
Args:
ncpus (int): Number of CPUs
Returns:
cpu_mask (str): CPU mask as hex string
"""
cpu_mask = '0'
if isinstance(ncpus, int) and ncpus >= 0:
cpu_mask = hex(pow(2, ncpus) - 1)[2:]

return cpu_mask


def configure_rps():
"""
Configure Receive Packet Steering (RPS)
Returns:
rv (int): zero for success and non-zero otherwise
"""
rv = 0
NET_DIR_PATH = "/sys/class/net"

num_cpus = get_num_cpus()
if not num_cpus:
rv = -1
return rv

cpumask = get_cpumask(num_cpus)
if cpumask == '0':
# Nothing to do
return rv

write_syslog("configure_rps: cpu mask {}".format(cpumask))

# Loop through Ethernet interfaces in /sys/class/net and set rps_cpus
for intf in os.listdir(NET_DIR_PATH):
if "Ethernet" in intf:
queues_path = os.path.join(NET_DIR_PATH, intf, "queues")
queues = os.listdir(queues_path)
num_rx_queues = len([q for q in queues if q.startswith("rx")])
for q in range(num_rx_queues):
rps_cpus_path = os.path.join(queues_path, "rx-{}", "rps_cpus").format(q)
with open(rps_cpus_path, 'w') as file:
file.write(cpumask)

return rv


def main():
rv = -1
try:
rv = configure_rps()
write_syslog("configure_rps {}".format("failed" if rv else "successful"))
except Exception as e:
write_syslog("configure_rps exception: {}".format(str(e)))

sys.exit(rv)


if __name__ == "__main__":
main()

1 change: 1 addition & 0 deletions files/image_config/udev/rules.d/99-rps.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ACTION=="add", SUBSYSTEM=="net", KERNEL=="Ethernet*", RUN+="/usr/bin/rps.py"

0 comments on commit 336e4d0

Please sign in to comment.