From 2d128922ba0b8e2d24e676bc99a1db9a2abcf06f Mon Sep 17 00:00:00 2001 From: prabhataravind <108555774+prabhataravind@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:06:31 -0800 Subject: [PATCH] [image_config]: Enable Receive Packet Steering (RPS) (#20211) [image_config]: Enable Receive Packet Steering (RPS) Signed-off-by: Prabhat Aravind --- .../build_templates/sonic_debian_extension.j2 | 8 +- files/image_config/rps/rps.py | 109 ++++++++++++++++++ files/image_config/udev/rules.d/99-rps.rules | 1 + 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100755 files/image_config/rps/rps.py create mode 100644 files/image_config/udev/rules.d/99-rps.rules diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index aa427f6157c1..8d529b2ec09e 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -515,8 +515,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 @@ -725,6 +727,10 @@ 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 +sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/rps.py + # Copy SNMP configuration files sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/ diff --git a/files/image_config/rps/rps.py b/files/image_config/rps/rps.py new file mode 100755 index 000000000000..df1dbf5a3ccd --- /dev/null +++ b/files/image_config/rps/rps.py @@ -0,0 +1,109 @@ +#!/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 +import argparse + +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(intf): + """ + 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 + + 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: + parser = argparse.ArgumentParser(description='Configure RPS.') + parser.add_argument('interface', type=str, help='Network interface') + args = parser.parse_args() + rv = configure_rps(args.interface) + write_syslog("configure_rps {} for interface {}".format + ("failed" if rv else "successful", args.interface)) + except Exception as e: + write_syslog("configure_rps exception: {}".format(str(e))) + + sys.exit(rv) + + +if __name__ == "__main__": + main() + diff --git a/files/image_config/udev/rules.d/99-rps.rules b/files/image_config/udev/rules.d/99-rps.rules new file mode 100644 index 000000000000..2e98cfe7e07d --- /dev/null +++ b/files/image_config/udev/rules.d/99-rps.rules @@ -0,0 +1 @@ +ACTION=="add", SUBSYSTEM=="net", KERNEL=="Ethernet*", RUN+="/usr/bin/rps.py %k"