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:
Renjaya Raga Zenta
2024-02-28 11:35:36 +07:00
parent 815fce2c35
commit 0f30bf5886
7 changed files with 287 additions and 0 deletions
+79
View File
@@ -25,6 +25,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "1"));
str = mfree(str);
cpu_set_reset(&c);
/* Simple range (from CPUAffinity example) */
@@ -43,6 +47,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "1-2 4"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "16"));
str = mfree(str);
cpu_set_reset(&c);
/* A more interesting range */
@@ -61,6 +69,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0-3 8-11"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "f0f"));
str = mfree(str);
cpu_set_reset(&c);
/* Quoted strings */
@@ -76,6 +88,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "8-11"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "f00"));
str = mfree(str);
cpu_set_reset(&c);
/* Use commas as separators */
@@ -106,6 +122,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0-7 63"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "80000000,000000ff"));
str = mfree(str);
cpu_set_reset(&c);
/* Ranges */
@@ -120,6 +140,28 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_string: %s", str);
str = mfree(str);
cpu_set_reset(&c);
assert_se(parse_cpu_set_full("36-39,44-47", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 36; cpu < 40; cpu++)
assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
for (cpu = 44; cpu < 48; cpu++)
assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "f0f0,00000000"));
str = mfree(str);
cpu_set_reset(&c);
assert_se(parse_cpu_set_full("64-71", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
for (cpu = 64; cpu < 72; cpu++)
assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "ff,00000000,00000000"));
str = mfree(str);
cpu_set_reset(&c);
/* Ranges with trailing comma, space */
assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
@@ -136,12 +178,20 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0-3 8-11"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "f0f"));
str = mfree(str);
cpu_set_reset(&c);
/* Negative range (returns empty cpu_set) */
assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
assert_se(CPU_COUNT_S(c.allocated, c.set) == 0);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "0"));
str = mfree(str);
cpu_set_reset(&c);
/* Overlapping ranges */
@@ -157,6 +207,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0-11"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "fff"));
str = mfree(str);
cpu_set_reset(&c);
/* Mix ranges and individual CPUs */
@@ -174,6 +228,10 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "0 2 4-11"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "ff5"));
str = mfree(str);
cpu_set_reset(&c);
/* Garbage */
@@ -190,6 +248,10 @@ TEST(parse_cpu_set) {
assert_se(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
assert_se(!c.set); /* empty string returns NULL */
assert_se(c.allocated == 0);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
assert_se(streq(str, "0"));
str = mfree(str);
/* Runaway quoted string */
assert_se(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
@@ -206,6 +268,23 @@ TEST(parse_cpu_set) {
log_info("cpu_set_to_range_string: %s", str);
assert_se(streq(str, "8000-8191"));
str = mfree(str);
assert_se(str = cpu_set_to_mask_string(&c));
log_info("cpu_set_to_mask_string: %s", str);
for (size_t i = 0; i < strlen(str); i++) {
if (i < 54) {
if (i >= 8 && (i + 1) % 9 == 0)
assert_se(str[i] == ',');
else
assert_se(str[i] == 'f');
}
else {
if (i >= 8 && (i + 1) % 9 == 0)
assert_se(str[i] == ',');
else
assert_se(str[i] == '0');
}
}
str = mfree(str);
cpu_set_reset(&c);
}