1
0
mirror of https://github.com/systemd/systemd synced 2026-04-21 22:44:51 +02:00

Compare commits

...

25 Commits

Author SHA1 Message Date
Luca Boccassi
a549442fff
Merge pull request #22582 from medhefgo/boot-input
boot: Minor input fixes
2022-02-22 22:11:44 +00:00
Luca Boccassi
6ccc08954e
Merge pull request #19970 from curtistklein/watchdog-pretimeout-merge
watchdog: Add watchdog pretimeout support
2022-02-22 22:08:09 +00:00
Yu Watanabe
6e4d122ad1 unit: escape %
Fixes #22601.
2022-02-23 06:54:54 +09:00
Lennart Poettering
b547838000 units: drop After=systemd-networkd.service from systemd-resolved.service
This ordering existed since resolved was first created, but there should
not be any need to order the two services against each other, as
resolved should be able to pick up networkd DNS metadata either way (as
it works with inotify in /run).

Let's drop this hence, and not cargo-cult this to eternity

Also see: https://github.com/systemd/systemd/pull/22389#issuecomment-1045978403
2022-02-23 06:52:39 +09:00
Yu Watanabe
05d8ad0f85
Merge pull request #22596 from yuwata/test-fix-fd-leaks
test: fix fd leaks
2022-02-23 06:51:06 +09:00
Zbigniew Jędrzejewski-Szmek
cab4ed0f4a
Merge pull request #22592 from yuwata/test-oomd-util-fixlets
test: test-oomd-util fixlets
2022-02-22 18:25:45 +01:00
Luca Boccassi
aff3a9e1fa watchdog: add setting to configure pretimeout governor 2022-02-22 17:19:54 +00:00
Curtis Klein
56b96db700 watchdog: check pretimeout governor
Check and log the default pretimeout governor configured in the kernel.
The pretimeout will not work unless at least one governor is available
and configured. This requires loading a kernel module manually.
2022-02-22 17:19:54 +00:00
Curtis Klein
5717062e93 watchdog: Add watchdog pretimeout support
Add support for managing and configuring watchdog pretimeout values if
the watchdog hardware supports it. The ping interval is adjusted to
account for a pretimeout so that it will still ping at half the timeout
interval before a pretimeout event would be triggered. By default the
pretimeout defaults to 0s or disabled.

The RuntimeWatchdogPreSec config option is added to allow the pretimeout
to be specified (similar to RuntimeWatchdogSec). The
RuntimeWatchdogPreUSec dbus property is added to override the pretimeout
value at runtime (similar to RuntimeWatchdogUSec). Setting the
pretimeout to 0s will disable the pretimeout.
2022-02-22 17:19:54 +00:00
Frantisek Sumsal
b491d74064 ci: fix clang-13 installation
For some reason Ubuntu Focal repositories now have `llvm-13` virtual
package which can't be installed, but successfully fools our check,
resulting in no clang/llvm being installed...

```
$ apt show llvm-13
Package: llvm-13
State: not a real package (virtual)
N: Can't select candidate version from package llvm-13 as it has no candidate
N: Can't select versions from package 'llvm-13' as it is purely virtual
N: No packages found

$ apt install --dry-run llvm-13
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package llvm-13 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'llvm-13' has no installation candidate
```
2022-02-22 17:57:25 +01:00
Zbigniew Jędrzejewski-Szmek
09d0758b22
Merge pull request #22574 from yuwata/network-dhcp-pd-fixes
network: dhcp-pd: fix two issues
2022-02-22 17:53:00 +01:00
Lennart Poettering
92148fb777 clang-format: we actually typically use 16ch continuation indentation
We use 8 for blocks, and 16 for continuation in most cases afaics, hence
say so in .clang-format too
2022-02-22 17:32:50 +01:00
Yu Watanabe
be99883e13 test: fix file descriptor leak in test-psi-util
Fixes an issue reported in #22576.
2022-02-23 00:58:16 +09:00
Yu Watanabe
1da5325d19 test: fix file descriptor leak in test-tmpfiles.c
Also fixes a typo in assertion.

Fixes an issure reported in #22576.
2022-02-23 00:58:16 +09:00
Yu Watanabe
19962747ca test: fix file descriptor leak in test-fs-util
Fixes an issue reported in #22576.
2022-02-23 00:58:13 +09:00
Jan Janssen
3f9973bf36 boot: Handle shift and logo keys too
Some firmware supports sending input events for shift and logo keys.
Previously, we would suppress these with EFI_NOT_READY unless
some other key was pressed alongside, but it is really the job of the
caller to decide how to handle these.

Note that for keys that already have a printable shift representation
the reported input event will not have the shift key bits set
(Shift+a is reported as A). Should some firmware turn out to violate the
spec here we can always remove that part.
2022-02-22 16:34:55 +01:00
Jan Janssen
1cb5d7857b boot: Properly check status code of console_key_read
In some cases there was a unlikely possibility that we would look
at an uninitialized key value.
Also, returning in case of unexpected input error cases should prevent
infinite looping.
2022-02-22 16:34:52 +01:00
Yu Watanabe
282696ce52 test: fix file descriptor leak in test-oomd-util
Fixes an issue reported in #22576.
2022-02-22 21:50:52 +09:00
Yu Watanabe
8306912b0e test: fix memory and fd leak in test-dhcp6-client
Fixes an issue reported in #22576.
2022-02-22 21:50:43 +09:00
Yu Watanabe
2e37084fc9 test: drop timeout handlers
Fixes file descriptor leak reported in #22576.
2022-02-22 21:50:32 +09:00
Yu Watanabe
62d4b3b36e test: fix file descriptor leak in test-catalog
Fixes an issue reported in #22576.
2022-02-22 21:50:29 +09:00
Yu Watanabe
07b7337aff network: dhcp-pd: allow to assign the same subnet prefix to multiple interfaces
There is no reason networkd refuses that. Especially, when multiple
downstream interfaces are connected to the same network, it is natural to
assign the same subnet prefix to them.

Prompted by #22571.
2022-02-22 20:39:32 +09:00
Yu Watanabe
38488babe7 network: dhcp-pd: fix prefix length of address assigned to upstream interface
This effectively revert ab0c82d9f749cc397a6b7e0327ddb2c08cd7d7e0.

I have no idea why I did that...

Fixes #22559.
2022-02-22 20:39:28 +09:00
Yu Watanabe
a6d6a51d83 test-oomd-util: fix conditional jump on uninitialised value
Fixes #22577.
2022-02-22 20:24:22 +09:00
Yu Watanabe
d9fe39b24a test-oomd-util: style fixlets 2022-02-22 20:21:57 +09:00
34 changed files with 651 additions and 220 deletions

View File

@ -46,7 +46,7 @@ ColumnLimit: 109
CompactNamespaces: true CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8 ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8 ContinuationIndentWidth: 16
Cpp11BracedListStyle: false Cpp11BracedListStyle: false
ForEachMacros: ForEachMacros:
- BITMAP_FOREACH - BITMAP_FOREACH

View File

@ -78,7 +78,7 @@ if [[ "$COMPILER" == clang ]]; then
# ATTOW llvm-11 got into focal-updates, which conflicts with llvm-11 # ATTOW llvm-11 got into focal-updates, which conflicts with llvm-11
# provided by the apt.llvm.org repositories. Let's use the system # provided by the apt.llvm.org repositories. Let's use the system
# llvm package if available in such cases to avoid that. # llvm package if available in such cases to avoid that.
if ! apt show --quiet "llvm-$COMPILER_VERSION" &>/dev/null; then if ! apt install --dry-run "llvm-$COMPILER_VERSION" >/dev/null; then
# Latest LLVM stack deb packages provided by https://apt.llvm.org/ # Latest LLVM stack deb packages provided by https://apt.llvm.org/
# Following snippet was partly borrowed from https://apt.llvm.org/llvm.sh # Following snippet was partly borrowed from https://apt.llvm.org/llvm.sh
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --yes --dearmor --output /usr/share/keyrings/apt-llvm-org.gpg wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --yes --dearmor --output /usr/share/keyrings/apt-llvm-org.gpg

View File

@ -428,6 +428,28 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>systemd.watchdog_pre_sec=</varname></term>
<listitem>
<para>Overrides the watchdog pre-timeout settings otherwise configured with
<varname>RuntimeWatchdogPreSec=</varname>. Takes a time value (if no unit is specified, seconds is the
implicitly assumed time unit) or the special strings <literal>off</literal> or
<literal>default</literal>. For details, see
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.watchdog_pretimeout_governor=</varname></term>
<listitem>
<para>Overrides the watchdog pre-timeout settings otherwise configured with
<varname>RuntimeWatchdogPreGovernor=</varname>. Takes a string value. For details, see
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>systemd.cpu_affinity=</varname></term> <term><varname>systemd.cpu_affinity=</varname></term>

View File

@ -402,6 +402,12 @@ node /org/freedesktop/systemd1 {
readwrite t RuntimeWatchdogUSec = ...; readwrite t RuntimeWatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true") @org.freedesktop.systemd1.Privileged("true")
readwrite t RuntimeWatchdogPreUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite s RuntimeWatchdogPreGovernor = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite t RebootWatchdogUSec = ...; readwrite t RebootWatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false") @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true") @org.freedesktop.systemd1.Privileged("true")
@ -650,6 +656,10 @@ node /org/freedesktop/systemd1 {
<!--property RuntimeWatchdogUSec is not documented!--> <!--property RuntimeWatchdogUSec is not documented!-->
<!--property RuntimeWatchdogPreUSec is not documented!-->
<!--property RuntimeWatchdogPreGovernor is not documented!-->
<!--property RebootWatchdogUSec is not documented!--> <!--property RebootWatchdogUSec is not documented!-->
<!--property KExecWatchdogUSec is not documented!--> <!--property KExecWatchdogUSec is not documented!-->
@ -1052,6 +1062,10 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeWatchdogUSec"/> <variablelist class="dbus-property" generated="True" extra-ref="RuntimeWatchdogUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeWatchdogPreUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeWatchdogPreGovernor"/>
<variablelist class="dbus-property" generated="True" extra-ref="RebootWatchdogUSec"/> <variablelist class="dbus-property" generated="True" extra-ref="RebootWatchdogUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="KExecWatchdogUSec"/> <variablelist class="dbus-property" generated="True" extra-ref="KExecWatchdogUSec"/>

View File

@ -177,6 +177,50 @@
<para>These settings have no effect if a hardware watchdog is not available.</para></listitem> <para>These settings have no effect if a hardware watchdog is not available.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>RuntimeWatchdogPreSec=</varname></term>
<listitem><para>Configure the hardware watchdog device pre-timeout value.
Takes a timeout value in seconds (or in other time units similar to
<varname>RuntimeWatchdogSec=</varname>). A watchdog pre-timeout is a
notification generated by the watchdog before the watchdog reset might
occur in the event the watchdog has not been serviced. This notification
is handled by the kernel and can be configured to take an action (i.e.
generate a kernel panic) using <varname>RuntimeWatchdogPreGovernor=</varname>.
Not all watchdog hardware or drivers support generating a pre-timeout and
depending on the state of the system, the kernel may be unable to take the
configured action before the watchdog reboot. The watchdog will be configured
to generate the pre-timeout event at the amount of time specified by
<varname>RuntimeWatchdogPreSec=</varname> before the runtime watchdog timeout
(set by <varname>RuntimeWatchdogSec=</varname>). For example, if the we have
<varname>RuntimeWatchdogSec=30</varname> and
<varname>RuntimeWatchdogPreSec=10</varname>, then the pre-timeout event
will occur if the watchdog has not pinged for 20s (10s before the
watchdog would fire). By default, <varname>RuntimeWatchdogPreSec=</varname>
defaults to 0 (off). The value set for <varname>RuntimeWatchdogPreSec=</varname>
must be smaller than the timeout value for <varname>RuntimeWatchdogSec=</varname>.
This setting has no effect if a hardware watchdog is not available or the
hardware watchdog does not support a pre-timeout and will be ignored by the
kernel if the setting is greater than the actual watchdog timeout.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RuntimeWatchdogPreGovernor=</varname></term>
<listitem><para>Configure the action taken by the hardware watchdog device
when the pre-timeout expires. The default action for the pre-timeout event
depends on the kernel configuration, but it is usually to log a kernel
message. For a list of valid actions available for a given watchdog device,
check the content of the
<filename>/sys/class/watchdog/watchdog<replaceable>X</replaceable>/pretimeout_available_governors</filename>
file. Typically, available governor types are <varname>noop</varname> and <varname>panic</varname>.
Availability, names and functionality might vary depending on the specific device driver
in use. If the <filename>pretimeout_available_governors</filename> sysfs file is empty,
the governor might be built as a kernel module and might need to be manually loaded
(e.g. <varname>pretimeout_noop.ko</varname>), or the watchdog device might not support
pre-timeouts.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>WatchdogDevice=</varname></term> <term><varname>WatchdogDevice=</varname></term>

View File

@ -182,6 +182,9 @@ static BOOLEAN line_edit(
cursor_color = TEXT_ATTR_SWAP(cursor_color); cursor_color = TEXT_ATTR_SWAP(cursor_color);
err = console_key_read(&key, 750 * 1000); err = console_key_read(&key, 750 * 1000);
if (!IN_SET(err, EFI_SUCCESS, EFI_TIMEOUT, EFI_NOT_READY))
return FALSE;
print_at(cursor + 1, y_pos, COLOR_EDIT, print + cursor); print_at(cursor + 1, y_pos, COLOR_EDIT, print + cursor);
} while (EFI_ERROR(err)); } while (EFI_ERROR(err));
@ -436,8 +439,16 @@ static void ps_bool(const CHAR16 *fmt, BOOLEAN value) {
Print(fmt, yes_no(value)); Print(fmt, yes_no(value));
} }
static void print_status(Config *config, CHAR16 *loaded_image_path) { static BOOLEAN ps_continue(void) {
UINT64 key; UINT64 key;
EFI_STATUS err;
Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n");
err = console_key_read(&key, UINT64_MAX);
return !EFI_ERROR(err) && !IN_SET(key, KEYPRESS(0, SCAN_ESC, 0), KEYPRESS(0, 0, 'q'), KEYPRESS(0, 0, 'Q'));
}
static void print_status(Config *config, CHAR16 *loaded_image_path) {
UINTN x_max, y_max; UINTN x_max, y_max;
UINT32 screen_width = 0, screen_height = 0; UINT32 screen_width = 0, screen_height = 0;
SecureBootMode secure; SecureBootMode secure;
@ -468,8 +479,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
ps_bool(L" TPM: %s\n", tpm_present()); ps_bool(L" TPM: %s\n", tpm_present());
Print(L" console mode: %d/%d (%lux%lu @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL, x_max, y_max, screen_width, screen_height); Print(L" console mode: %d/%d (%lux%lu @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL, x_max, y_max, screen_width, screen_height);
Print(L"\n--- Press any key to continue. ---\n\n"); if (!ps_continue())
console_key_read(&key, UINT64_MAX); return;
switch (config->timeout_sec_config) { switch (config->timeout_sec_config) {
case TIMEOUT_UNSET: case TIMEOUT_UNSET:
@ -519,8 +530,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
if (config->console_mode_efivar != CONSOLE_MODE_KEEP) if (config->console_mode_efivar != CONSOLE_MODE_KEEP)
Print(L"console-mode (EFI var): %ld\n", config->console_mode_efivar); Print(L"console-mode (EFI var): %ld\n", config->console_mode_efivar);
Print(L"\n--- Press any key to continue. ---\n\n"); if (!ps_continue())
console_key_read(&key, UINT64_MAX); return;
for (UINTN i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
ConfigEntry *entry = config->entries[i]; ConfigEntry *entry = config->entries[i];
@ -545,10 +556,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L" next path: %s\\%s\n", entry->path, entry->next_name); Print(L" next path: %s\\%s\n", entry->path, entry->next_name);
} }
Print(L"\n--- Press any key to continue, ESC or q to quit. ---\n\n"); if (!ps_continue())
console_key_read(&key, UINT64_MAX); return;
if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q') || key == KEYPRESS(0, 0, 'Q'))
break;
} }
} }
@ -734,7 +743,12 @@ static BOOLEAN menu_run(
beep(idx_highlight + 1); beep(idx_highlight + 1);
err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : UINT64_MAX); err = console_key_read(&key, timeout_remain > 0 ? 1000 * 1000 : UINT64_MAX);
if (err == EFI_NOT_READY)
/* No input device returned a key, try again. This
* normally should not happen. */
continue;
if (err == EFI_TIMEOUT) { if (err == EFI_TIMEOUT) {
assert(timeout_remain > 0);
timeout_remain--; timeout_remain--;
if (timeout_remain == 0) { if (timeout_remain == 0) {
exit = TRUE; exit = TRUE;
@ -743,7 +757,12 @@ static BOOLEAN menu_run(
/* update status */ /* update status */
continue; continue;
} else }
if (EFI_ERROR(err)) {
exit = TRUE;
break;
}
timeout_remain = 0; timeout_remain = 0;
/* clear status after keystroke */ /* clear status after keystroke */

View File

@ -124,29 +124,27 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
* The two may be out of sync on some firmware, giving us double input. */ * The two may be out of sync on some firmware, giving us double input. */
if (conInEx) { if (conInEx) {
EFI_KEY_DATA keydata; EFI_KEY_DATA keydata;
UINT64 keypress;
UINT32 shift = 0; UINT32 shift = 0;
err = conInEx->ReadKeyStrokeEx(conInEx, &keydata); err = conInEx->ReadKeyStrokeEx(conInEx, &keydata);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
/* do not distinguish between left and right keys */ if (FLAGS_SET(keydata.KeyState.KeyShiftState, EFI_SHIFT_STATE_VALID)) {
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) { /* Do not distinguish between left and right keys (set both flags). */
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)) if (keydata.KeyState.KeyShiftState & EFI_SHIFT_PRESSED)
shift |= EFI_SHIFT_PRESSED;
if (keydata.KeyState.KeyShiftState & EFI_CONTROL_PRESSED)
shift |= EFI_CONTROL_PRESSED; shift |= EFI_CONTROL_PRESSED;
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)) if (keydata.KeyState.KeyShiftState & EFI_ALT_PRESSED)
shift |= EFI_ALT_PRESSED; shift |= EFI_ALT_PRESSED;
if (keydata.KeyState.KeyShiftState & EFI_LOGO_PRESSED)
shift |= EFI_LOGO_PRESSED;
} }
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar); *key = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
if (keypress > 0) {
*key = keypress;
return EFI_SUCCESS; return EFI_SUCCESS;
}
return EFI_NOT_READY;
} else if (!EFI_ERROR(BS->CheckEvent(ST->ConIn->WaitForKey))) { } else if (!EFI_ERROR(BS->CheckEvent(ST->ConIn->WaitForKey))) {
EFI_INPUT_KEY k; EFI_INPUT_KEY k;

View File

@ -3,10 +3,15 @@
#include "missing_efi.h" #include "missing_efi.h"
#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED) enum {
#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED) EFI_SHIFT_PRESSED = EFI_RIGHT_SHIFT_PRESSED|EFI_LEFT_SHIFT_PRESSED,
EFI_CONTROL_PRESSED = EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED,
EFI_ALT_PRESSED = EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED,
EFI_LOGO_PRESSED = EFI_RIGHT_LOGO_PRESSED|EFI_LEFT_LOGO_PRESSED,
};
#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | (((UINT64)scan) << 16) | (uni)) #define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | (((UINT64)scan) << 16) | (uni))
#define KEYCHAR(k) ((k) & 0xffff) #define KEYCHAR(k) ((CHAR16)(k))
#define CHAR_CTRL(c) ((c) - 'a' + 1) #define CHAR_CTRL(c) ((c) - 'a' + 1)
enum { enum {

View File

@ -13,10 +13,14 @@
#define SimpleTextInputExProtocol ((EFI_GUID)EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID) #define SimpleTextInputExProtocol ((EFI_GUID)EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID)
#define EFI_SHIFT_STATE_VALID 0x80000000 #define EFI_SHIFT_STATE_VALID 0x80000000
#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
#define EFI_LEFT_SHIFT_PRESSED 0x00000002
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 #define EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define EFI_LEFT_CONTROL_PRESSED 0x00000008 #define EFI_LEFT_CONTROL_PRESSED 0x00000008
#define EFI_RIGHT_ALT_PRESSED 0x00000010 #define EFI_RIGHT_ALT_PRESSED 0x00000010
#define EFI_LEFT_ALT_PRESSED 0x00000020 #define EFI_LEFT_ALT_PRESSED 0x00000020
#define EFI_RIGHT_LOGO_PRESSED 0x00000040
#define EFI_LEFT_LOGO_PRESSED 0x00000080
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;

View File

@ -265,6 +265,42 @@ static int property_get_runtime_watchdog(
return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_RUNTIME)); return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_RUNTIME));
} }
static int property_get_pretimeout_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_PRETIMEOUT));
}
static int property_get_pretimeout_watchdog_governor(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "s", m->watchdog_pretimeout_governor);
}
static int property_get_reboot_watchdog( static int property_get_reboot_watchdog(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -330,6 +366,42 @@ static int property_set_runtime_watchdog(
return property_set_watchdog(userdata, WATCHDOG_RUNTIME, value); return property_set_watchdog(userdata, WATCHDOG_RUNTIME, value);
} }
static int property_set_pretimeout_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *userdata,
sd_bus_error *error) {
return property_set_watchdog(userdata, WATCHDOG_PRETIMEOUT, value);
}
static int property_set_pretimeout_watchdog_governor(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
char *governor;
int r;
assert(m);
r = sd_bus_message_read(value, "s", &governor);
if (r < 0)
return r;
if (!string_is_safe(governor))
return -EINVAL;
return manager_override_watchdog_pretimeout_governor(m, governor);
}
static int property_set_reboot_watchdog( static int property_set_reboot_watchdog(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -2696,6 +2768,8 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_error), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_error), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", property_get_runtime_watchdog, property_set_runtime_watchdog, 0, 0), SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", property_get_runtime_watchdog, property_set_runtime_watchdog, 0, 0),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogPreUSec", "t", property_get_pretimeout_watchdog, property_set_pretimeout_watchdog, 0, 0),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogPreGovernor", "s", property_get_pretimeout_watchdog_governor, property_set_pretimeout_watchdog_governor, 0, 0),
SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, 0), SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, 0),
/* The following item is an obsolete alias */ /* The following item is an obsolete alias */
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, SD_BUS_VTABLE_HIDDEN),

View File

@ -138,7 +138,9 @@ static unsigned arg_default_start_limit_burst;
static usec_t arg_runtime_watchdog; static usec_t arg_runtime_watchdog;
static usec_t arg_reboot_watchdog; static usec_t arg_reboot_watchdog;
static usec_t arg_kexec_watchdog; static usec_t arg_kexec_watchdog;
static usec_t arg_pretimeout_watchdog;
static char *arg_early_core_pattern; static char *arg_early_core_pattern;
static char *arg_watchdog_pretimeout_governor;
static char *arg_watchdog_device; static char *arg_watchdog_device;
static char **arg_default_environment; static char **arg_default_environment;
static char **arg_manager_environment; static char **arg_manager_environment;
@ -557,6 +559,37 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
arg_kexec_watchdog = arg_reboot_watchdog = arg_runtime_watchdog; arg_kexec_watchdog = arg_reboot_watchdog = arg_runtime_watchdog;
} else if (proc_cmdline_key_streq(key, "systemd.watchdog_pre_sec")) {
if (proc_cmdline_value_missing(key, value))
return 0;
if (streq(value, "default"))
arg_pretimeout_watchdog = USEC_INFINITY;
else if (streq(value, "off"))
arg_pretimeout_watchdog = 0;
else {
r = parse_sec(value, &arg_pretimeout_watchdog);
if (r < 0) {
log_warning_errno(r, "Failed to parse systemd.watchdog_pre_sec= argument '%s', ignoring: %m", value);
return 0;
}
}
} else if (proc_cmdline_key_streq(key, "systemd.watchdog_pretimeout_governor")) {
if (proc_cmdline_value_missing(key, value) || isempty(value)) {
arg_watchdog_pretimeout_governor = mfree(arg_watchdog_pretimeout_governor);
return 0;
}
if (!string_is_safe(value)) {
log_warning("Watchdog pretimeout governor '%s' is not valid, ignoring.", value);
return 0;
}
return free_and_strdup_warn(&arg_watchdog_pretimeout_governor, value);
} else if (proc_cmdline_key_streq(key, "systemd.clock_usec")) { } else if (proc_cmdline_key_streq(key, "systemd.clock_usec")) {
if (proc_cmdline_value_missing(key, value)) if (proc_cmdline_value_missing(key, value))
@ -709,10 +742,12 @@ static int parse_config_file(void) {
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy }, { "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy },
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL }, { "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog }, { "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
{ "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, { "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog },
{ "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */ { "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog }, { "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device }, { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
{ "Manager", "RuntimeWatchdogPreGovernor", config_parse_safe_string, 0, &arg_watchdog_pretimeout_governor },
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set }, { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs }, { "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
#if HAVE_SECCOMP #if HAVE_SECCOMP
@ -837,6 +872,7 @@ static void set_manager_defaults(Manager *m) {
} }
static void set_manager_settings(Manager *m) { static void set_manager_settings(Manager *m) {
int r;
assert(m); assert(m);
@ -851,6 +887,10 @@ static void set_manager_settings(Manager *m) {
manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog); manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog);
manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog); manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog);
manager_set_watchdog(m, WATCHDOG_KEXEC, arg_kexec_watchdog); manager_set_watchdog(m, WATCHDOG_KEXEC, arg_kexec_watchdog);
manager_set_watchdog(m, WATCHDOG_PRETIMEOUT, arg_pretimeout_watchdog);
r = manager_set_watchdog_pretimeout_governor(m, arg_watchdog_pretimeout_governor);
if (r < 0)
log_warning_errno(r, "Failed to set watchdog pretimeout governor to '%s', ignoring: %m", arg_watchdog_pretimeout_governor);
manager_set_show_status(m, arg_show_status, "commandline"); manager_set_show_status(m, arg_show_status, "commandline");
m->status_unit_format = arg_status_unit_format; m->status_unit_format = arg_status_unit_format;
@ -1595,7 +1635,10 @@ static int become_shutdown(
watchdog_timer = arg_kexec_watchdog; watchdog_timer = arg_kexec_watchdog;
/* If we reboot or kexec let's set the shutdown watchdog and tell the /* If we reboot or kexec let's set the shutdown watchdog and tell the
* shutdown binary to repeatedly ping it */ * shutdown binary to repeatedly ping it.
* Disable the pretimeout watchdog, as we do not support it from the shutdown binary. */
(void) watchdog_setup_pretimeout(0);
(void) watchdog_setup_pretimeout_governor(NULL);
r = watchdog_setup(watchdog_timer); r = watchdog_setup(watchdog_timer);
watchdog_close(r < 0); watchdog_close(r < 0);
@ -2448,8 +2491,10 @@ static void reset_arguments(void) {
arg_runtime_watchdog = 0; arg_runtime_watchdog = 0;
arg_reboot_watchdog = 10 * USEC_PER_MINUTE; arg_reboot_watchdog = 10 * USEC_PER_MINUTE;
arg_kexec_watchdog = 0; arg_kexec_watchdog = 0;
arg_pretimeout_watchdog = 0;
arg_early_core_pattern = NULL; arg_early_core_pattern = NULL;
arg_watchdog_device = NULL; arg_watchdog_device = NULL;
arg_watchdog_pretimeout_governor = mfree(arg_watchdog_pretimeout_governor);
arg_default_environment = strv_free(arg_default_environment); arg_default_environment = strv_free(arg_default_environment);
arg_manager_environment = strv_free(arg_manager_environment); arg_manager_environment = strv_free(arg_manager_environment);

View File

@ -118,6 +118,8 @@ int manager_serialize(
(void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]); (void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
(void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]); (void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
(void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]); (void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
(void) serialize_usec(f, "pretimeout-watchdog-overridden", m->watchdog_overridden[WATCHDOG_PRETIMEOUT]);
(void) serialize_item(f, "pretimeout-watchdog-governor-overridden", m->watchdog_pretimeout_governor_overridden);
for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
_cleanup_free_ char *joined = NULL; _cleanup_free_ char *joined = NULL;
@ -455,6 +457,19 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
else else
manager_override_watchdog(m, WATCHDOG_KEXEC, t); manager_override_watchdog(m, WATCHDOG_KEXEC, t);
} else if ((val = startswith(l, "pretimeout-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse pretimeout-watchdog-overridden value '%s', ignoring.", val);
else
manager_override_watchdog(m, WATCHDOG_PRETIMEOUT, t);
} else if ((val = startswith(l, "pretimeout-watchdog-governor-overridden="))) {
r = free_and_strdup(&m->watchdog_pretimeout_governor_overridden, val);
if (r < 0)
return r;
} else if (startswith(l, "env=")) { } else if (startswith(l, "env=")) {
r = deserialize_environment(l + 4, &m->client_environment); r = deserialize_environment(l + 4, &m->client_environment);
if (r < 0) if (r < 0)

View File

@ -813,6 +813,7 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
.watchdog_overridden[WATCHDOG_RUNTIME] = USEC_INFINITY, .watchdog_overridden[WATCHDOG_RUNTIME] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY, .watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY, .watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_PRETIMEOUT] = USEC_INFINITY,
.show_status_overridden = _SHOW_STATUS_INVALID, .show_status_overridden = _SHOW_STATUS_INVALID,
@ -1541,6 +1542,9 @@ Manager* manager_free(Manager *m) {
m->prefix[dt] = mfree(m->prefix[dt]); m->prefix[dt] = mfree(m->prefix[dt]);
free(m->received_credentials); free(m->received_credentials);
free(m->watchdog_pretimeout_governor);
free(m->watchdog_pretimeout_governor_overridden);
#if BPF_FRAMEWORK #if BPF_FRAMEWORK
lsm_bpf_destroy(m->restrict_fs); lsm_bpf_destroy(m->restrict_fs);
#endif #endif
@ -3232,9 +3236,12 @@ void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
if (m->watchdog[t] == timeout) if (m->watchdog[t] == timeout)
return; return;
if (t == WATCHDOG_RUNTIME) if (t == WATCHDOG_RUNTIME) {
if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME])) if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME]))
(void) watchdog_setup(timeout); (void) watchdog_setup(timeout);
} else if (t == WATCHDOG_PRETIMEOUT)
if (m->watchdog_overridden[WATCHDOG_PRETIMEOUT] == USEC_INFINITY)
(void) watchdog_setup_pretimeout(timeout);
m->watchdog[t] = timeout; m->watchdog[t] = timeout;
} }
@ -3253,11 +3260,58 @@ void manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
usec_t usec = timestamp_is_set(timeout) ? timeout : m->watchdog[t]; usec_t usec = timestamp_is_set(timeout) ? timeout : m->watchdog[t];
(void) watchdog_setup(usec); (void) watchdog_setup(usec);
} } else if (t == WATCHDOG_PRETIMEOUT)
(void) watchdog_setup_pretimeout(timeout);
m->watchdog_overridden[t] = timeout; m->watchdog_overridden[t] = timeout;
} }
int manager_set_watchdog_pretimeout_governor(Manager *m, const char *governor) {
_cleanup_free_ char *p = NULL;
int r;
assert(m);
if (MANAGER_IS_USER(m))
return 0;
if (streq_ptr(m->watchdog_pretimeout_governor, governor))
return 0;
p = strdup(governor);
if (!p)
return -ENOMEM;
r = watchdog_setup_pretimeout_governor(governor);
if (r < 0)
return r;
return free_and_replace(m->watchdog_pretimeout_governor, p);
}
int manager_override_watchdog_pretimeout_governor(Manager *m, const char *governor) {
_cleanup_free_ char *p = NULL;
int r;
assert(m);
if (MANAGER_IS_USER(m))
return 0;
if (streq_ptr(m->watchdog_pretimeout_governor_overridden, governor))
return 0;
p = strdup(governor);
if (!p)
return -ENOMEM;
r = watchdog_setup_pretimeout_governor(governor);
if (r < 0)
return r;
return free_and_replace(m->watchdog_pretimeout_governor_overridden, p);
}
int manager_reload(Manager *m) { int manager_reload(Manager *m) {
_unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; _unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL; _cleanup_fdset_free_ FDSet *fds = NULL;

View File

@ -118,6 +118,7 @@ typedef enum WatchdogType {
WATCHDOG_RUNTIME, WATCHDOG_RUNTIME,
WATCHDOG_REBOOT, WATCHDOG_REBOOT,
WATCHDOG_KEXEC, WATCHDOG_KEXEC,
WATCHDOG_PRETIMEOUT,
_WATCHDOG_TYPE_MAX, _WATCHDOG_TYPE_MAX,
} WatchdogType; } WatchdogType;
@ -247,6 +248,8 @@ struct Manager {
usec_t watchdog[_WATCHDOG_TYPE_MAX]; usec_t watchdog[_WATCHDOG_TYPE_MAX];
usec_t watchdog_overridden[_WATCHDOG_TYPE_MAX]; usec_t watchdog_overridden[_WATCHDOG_TYPE_MAX];
char *watchdog_pretimeout_governor;
char *watchdog_pretimeout_governor_overridden;
dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX]; dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX];
@ -574,6 +577,8 @@ ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s);
usec_t manager_get_watchdog(Manager *m, WatchdogType t); usec_t manager_get_watchdog(Manager *m, WatchdogType t);
void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout); void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout);
void manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout); void manager_override_watchdog(Manager *m, WatchdogType t, usec_t timeout);
int manager_set_watchdog_pretimeout_governor(Manager *m, const char *governor);
int manager_override_watchdog_pretimeout_governor(Manager *m, const char *governor);
const char* oom_policy_to_string(OOMPolicy i) _const_; const char* oom_policy_to_string(OOMPolicy i) _const_;
OOMPolicy oom_policy_from_string(const char *s) _pure_; OOMPolicy oom_policy_from_string(const char *s) _pure_;

View File

@ -30,6 +30,8 @@
#NUMAPolicy=default #NUMAPolicy=default
#NUMAMask= #NUMAMask=
#RuntimeWatchdogSec=off #RuntimeWatchdogSec=off
#RuntimeWatchdogPreSec=off
#RuntimeWatchdogPreGovernor=
#RebootWatchdogSec=10min #RebootWatchdogSec=10min
#KExecWatchdogSec=off #KExecWatchdogSec=off
#WatchdogDevice= #WatchdogDevice=

View File

@ -31,13 +31,6 @@ static bool verbose = true;
static int test_fd[2]; static int test_fd[2];
static test_callback_recv_t callback_recv; static test_callback_recv_t callback_recv;
static be32_t xid; static be32_t xid;
static sd_event_source *test_hangcheck;
static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
assert_not_reached();
return 0;
}
static void test_request_basic(sd_event *e) { static void test_request_basic(sd_event *e) {
int r; int r;
@ -514,19 +507,15 @@ static void test_addr_acq(sd_event *e) {
callback_recv = test_addr_acq_recv_discover; callback_recv = test_addr_acq_recv_discover;
assert_se(sd_event_add_time_relative( assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
e, &test_hangcheck,
clock_boottime_or_monotonic(),
2 * USEC_PER_SEC, 0, 2 * USEC_PER_SEC, 0,
test_dhcp_hangcheck, NULL) >= 0); NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
res = sd_dhcp_client_start(client); res = sd_dhcp_client_start(client);
assert_se(IN_SET(res, 0, -EINPROGRESS)); assert_se(IN_SET(res, 0, -EINPROGRESS));
assert_se(sd_event_loop(e) >= 0); assert_se(sd_event_loop(e) >= 0);
test_hangcheck = sd_event_source_unref(test_hangcheck);
assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0); assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
assert_se(sd_dhcp_client_stop(client) >= 0); assert_se(sd_dhcp_client_stop(client) >= 0);
sd_dhcp_client_unref(client); sd_dhcp_client_unref(client);

View File

@ -78,8 +78,6 @@ static int test_ifindex = 42;
static unsigned test_client_sent_message_count = 0; static unsigned test_client_sent_message_count = 0;
static sd_dhcp6_client *client_ref = NULL; static sd_dhcp6_client *client_ref = NULL;
STATIC_DESTRUCTOR_REGISTER(client_ref, sd_dhcp6_client_unrefp);
static void test_client_basic(void) { static void test_client_basic(void) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
int v; int v;
@ -981,7 +979,7 @@ static void test_dhcp6_client(void) {
assert_se(sd_event_new(&e) >= 0); assert_se(sd_event_new(&e) >= 0);
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(), assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
2 * USEC_PER_SEC, 0, 2 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(ETIMEDOUT)) >= 0); NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
@ -1004,6 +1002,7 @@ static void test_dhcp6_client(void) {
assert_se(test_client_sent_message_count == 4); assert_se(test_client_sent_message_count == 4);
assert_se(!sd_dhcp6_client_unref(client_ref));
test_fd[1] = safe_close(test_fd[1]); test_fd[1] = safe_close(test_fd[1]);
} }

View File

@ -51,7 +51,6 @@ static uint8_t advertisement[] = {
0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
static sd_event_source *test_hangcheck;
static bool test_stopped; static bool test_stopped;
static int test_fd[2]; static int test_fd[2];
static sd_event_source *recv_router_advertisement; static sd_event_source *recv_router_advertisement;
@ -101,13 +100,6 @@ static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8,
static const char *test_dnssl[] = { "lab.intra", static const char *test_dnssl[] = { "lab.intra",
NULL }; NULL };
static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
void *userdata) {
assert_se(false);
return 0;
}
static void test_radv_prefix(void) { static void test_radv_prefix(void) {
sd_radv_prefix *p; sd_radv_prefix *p;
@ -341,16 +333,13 @@ static void test_ra(void) {
assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0],
EPOLLIN, radv_recv, ra) >= 0); EPOLLIN, radv_recv, ra) >= 0);
assert_se(sd_event_add_time_relative( assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
e, &test_hangcheck, clock_boottime_or_monotonic(),
2 * USEC_PER_SEC, 0, 2 * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_radv_start(ra) >= 0); assert_se(sd_radv_start(ra) >= 0);
sd_event_loop(e); assert_se(sd_event_loop(e) >= 0);
test_hangcheck = sd_event_source_unref(test_hangcheck);
ra = sd_radv_unref(ra); ra = sd_radv_unref(ra);
assert_se(!ra); assert_se(!ra);

View File

@ -22,7 +22,6 @@ static struct ether_addr mac_addr = {
}; };
static bool verbose = false; static bool verbose = false;
static sd_event_source *test_hangcheck;
static int test_fd[2]; static int test_fd[2];
static sd_ndisc *test_timeout_nd; static sd_ndisc *test_timeout_nd;
@ -166,13 +165,6 @@ static void router_dump(sd_ndisc_router *rt) {
} }
} }
static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
void *userdata) {
assert_se(false);
return 0;
}
int icmp6_bind_router_solicitation(int ifindex) { int icmp6_bind_router_solicitation(int ifindex) {
assert_se(ifindex == 42); assert_se(ifindex == 42);
@ -285,10 +277,9 @@ static void test_rs(void) {
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0); assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);
assert_se(sd_event_add_time_relative( assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
e, &test_hangcheck, clock_boottime_or_monotonic(),
30 * USEC_PER_SEC, 0, 30 * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_ndisc_stop(nd) >= 0); assert_se(sd_ndisc_stop(nd) >= 0);
assert_se(sd_ndisc_start(nd) >= 0); assert_se(sd_ndisc_start(nd) >= 0);
@ -297,9 +288,7 @@ static void test_rs(void) {
assert_se(sd_ndisc_start(nd) >= 0); assert_se(sd_ndisc_start(nd) >= 0);
sd_event_loop(e); assert_se(sd_event_loop(e) >= 0);
test_hangcheck = sd_event_source_unref(test_hangcheck);
nd = sd_ndisc_unref(nd); nd = sd_ndisc_unref(nd);
assert_se(!nd); assert_se(!nd);
@ -379,16 +368,13 @@ static void test_timeout(void) {
assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_event_add_time_relative( assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
e, &test_hangcheck, clock_boottime_or_monotonic(),
30 * USEC_PER_SEC, 0, 30 * USEC_PER_SEC, 0,
test_rs_hangcheck, NULL) >= 0); NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
assert_se(sd_ndisc_start(nd) >= 0); assert_se(sd_ndisc_start(nd) >= 0);
sd_event_loop(e); assert_se(sd_event_loop(e) >= 0);
test_hangcheck = sd_event_source_unref(test_hangcheck);
nd = sd_ndisc_unref(nd); nd = sd_ndisc_unref(nd);

View File

@ -196,6 +196,7 @@ static void test_catalog_file_lang(void) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
_cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX"; _cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX";
_cleanup_close_ int fd = -1;
_cleanup_free_ char *text = NULL; _cleanup_free_ char *text = NULL;
int r; int r;
@ -218,7 +219,7 @@ int main(int argc, char *argv[]) {
test_catalog_import_merge(); test_catalog_import_merge();
test_catalog_import_merge_no_body(); test_catalog_import_merge_no_body();
assert_se(mkostemp_safe(database) >= 0); assert_se((fd = mkostemp_safe(database)) >= 0);
test_catalog_update(database); test_catalog_update(database);

View File

@ -252,8 +252,8 @@ static int generate_addresses(
return 0; return 0;
} }
int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) { int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret) {
return generate_addresses(link, link->network->dhcp_pd_tokens, &DHCP_PD_APP_ID, prefix, prefixlen, ret); return generate_addresses(link, link->network->dhcp_pd_tokens, &DHCP_PD_APP_ID, prefix, 64, ret);
} }
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) { int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {

View File

@ -7,7 +7,7 @@
typedef struct Link Link; typedef struct Link Link;
int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret); int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, Set **ret);
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret); int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret); int radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);

View File

@ -307,7 +307,7 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1; return 1;
} }
static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, usec_t lifetime_usec) { static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
Route *existing; Route *existing;
int r; int r;
@ -326,7 +326,7 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, uint
route->source = NETWORK_CONFIG_SOURCE_DHCP_PD; route->source = NETWORK_CONFIG_SOURCE_DHCP_PD;
route->family = AF_INET6; route->family = AF_INET6;
route->dst.in6 = *prefix; route->dst.in6 = *prefix;
route->dst_prefixlen = prefixlen; route->dst_prefixlen = 64;
route->protocol = RTPROT_DHCP; route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_pd_route_metric; route->priority = link->network->dhcp_pd_route_metric;
route->lifetime_usec = lifetime_usec; route->lifetime_usec = lifetime_usec;
@ -386,7 +386,6 @@ static void log_dhcp_pd_address(Link *link, const Address *address) {
static int dhcp_pd_request_address( static int dhcp_pd_request_address(
Link *link, Link *link,
const struct in6_addr *prefix, const struct in6_addr *prefix,
uint8_t prefixlen,
usec_t lifetime_preferred_usec, usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) { usec_t lifetime_valid_usec) {
@ -401,7 +400,7 @@ static int dhcp_pd_request_address(
if (!link->network->dhcp_pd_assign) if (!link->network->dhcp_pd_assign)
return 0; return 0;
r = dhcp_pd_generate_addresses(link, prefix, prefixlen, &addresses); r = dhcp_pd_generate_addresses(link, prefix, &addresses);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCP delegated prefix: %m"); return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCP delegated prefix: %m");
@ -416,10 +415,9 @@ static int dhcp_pd_request_address(
address->source = NETWORK_CONFIG_SOURCE_DHCP_PD; address->source = NETWORK_CONFIG_SOURCE_DHCP_PD;
address->family = AF_INET6; address->family = AF_INET6;
address->in_addr.in6 = *a; address->in_addr.in6 = *a;
address->prefixlen = prefixlen; address->prefixlen = 64;
address->lifetime_preferred_usec = lifetime_preferred_usec; address->lifetime_preferred_usec = lifetime_preferred_usec;
address->lifetime_valid_usec = lifetime_valid_usec; address->lifetime_valid_usec = lifetime_valid_usec;
if (prefixlen == 64)
SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp_pd_manage_temporary_address); SET_FLAG(address->flags, IFA_F_MANAGETEMPADDR, link->network->dhcp_pd_manage_temporary_address);
address->route_metric = link->network->dhcp_pd_route_metric; address->route_metric = link->network->dhcp_pd_route_metric;
@ -489,20 +487,13 @@ static int dhcp_pd_get_preferred_subnet_prefix(
"subnet id %" PRIu64 " is out of range. Only have %" PRIu64 " subnets.", "subnet id %" PRIu64 " is out of range. Only have %" PRIu64 " subnets.",
link->network->dhcp_pd_subnet_id, UINT64_C(1) << (64 - pd_prefix_len)); link->network->dhcp_pd_subnet_id, UINT64_C(1) << (64 - pd_prefix_len));
if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) >= 0 &&
assigned_link != link) {
_cleanup_free_ char *assigned_buf = NULL;
(void) in6_addr_to_string(&prefix, &assigned_buf);
return log_link_warning_errno(link, SYNTHETIC_ERRNO(EAGAIN),
"The requested prefix %s is already assigned to another link.",
strna(assigned_buf));
}
*ret = prefix; *ret = prefix;
return 0; return 0;
} }
if (dhcp_pd_get_assigned_subnet_prefix(link, pd_prefix, pd_prefix_len, ret) >= 0)
return 0;
for (uint64_t n = 0; ; n++) { for (uint64_t n = 0; ; n++) {
/* If we do not have an allocation preference just iterate /* If we do not have an allocation preference just iterate
* through the address space and return the first free prefix. */ * through the address space and return the first free prefix. */
@ -519,19 +510,25 @@ static int dhcp_pd_get_preferred_subnet_prefix(
/* Check that the prefix is not assigned to another link. */ /* Check that the prefix is not assigned to another link. */
if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) < 0 || if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) < 0 ||
assigned_link == link) { assigned_link == link)
break;
}
r = link_add_dhcp_pd_subnet_prefix(link, &prefix);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to save acquired free subnet prefix: %m");
*ret = prefix; *ret = prefix;
return 0; return 0;
} }
}
}
static int dhcp_pd_assign_subnet_prefix( static int dhcp_pd_assign_subnet_prefix(
Link *link, Link *link,
const struct in6_addr *pd_prefix, const struct in6_addr *pd_prefix,
uint8_t pd_prefix_len, uint8_t pd_prefix_len,
usec_t lifetime_preferred_usec, usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) { usec_t lifetime_valid_usec,
bool is_uplink) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
struct in6_addr prefix; struct in6_addr prefix;
@ -541,68 +538,31 @@ static int dhcp_pd_assign_subnet_prefix(
assert(link->network); assert(link->network);
assert(pd_prefix); assert(pd_prefix);
if (dhcp_pd_get_assigned_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0 && r = dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix);
dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0) if (r < 0)
return 0; return r == -ERANGE ? 0 : r;
(void) in6_addr_prefix_to_string(&prefix, 64, &buf); (void) in6_addr_prefix_to_string(&prefix, 64, &buf);
if (link_radv_enabled(link) && link->network->dhcp_pd_announce) { if (link_radv_enabled(link) && link->network->dhcp_pd_announce) {
if (is_uplink)
log_link_debug(link, "Ignoring Announce= setting on upstream interface.");
else {
r = radv_add_prefix(link, &prefix, 64, lifetime_preferred_usec, lifetime_valid_usec); r = radv_add_prefix(link, &prefix, 64, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, return log_link_warning_errno(link, r,
"Failed to assign/update prefix %s to IPv6 Router Advertisement: %m", "Failed to assign/update prefix %s to IPv6 Router Advertisement: %m",
strna(buf)); strna(buf));
} }
r = dhcp_pd_request_route(link, &prefix, 64, lifetime_valid_usec);
if (r < 0)
return log_link_warning_errno(link, r,
"Failed to assign/update route for prefix %s: %m",
strna(buf));
r = dhcp_pd_request_address(link, &prefix, 64, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0)
return log_link_warning_errno(link, r,
"Failed to assign/update address for prefix %s: %m",
strna(buf));
r = link_add_dhcp_pd_subnet_prefix(link, &prefix);
if (r < 0)
return log_link_warning_errno(link, r,
"Failed to save assigned prefix %s: %m",
strna(buf));
log_link_debug(link, "Assigned prefix %s", strna(buf));
return 1;
} }
static int dhcp_pd_assign_prefix_on_uplink( r = dhcp_pd_request_route(link, &prefix, lifetime_valid_usec);
Link *link,
const struct in6_addr *pd_prefix,
uint8_t pd_prefix_len,
usec_t lifetime_preferred_usec,
usec_t lifetime_valid_usec) {
_cleanup_free_ char *buf = NULL;
int r;
assert(link);
assert(link->network);
assert(pd_prefix);
(void) in6_addr_prefix_to_string(pd_prefix, pd_prefix_len, &buf);
if (link->network->dhcp_pd_announce)
log_link_debug(link, "Ignoring Announce= setting on upstream interface.");
r = dhcp_pd_request_route(link, pd_prefix, pd_prefix_len, lifetime_valid_usec);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, return log_link_warning_errno(link, r,
"Failed to assign/update route for prefix %s: %m", "Failed to assign/update route for prefix %s: %m",
strna(buf)); strna(buf));
r = dhcp_pd_request_address(link, pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); r = dhcp_pd_request_address(link, &prefix, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, return log_link_warning_errno(link, r,
"Failed to assign/update address for prefix %s: %m", "Failed to assign/update address for prefix %s: %m",
@ -954,18 +914,14 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) {
return r; return r;
if (streq_ptr(uplink->dhcp4_6rd_tunnel_name, link->ifname)) { if (streq_ptr(uplink->dhcp4_6rd_tunnel_name, link->ifname)) {
r = dhcp_pd_assign_prefix_on_uplink(link, &pd_prefix, pd_prefixlen, lifetime_usec, lifetime_usec);
if (r < 0)
return r;
r = dhcp4_pd_request_default_gateway_on_6rd_tunnel(link, &br_addresses[0], lifetime_usec); r = dhcp4_pd_request_default_gateway_on_6rd_tunnel(link, &br_addresses[0], lifetime_usec);
if (r < 0) if (r < 0)
return r; return r;
} else { }
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefixlen, lifetime_usec, lifetime_usec);
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefixlen, lifetime_usec, lifetime_usec, /* is_uplink = */ false);
if (r < 0) if (r < 0)
return r; return r;
}
return dhcp_pd_finalize(link); return dhcp_pd_finalize(link);
} }
@ -1127,10 +1083,9 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec); lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec); lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
if (link == uplink) r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len,
r = dhcp_pd_assign_prefix_on_uplink(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec); lifetime_preferred_usec, lifetime_valid_usec,
else /* is_uplink = */ link == uplink);
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
if (r < 0) if (r < 0)
return r; return r;
} }

View File

@ -5,6 +5,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "cgroup-setup.h" #include "cgroup-setup.h"
#include "cgroup-util.h" #include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "oomd-util.h" #include "oomd-util.h"
@ -13,6 +14,7 @@
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "tests.h" #include "tests.h"
#include "tmpfile-util.h"
static int fork_and_sleep(unsigned sleep_min) { static int fork_and_sleep(unsigned sleep_min) {
usec_t n, timeout, ts; usec_t n, timeout, ts;
@ -244,12 +246,13 @@ static void test_oomd_update_cgroup_contexts_between_hashmaps(void) {
static void test_oomd_system_context_acquire(void) { static void test_oomd_system_context_acquire(void) {
_cleanup_(unlink_tempfilep) char path[] = "/oomdgetsysctxtestXXXXXX"; _cleanup_(unlink_tempfilep) char path[] = "/oomdgetsysctxtestXXXXXX";
_cleanup_close_ int fd = -1;
OomdSystemContext ctx; OomdSystemContext ctx;
if (geteuid() != 0) if (geteuid() != 0)
return (void) log_tests_skipped("not root"); return (void) log_tests_skipped("not root");
assert_se(mkstemp(path)); assert_se((fd = mkostemp_safe(path)) >= 0);
assert_se(oomd_system_context_acquire("/verylikelynonexistentpath", &ctx) == -ENOENT); assert_se(oomd_system_context_acquire("/verylikelynonexistentpath", &ctx) == -ENOENT);
@ -283,7 +286,7 @@ static void test_oomd_system_context_acquire(void) {
static void test_oomd_pressure_above(void) { static void test_oomd_pressure_above(void) {
_cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL; _cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL;
_cleanup_set_free_ Set *t1 = NULL, *t2 = NULL, *t3 = NULL; _cleanup_set_free_ Set *t1 = NULL, *t2 = NULL, *t3 = NULL;
OomdCGroupContext ctx[2], *c; OomdCGroupContext ctx[2] = {}, *c;
loadavg_t threshold; loadavg_t threshold;
assert_se(store_loadavg_fixed_point(80, 0, &threshold) == 0); assert_se(store_loadavg_fixed_point(80, 0, &threshold) == 0);
@ -300,12 +303,11 @@ static void test_oomd_pressure_above(void) {
assert_se(store_loadavg_fixed_point(1, 11, &(ctx[1].memory_pressure.avg300)) == 0); assert_se(store_loadavg_fixed_point(1, 11, &(ctx[1].memory_pressure.avg300)) == 0);
ctx[1].mem_pressure_limit = threshold; ctx[1].mem_pressure_limit = threshold;
/* High memory pressure */ /* High memory pressure */
assert_se(h1 = hashmap_new(&string_hash_ops)); assert_se(h1 = hashmap_new(&string_hash_ops));
assert_se(hashmap_put(h1, "/herp.slice", &ctx[0]) >= 0); assert_se(hashmap_put(h1, "/herp.slice", &ctx[0]) >= 0);
assert_se(oomd_pressure_above(h1, 0 /* duration */, &t1) == 1); assert_se(oomd_pressure_above(h1, 0 /* duration */, &t1) == 1);
assert_se(set_contains(t1, &ctx[0]) == true); assert_se(set_contains(t1, &ctx[0]));
assert_se(c = hashmap_get(h1, "/herp.slice")); assert_se(c = hashmap_get(h1, "/herp.slice"));
assert_se(c->mem_pressure_limit_hit_start > 0); assert_se(c->mem_pressure_limit_hit_start > 0);
@ -313,14 +315,14 @@ static void test_oomd_pressure_above(void) {
assert_se(h2 = hashmap_new(&string_hash_ops)); assert_se(h2 = hashmap_new(&string_hash_ops));
assert_se(hashmap_put(h2, "/derp.slice", &ctx[1]) >= 0); assert_se(hashmap_put(h2, "/derp.slice", &ctx[1]) >= 0);
assert_se(oomd_pressure_above(h2, 0 /* duration */, &t2) == 0); assert_se(oomd_pressure_above(h2, 0 /* duration */, &t2) == 0);
assert_se(t2 == NULL); assert_se(!t2);
assert_se(c = hashmap_get(h2, "/derp.slice")); assert_se(c = hashmap_get(h2, "/derp.slice"));
assert_se(c->mem_pressure_limit_hit_start == 0); assert_se(c->mem_pressure_limit_hit_start == 0);
/* High memory pressure w/ multiple cgroups */ /* High memory pressure w/ multiple cgroups */
assert_se(hashmap_put(h1, "/derp.slice", &ctx[1]) >= 0); assert_se(hashmap_put(h1, "/derp.slice", &ctx[1]) >= 0);
assert_se(oomd_pressure_above(h1, 0 /* duration */, &t3) == 1); assert_se(oomd_pressure_above(h1, 0 /* duration */, &t3) == 1);
assert_se(set_contains(t3, &ctx[0]) == true); assert_se(set_contains(t3, &ctx[0]));
assert_se(set_size(t3) == 1); assert_se(set_size(t3) == 1);
assert_se(c = hashmap_get(h1, "/herp.slice")); assert_se(c = hashmap_get(h1, "/herp.slice"));
assert_se(c->mem_pressure_limit_hit_start > 0); assert_se(c->mem_pressure_limit_hit_start > 0);

View File

@ -9,6 +9,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "log.h" #include "log.h"
#include "path-util.h" #include "path-util.h"
#include "string-util.h" #include "string-util.h"
@ -18,7 +19,10 @@
static int watchdog_fd = -1; static int watchdog_fd = -1;
static char *watchdog_device; static char *watchdog_device;
static usec_t watchdog_timeout; /* 0 → close device and USEC_INFINITY → don't change timeout */ static usec_t watchdog_timeout; /* 0 → close device and USEC_INFINITY → don't change timeout */
static usec_t watchdog_pretimeout; /* 0 → disable pretimeout and USEC_INFINITY → don't change pretimeout */
static usec_t watchdog_last_ping = USEC_INFINITY; static usec_t watchdog_last_ping = USEC_INFINITY;
static bool watchdog_supports_pretimeout = false; /* Depends on kernel state that might change at runtime */
static char *watchdog_pretimeout_governor = NULL;
/* Starting from kernel version 4.5, the maximum allowable watchdog timeout is /* Starting from kernel version 4.5, the maximum allowable watchdog timeout is
* UINT_MAX/1000U seconds (since internal calculations are done in milliseconds * UINT_MAX/1000U seconds (since internal calculations are done in milliseconds
@ -29,11 +33,72 @@ static usec_t watchdog_last_ping = USEC_INFINITY;
*/ */
#define WATCHDOG_TIMEOUT_MAX_SEC (CONST_MIN(UINT_MAX/1000U, (unsigned)INT_MAX)) #define WATCHDOG_TIMEOUT_MAX_SEC (CONST_MIN(UINT_MAX/1000U, (unsigned)INT_MAX))
#define WATCHDOG_GOV_NAME_MAXLEN 20 /* From the kernel watchdog driver */
static int saturated_usec_to_sec(usec_t val) { static int saturated_usec_to_sec(usec_t val) {
usec_t t = DIV_ROUND_UP(val, USEC_PER_SEC); usec_t t = DIV_ROUND_UP(val, USEC_PER_SEC);
return MIN(t, (usec_t) WATCHDOG_TIMEOUT_MAX_SEC); /* Saturate to watchdog max */ return MIN(t, (usec_t) WATCHDOG_TIMEOUT_MAX_SEC); /* Saturate to watchdog max */
} }
static int get_watchdog_sysfs_path(const char *filename, char **ret_path) {
struct stat st;
if (watchdog_fd < 0)
return -EBADF;
if (fstat(watchdog_fd, &st))
return -errno;
if (!S_ISCHR(st.st_mode))
return -EBADF;
if (asprintf(ret_path, "/sys/dev/char/%d:%d/%s", major(st.st_rdev), minor(st.st_rdev), filename) < 0)
return -ENOMEM;
return 0;
}
static int get_pretimeout_governor(char **ret_gov) {
_cleanup_free_ char *sys_fn = NULL;
int r;
r = get_watchdog_sysfs_path("pretimeout_governor", &sys_fn);
if (r < 0)
return r;
log_info("Watchdog: reading from %s", sys_fn);
r = read_virtual_file(sys_fn, WATCHDOG_GOV_NAME_MAXLEN - 1, ret_gov, NULL);
if (r < 0)
return r;
delete_trailing_chars(*ret_gov, WHITESPACE);
return 0;
}
static int set_pretimeout_governor(const char *governor) {
_cleanup_free_ char *sys_fn = NULL;
int r;
if (isempty(governor))
return 0; /* Nothing to do */
r = get_watchdog_sysfs_path("pretimeout_governor", &sys_fn);
if (r < 0)
return r;
log_info("Watchdog: setting pretimeout_governor to '%s' via '%s'", governor, sys_fn);
r = write_string_file(sys_fn,
governor,
WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
if (r < 0)
return log_error_errno(r, "Failed to set pretimeout_governor to '%s': %m", governor);
return r;
}
static int watchdog_set_enable(bool enable) { static int watchdog_set_enable(bool enable) {
int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD; int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
@ -84,6 +149,46 @@ static int watchdog_set_timeout(void) {
return 0; return 0;
} }
static int watchdog_get_pretimeout(void) {
int sec = 0;
assert(watchdog_fd >= 0);
if (ioctl(watchdog_fd, WDIOC_GETPRETIMEOUT, &sec) < 0) {
watchdog_pretimeout = 0;
return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get pretimeout value, ignoring: %m");
}
watchdog_pretimeout = sec * USEC_PER_SEC;
return 0;
}
static int watchdog_set_pretimeout(void) {
int sec;
assert(watchdog_fd >= 0);
assert(watchdog_pretimeout != USEC_INFINITY);
sec = saturated_usec_to_sec(watchdog_pretimeout);
if (ioctl(watchdog_fd, WDIOC_SETPRETIMEOUT, &sec) < 0) {
watchdog_pretimeout = 0;
if (ERRNO_IS_NOT_SUPPORTED(errno)) {
log_info("Watchdog does not support pretimeouts.");
return 0;
}
return log_error_errno(errno, "Failed to set pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
}
/* The set ioctl does not return the actual value set so get it now. */
(void) watchdog_get_pretimeout();
return 0;
}
static int watchdog_ping_now(void) { static int watchdog_ping_now(void) {
assert(watchdog_fd >= 0); assert(watchdog_fd >= 0);
@ -95,6 +200,60 @@ static int watchdog_ping_now(void) {
return 0; return 0;
} }
static int update_pretimeout(void) {
_cleanup_free_ char *governor = NULL;
int r, t_sec, pt_sec;
if (watchdog_fd < 0)
return 0;
if (watchdog_timeout == USEC_INFINITY || watchdog_pretimeout == USEC_INFINITY)
return 0;
if (!watchdog_supports_pretimeout && watchdog_pretimeout == 0)
return 0; /* Nothing to do */
/* The configuration changed, do not assume it can still work, as the module(s)
* might have been unloaded. */
watchdog_supports_pretimeout = false;
/* Update the pretimeout governor as well */
(void) set_pretimeout_governor(watchdog_pretimeout_governor);
r = get_pretimeout_governor(&governor);
if (r < 0)
return log_warning_errno(r, "Watchdog: failed to read pretimeout governor: %m");
if (isempty(governor))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"Watchdog: no pretimeout governor detected - is the required kernel module loaded?");
/* If we have a pretimeout governor, then pretimeout is supported. Without a governor
* pretimeout does not work at all.
* Note that this might require a kernel module that is not autoloaded, so we don't
* cache this, but we check everytime the configuration changes. */
watchdog_supports_pretimeout = true;
/* Determine if the pretimeout is valid for the current watchdog timeout. */
t_sec = saturated_usec_to_sec(watchdog_timeout);
pt_sec = saturated_usec_to_sec(watchdog_pretimeout);
if (pt_sec >= t_sec) {
r = log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Cannot set watchdog pretimeout to %is (%s watchdog timeout of %is)",
pt_sec, pt_sec == t_sec ? "same as" : "longer than", t_sec);
(void) watchdog_get_pretimeout();
} else
r = watchdog_set_pretimeout();
if (watchdog_pretimeout == 0)
log_info("Watchdog pretimeout is disabled.");
else
log_info("Watchdog running with a pretimeout of %s with governor '%s'.",
FORMAT_TIMESPAN(watchdog_pretimeout, 0),
governor);
return r;
}
static int update_timeout(void) { static int update_timeout(void) {
int r; int r;
@ -121,6 +280,12 @@ static int update_timeout(void) {
return log_error_errno(r, "Failed to query watchdog HW timeout: %m"); return log_error_errno(r, "Failed to query watchdog HW timeout: %m");
} }
/* If the watchdog timeout was changed, the pretimeout could have been
* changed as well by the driver or the kernel so we need to update the
* pretimeout now. Or if the watchdog is being configured for the first
* time, we want to configure the pretimeout before it is enabled. */
(void) update_pretimeout();
r = watchdog_set_enable(true); r = watchdog_set_enable(true);
if (r < 0) if (r < 0)
return r; return r;
@ -210,9 +375,38 @@ int watchdog_setup(usec_t timeout) {
return r; return r;
} }
usec_t watchdog_runtime_wait(void) { int watchdog_setup_pretimeout(usec_t timeout) {
/* timeout=0 disables the pretimeout whereas timeout=USEC_INFINITY is a nop. */
if ((watchdog_fd >= 0 && timeout == watchdog_pretimeout) || timeout == USEC_INFINITY)
return 0;
if (!timestamp_is_set(watchdog_timeout)) /* Initialize the watchdog timeout with the caller value. This value is
* going to be updated by update_pretimeout() with the running value,
* even if it fails to update the timeout. */
watchdog_pretimeout = timeout;
return update_pretimeout();
}
int watchdog_setup_pretimeout_governor(const char *governor) {
if (free_and_strdup(&watchdog_pretimeout_governor, governor) < 0)
return -ENOMEM;
return set_pretimeout_governor(watchdog_pretimeout_governor);
}
static usec_t calc_timeout(void) {
/* Calculate the effective timeout which accounts for the watchdog
* pretimeout if configured and supported. */
if (watchdog_supports_pretimeout && timestamp_is_set(watchdog_pretimeout) && watchdog_timeout >= watchdog_pretimeout)
return watchdog_timeout - watchdog_pretimeout;
else
return watchdog_timeout;
}
usec_t watchdog_runtime_wait(void) {
usec_t timeout = calc_timeout();
if (!timestamp_is_set(timeout))
return USEC_INFINITY; return USEC_INFINITY;
/* Sleep half the watchdog timeout since the last successful ping at most */ /* Sleep half the watchdog timeout since the last successful ping at most */
@ -220,14 +414,14 @@ usec_t watchdog_runtime_wait(void) {
usec_t ntime = now(clock_boottime_or_monotonic()); usec_t ntime = now(clock_boottime_or_monotonic());
assert(ntime >= watchdog_last_ping); assert(ntime >= watchdog_last_ping);
return usec_sub_unsigned(watchdog_last_ping + (watchdog_timeout / 2), ntime); return usec_sub_unsigned(watchdog_last_ping + (timeout / 2), ntime);
} }
return watchdog_timeout / 2; return timeout / 2;
} }
int watchdog_ping(void) { int watchdog_ping(void) {
usec_t ntime; usec_t ntime, timeout;
if (watchdog_timeout == 0) if (watchdog_timeout == 0)
return 0; return 0;
@ -237,12 +431,13 @@ int watchdog_ping(void) {
return open_watchdog(); return open_watchdog();
ntime = now(clock_boottime_or_monotonic()); ntime = now(clock_boottime_or_monotonic());
timeout = calc_timeout();
/* Never ping earlier than watchdog_timeout/4 and try to ping /* Never ping earlier than watchdog_timeout/4 and try to ping
* by watchdog_timeout/2 plus scheduling latencies the latest */ * by watchdog_timeout/2 plus scheduling latencies at the latest */
if (timestamp_is_set(watchdog_last_ping)) { if (timestamp_is_set(watchdog_last_ping)) {
assert(ntime >= watchdog_last_ping); assert(ntime >= watchdog_last_ping);
if ((ntime - watchdog_last_ping) < (watchdog_timeout / 4)) if ((ntime - watchdog_last_ping) < (timeout / 4))
return 0; return 0;
} }

View File

@ -8,6 +8,8 @@
int watchdog_set_device(const char *path); int watchdog_set_device(const char *path);
int watchdog_setup(usec_t timeout); int watchdog_setup(usec_t timeout);
int watchdog_setup_pretimeout(usec_t usec);
int watchdog_setup_pretimeout_governor(const char *governor);
int watchdog_ping(void); int watchdog_ping(void);
void watchdog_close(bool disarm); void watchdog_close(bool disarm);
usec_t watchdog_runtime_wait(void); usec_t watchdog_runtime_wait(void);

View File

@ -29,10 +29,11 @@ static const char *arg_test_dir = NULL;
TEST(chase_symlinks) { TEST(chase_symlinks) {
_cleanup_free_ char *result = NULL; _cleanup_free_ char *result = NULL;
_cleanup_close_ int pfd = -1;
char *temp; char *temp;
const char *top, *p, *pslash, *q, *qslash; const char *top, *p, *pslash, *q, *qslash;
struct stat st; struct stat st;
int r, pfd; int r;
temp = strjoina(arg_test_dir ?: "/tmp", "/test-chase.XXXXXX"); temp = strjoina(arg_test_dir ?: "/tmp", "/test-chase.XXXXXX");
assert_se(mkdtemp(temp)); assert_se(mkdtemp(temp));
@ -318,6 +319,7 @@ TEST(chase_symlinks) {
assert_se(fstat(pfd, &st) >= 0); assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
result = mfree(result); result = mfree(result);
pfd = safe_close(pfd);
/* s1 -> s2 -> nonexistent */ /* s1 -> s2 -> nonexistent */
q = strjoina(temp, "/s1"); q = strjoina(temp, "/s1");
@ -331,6 +333,7 @@ TEST(chase_symlinks) {
assert_se(fstat(pfd, &st) >= 0); assert_se(fstat(pfd, &st) >= 0);
assert_se(S_ISLNK(st.st_mode)); assert_se(S_ISLNK(st.st_mode));
result = mfree(result); result = mfree(result);
pfd = safe_close(pfd);
/* Test CHASE_STEP */ /* Test CHASE_STEP */

View File

@ -1,20 +1,23 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "parse-util.h" #include "parse-util.h"
#include "psi-util.h" #include "psi-util.h"
#include "tests.h" #include "tests.h"
#include "tmpfile-util.h"
TEST(read_mem_pressure) { TEST(read_mem_pressure) {
_cleanup_(unlink_tempfilep) char path[] = "/tmp/pressurereadtestXXXXXX"; _cleanup_(unlink_tempfilep) char path[] = "/tmp/pressurereadtestXXXXXX";
_cleanup_close_ int fd = -1;
ResourcePressure rp; ResourcePressure rp;
if (geteuid() != 0) if (geteuid() != 0)
return (void) log_tests_skipped("not root"); return (void) log_tests_skipped("not root");
assert_se(mkstemp(path)); assert_se((fd = mkostemp_safe(path)) >= 0);
assert_se(read_resource_pressure("/verylikelynonexistentpath", PRESSURE_TYPE_SOME, &rp) < 0); assert_se(read_resource_pressure("/verylikelynonexistentpath", PRESSURE_TYPE_SOME, &rp) < 0);
assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0); assert_se(read_resource_pressure(path, PRESSURE_TYPE_SOME, &rp) < 0);

View File

@ -35,7 +35,7 @@ TEST(tmpfiles) {
assert_se(endswith(ans, " (deleted)")); assert_se(endswith(ans, " (deleted)"));
fd2 = mkostemp_safe(pattern); fd2 = mkostemp_safe(pattern);
assert_se(fd >= 0); assert_se(fd2 >= 0);
assert_se(unlink(pattern) == 0); assert_se(unlink(pattern) == 0);
assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd2) > 0); assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd2) > 0);
@ -47,6 +47,7 @@ TEST(tmpfiles) {
pattern = strjoina(p, "/tmpfiles-test"); pattern = strjoina(p, "/tmpfiles-test");
assert_se(tempfn_random(pattern, NULL, &d) >= 0); assert_se(tempfn_random(pattern, NULL, &d) >= 0);
fd = safe_close(fd);
fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp); fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp);
assert_se(fd >= 0); assert_se(fd >= 0);
assert_se(write(fd, "foobar\n", 7) == 7); assert_se(write(fd, "foobar\n", 7) == 7);

View File

@ -737,6 +737,8 @@ LogLevel=
LogLocation= LogLocation=
LogTarget= LogTarget=
RuntimeWatchdogSec= RuntimeWatchdogSec=
RuntimeWatchdogPreSec=
RuntimeWatchdogPreGovernor=
ShowStatus= ShowStatus=
RebootWatchdogSec= RebootWatchdogSec=
ShutdownWatchdogSec= ShutdownWatchdogSec=

View File

@ -10,7 +10,7 @@ DHCPPrefixDelegation=yes
[DHCPPrefixDelegation] [DHCPPrefixDelegation]
UplinkInterface=veth99 UplinkInterface=veth99
SubnetId=2 SubnetId=0
Announce=no Announce=no
Token=eui64 Token=eui64
Token=::1a:2b:3c:4d Token=::1a:2b:3c:4d

View File

@ -5269,11 +5269,11 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# Link Subnet IDs # Link Subnet IDs
# test1: 0x00 # test1: 0x00
# dummy97: 0x01 (The link will appear later) # dummy97: 0x01 (The link will appear later)
# dummy98: 0x02 # dummy98: 0x00
# dummy99: auto -> 0x03 (No address assignment) # dummy99: auto -> 0x02 (No address assignment)
# veth97: 0x08 # veth97: 0x08
# veth98: 0x09 # veth98: 0x09
# veth99: 0x10 (ignored, as it is upstream) # veth99: 0x10
print('### ip -6 address show dev veth99 scope global') print('### ip -6 address show dev veth99 scope global')
output = check_output('ip -6 address show dev veth99 scope global') output = check_output('ip -6 address show dev veth99 scope global')
@ -5281,9 +5281,12 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# IA_NA # IA_NA
self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/56 (metric 256 |)scope global dynamic') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic')
# address in IA_PD (Token=eui64) # address in IA_PD (Token=eui64)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1034:56ff:fe78:9abc/56 (metric 256 |)scope global dynamic') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic')
# address in IA_PD (temporary)
# Note that the temporary addresses may appear after the link enters configured state
self.wait_address('veth99', 'inet6 3ffe:501:ffff:[2-9a-f]10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev test1 scope global') print('### ip -6 address show dev test1 scope global')
output = check_output('ip -6 address show dev test1 scope global') output = check_output('ip -6 address show dev test1 scope global')
@ -5291,22 +5294,21 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
# Note that the temporary addresses may appear after the link enters configured state
self.wait_address('test1', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('test1', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy98 scope global') print('### ip -6 address show dev dummy98 scope global')
output = check_output('ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global') print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy99 scope global') output = check_output('ip -6 address show dev dummy99 scope global')
print(output) print(output)
# Assign=no # Assign=no
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03') self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
print('### ip -6 address show dev veth97 scope global') print('### ip -6 address show dev veth97 scope global')
output = check_output('ip -6 address show dev veth97 scope global') output = check_output('ip -6 address show dev veth97 scope global')
@ -5356,7 +5358,7 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 route show dev veth99') print('### ip -6 route show dev veth99')
output = check_output('ip -6 route show dev veth99') output = check_output('ip -6 route show dev veth99')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/56 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]10::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev test1') print('### ip -6 route show dev test1')
output = check_output('ip -6 route show dev test1') output = check_output('ip -6 route show dev test1')
@ -5366,12 +5368,12 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 route show dev dummy98') print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev dummy99') print('### ip -6 route show dev dummy99')
output = check_output('ip -6 route show dev dummy99') output = check_output('ip -6 route show dev dummy99')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
print('### ip -6 route show dev veth97') print('### ip -6 route show dev veth97')
output = check_output('ip -6 route show dev veth97') output = check_output('ip -6 route show dev veth97')
@ -5418,25 +5420,25 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
output = check_output('ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global') print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy99 scope global') output = check_output('ip -6 address show dev dummy99 scope global')
print(output) print(output)
# Assign=no # Assign=no
self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03') self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
print('### ip -6 route show dev dummy98') print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev dummy99') print('### ip -6 route show dev dummy99')
output = check_output('ip -6 route show dev dummy99') output = check_output('ip -6 route show dev dummy99')
print(output) print(output)
self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires') self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
def verify_dhcp4_6rd(self, tunnel_name): def verify_dhcp4_6rd(self, tunnel_name):
print('### ip -4 address show dev veth-peer scope global') print('### ip -4 address show dev veth-peer scope global')
@ -5447,8 +5449,9 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
# Link Subnet IDs # Link Subnet IDs
# test1: 0x00 # test1: 0x00
# dummy97: 0x01 (The link will appear later) # dummy97: 0x01 (The link will appear later)
# dummy98: 0x02 # dummy98: 0x00
# dummy99: auto -> 0x03 (No address assignment) # dummy99: auto -> 0x0[23] (No address assignment)
# 6rd-XXX: auto -> 0x0[23]
# veth97: 0x08 # veth97: 0x08
# veth98: 0x09 # veth98: 0x09
# veth99: 0x10 # veth99: 0x10
@ -5481,15 +5484,15 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
output = check_output('ip -6 address show dev dummy98 scope global') output = check_output('ip -6 address show dev dummy98 scope global')
print(output) print(output)
# address in IA_PD (Token=static) # address in IA_PD (Token=static)
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr') self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
# address in IA_PD (temporary) # address in IA_PD (temporary)
self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+02:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6') self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
print('### ip -6 address show dev dummy99 scope global') print('### ip -6 address show dev dummy99 scope global')
output = check_output('ip -6 address show dev dummy99 scope global') output = check_output('ip -6 address show dev dummy99 scope global')
print(output) print(output)
# Assign=no # Assign=no
self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+03') self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]')
print('### ip -6 address show dev veth97 scope global') print('### ip -6 address show dev veth97 scope global')
output = check_output('ip -6 address show dev veth97 scope global') output = check_output('ip -6 address show dev veth97 scope global')
@ -5549,12 +5552,12 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 route show dev dummy98') print('### ip -6 route show dev dummy98')
output = check_output('ip -6 route show dev dummy98') output = check_output('ip -6 route show dev dummy98')
print(output) print(output)
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+02::/64 proto kernel metric [0-9]* expires') self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires')
print('### ip -6 route show dev dummy99') print('### ip -6 route show dev dummy99')
output = check_output('ip -6 route show dev dummy99') output = check_output('ip -6 route show dev dummy99')
print(output) print(output)
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+03::/64 proto dhcp metric [0-9]* expires') self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto dhcp metric [0-9]* expires')
print('### ip -6 route show dev veth97') print('### ip -6 route show dev veth97')
output = check_output('ip -6 route show dev veth97') output = check_output('ip -6 route show dev veth97')
@ -5601,13 +5604,13 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
print('### ip -6 address show dev {}'.format(tunnel_name)) print('### ip -6 address show dev {}'.format(tunnel_name))
output = check_output('ip -6 address show dev {}'.format(tunnel_name)) output = check_output('ip -6 address show dev {}'.format(tunnel_name))
print(output) print(output)
self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/56 (metric 256 |)scope global dynamic') self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global dynamic')
self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global') self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
print('### ip -6 route show dev {}'.format(tunnel_name)) print('### ip -6 route show dev {}'.format(tunnel_name))
output = check_output('ip -6 route show dev {}'.format(tunnel_name)) output = check_output('ip -6 route show dev {}'.format(tunnel_name))
print(output) print(output)
self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/56 proto kernel metric [0-9]* expires') self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto kernel metric [0-9]* expires')
self.assertRegex(output, '::/96 proto kernel metric [0-9]*') self.assertRegex(output, '::/96 proto kernel metric [0-9]*')
print('### ip -6 route show default') print('### ip -6 route show default')

View File

@ -15,7 +15,7 @@ Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
DefaultDependencies=no DefaultDependencies=no
After=systemd-sysusers.service systemd-networkd.service After=systemd-sysusers.service
Before=network.target nss-lookup.target shutdown.target Before=network.target nss-lookup.target shutdown.target
Conflicts=shutdown.target Conflicts=shutdown.target
Wants=nss-lookup.target Wants=nss-lookup.target

View File

@ -22,4 +22,4 @@ After=swap.target
What=tmpfs What=tmpfs
Where=/tmp Where=/tmp
Type=tmpfs Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=1m Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m