udevd: Add ReceivePacketSteeringCPUMask for systemd.link
Takes a list of CPU indices or ranges separated by either whitespace or commas. Alternatively, takes the special value "all" in which will include all available CPUs in the mask. CPU ranges are specified by the lower and upper CPU indices separated by a dash (e.g. "2-6"). This option may be specified more than once, in which case the specified CPU affinity masks are merged. If an empty string is assigned, the mask is reset, all assignments prior to this will have no effect. Defaults to unset and RPS CPU list is unchanged. To disable RPS when it was previously enabled, use the special value "disable". Currently, this will set CPU mask to all `rx` queue of matched device (if it has multiple queues). The `/sys/class/net/<dev>/queues/rx-<n>/rps_cpus` only accept cpu bitmap mask in hexadecimal. Fix: #30323
This commit is contained in:
@@ -108,6 +108,7 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32,
|
||||
Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)
|
||||
Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)
|
||||
Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval)
|
||||
Link.ReceivePacketSteeringCPUMask, config_parse_rps_cpu_mask, 0, offsetof(LinkConfig, rps_cpu_mask)
|
||||
Link.MDI, config_parse_mdi, 0, offsetof(LinkConfig, mdi)
|
||||
Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs)
|
||||
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||
|
||||
@@ -73,6 +73,7 @@ static LinkConfig* link_config_free(LinkConfig *config) {
|
||||
free(config->alias);
|
||||
free(config->wol_password_file);
|
||||
erase_and_free(config->wol_password);
|
||||
cpu_set_free(config->rps_cpu_mask);
|
||||
|
||||
ordered_hashmap_free_with_destructor(config->sr_iov_by_section, sr_iov_free);
|
||||
|
||||
@@ -937,6 +938,49 @@ static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_apply_rps_cpu_mask(Link *link) {
|
||||
_cleanup_free_ char *mask_str = NULL;
|
||||
LinkConfig *config;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
config = ASSERT_PTR(link->config);
|
||||
|
||||
/* Skip if the config is not specified. */
|
||||
if (!config->rps_cpu_mask)
|
||||
return 0;
|
||||
|
||||
mask_str = cpu_set_to_mask_string(config->rps_cpu_mask);
|
||||
if (!mask_str)
|
||||
return log_oom();
|
||||
|
||||
log_link_debug(link, "Applying RPS CPU mask: %s", mask_str);
|
||||
|
||||
/* Currently, this will set CPU mask to all rx queue of matched device. */
|
||||
FOREACH_DEVICE_SYSATTR(link->device, attr) {
|
||||
const char *c;
|
||||
|
||||
c = path_startswith(attr, "queues/");
|
||||
if (!c)
|
||||
continue;
|
||||
|
||||
c = startswith(c, "rx-");
|
||||
if (!c)
|
||||
continue;
|
||||
|
||||
c += strcspn(c, "/");
|
||||
|
||||
if (!path_equal(c, "/rps_cpus"))
|
||||
continue;
|
||||
|
||||
r = sd_device_set_sysattr_value(link->device, attr, mask_str);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r, "Failed to write %s sysfs attribute, ignoring: %m", attr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_apply_udev_properties(Link *link, bool test) {
|
||||
LinkConfig *config;
|
||||
sd_device *device;
|
||||
@@ -1024,6 +1068,10 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link, boo
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_apply_rps_cpu_mask(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1314,6 +1362,65 @@ int config_parse_wol_password(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_rps_cpu_mask(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(cpu_set_freep) CPUSet *allocated = NULL;
|
||||
CPUSet *mask, **rps_cpu_mask = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*rps_cpu_mask = cpu_set_free(*rps_cpu_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*rps_cpu_mask)
|
||||
mask = *rps_cpu_mask;
|
||||
else {
|
||||
allocated = new0(CPUSet, 1);
|
||||
if (!allocated)
|
||||
return log_oom();
|
||||
|
||||
mask = allocated;
|
||||
}
|
||||
|
||||
if (streq(rvalue, "disable")) {
|
||||
cpu_set_reset(mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(rvalue, "all")) {
|
||||
r = cpu_mask_add_all(mask);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to create CPU affinity mask representing \"all\" cpus, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
r = parse_cpu_set_extend(rvalue, mask, /* warn= */ true, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (allocated)
|
||||
*rps_cpu_mask = TAKE_PTR(allocated);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
|
||||
[MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
|
||||
[MAC_ADDRESS_POLICY_RANDOM] = "random",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "condition.h"
|
||||
#include "conf-parser.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "ethtool-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "list.h"
|
||||
@@ -84,6 +85,7 @@ struct LinkConfig {
|
||||
int autoneg_flow_control;
|
||||
netdev_coalesce_param coalesce;
|
||||
uint8_t mdi;
|
||||
CPUSet *rps_cpu_mask;
|
||||
|
||||
uint32_t sr_iov_num_vfs;
|
||||
OrderedHashmap *sr_iov_by_section;
|
||||
@@ -121,3 +123,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wol_password);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_rps_cpu_mask);
|
||||
|
||||
Reference in New Issue
Block a user